🏔 Love Freedom - ❌ Block Mass Surveillance
This report summarizes scanner evidence for safing/portmaster, a Go project with 14,010 GitHub stars. SynthScan examined 234,344 lines of code across 1608 source files, recording 297 pattern matches distributed across 12 syntactic categories. The legacy adjusted pattern signal is 2.0 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 273 finding(s).
Are imports declared and package/API names verified? 4 finding(s).
Are wrappers, guards, and repeated structures necessary? 24 finding(s).
Which changes need focused human review? 297 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 297 distinct pattern matches across 12 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | windows_kext/driver/src/connection_map.rs | 121 | /// It must not inherit the old verdict or the old owner's process id. | COMMENT |
| LOW | windows_kext/driver/src/device.rs | 301 | // "Packet cache: {} entries", | COMMENT |
| LOW | windows_kext/driver/src/lib.rs | 41 | #[panic_handler] | COMMENT |
| LOW | windows_kext/driver/src/packet_util.rs | 61 | /// Redirects an outbound packet to a specified remote address and port. | COMMENT |
| LOW | windows_kext/driver/src/packet_util.rs | 141 | COMMENT | |
| LOW | windows_kext/driver/src/packet_util.rs | 381 | // Converts a given key into connection information. | COMMENT |
| LOW | windows_kext/driver/src/packet_util.rs | 401 | // process_id: u64, | COMMENT |
| LOW | windows_kext/driver/src/packet_util.rs | 421 | // payload, | COMMENT |
| LOW | windows_kext/driver/src/callouts.rs | 61 | // ale_callouts::ale_resource_monitor, | COMMENT |
| LOW | windows_kext/wdk/src/error.rs | 1 | // use anyhow::anyhow; | COMMENT |
| LOW | windows_kext/c_helper/helper.c | 1 | COMMENT | |
| LOW | cmds/observation-hub/apprise.go | 181 | COMMENT | |
| LOW | cmds/observation-hub/apprise.go | 241 | } | COMMENT |
| LOW | cmds/observation-hub/apprise.go | 261 | COMMENT | |
| LOW | cmds/portmaster-core/main_windows.go | 21 | // Ensure the service ImagePath in the registry is properly quoted (CWE-428). | COMMENT |
| LOW | cmds/updatemgr/build.sh | 1 | #!/bin/bash | COMMENT |
| LOW | desktop/tauri/src-tauri/Cargo.toml | 81 | # this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is d | COMMENT |
| LOW | desktop/tauri/src-tauri/Cargo.toml | 101 | # https://github.com/tauri-apps/tao/pull/1334 | COMMENT |
| LOW | desktop/tauri/src-tauri/src/windows_tao_patch.rs | 1 | //! Windows-only: guard for the patched `tao` dependency, plus a debug-only | COMMENT |
| LOW | desktop/tauri/src-tauri/src/windows_tao_patch.rs | 21 | //! normal use needs hours or days to hit it. | COMMENT |
| LOW | desktop/tauri/src-tauri/src/windows_tao_patch.rs | 41 | //! `tao::PORTMASTER_PATCH_LEVEL`. Only the count becomes atomic; the runner | COMMENT |
| LOW | desktop/tauri/src-tauri/src/windows_tao_patch.rs | 61 | //! flag because the CLI parser in `cli.rs` skips unknown flags. The flag is | COMMENT |
| LOW | desktop/tauri/src-tauri/src/window.rs | 161 | /// | COMMENT |
| LOW | desktop/tauri/src-tauri/src/window.rs | 201 | /// Opens a window for the tauri application. | COMMENT |
| LOW | …ktop/tauri/src-tauri/src/linux_graphics_workarounds.rs | 1 | //! Linux-only graphics workarounds, applied at the start of `main()` before | COMMENT |
| LOW | …ktop/tauri/src-tauri/src/linux_graphics_workarounds.rs | 21 | //! Reference: <https://v2.tauri.app/develop/debug/linux-graphics/>. | COMMENT |
| LOW | …ktop/tauri/src-tauri/src/linux_graphics_workarounds.rs | 41 | //! in `is_wayland_session()`. | COMMENT |
| LOW | desktop/tauri/src-tauri/src/main.rs | 181 | } | COMMENT |
| LOW | desktop/tauri/src-tauri/src/portmaster/mod.rs | 1 | /// This module contains a custom tauri plugin that handles all communication | COMMENT |
| LOW | …rojects/safing/portmaster-api/src/lib/network.types.ts | 101 | Port: number; | COMMENT |
| LOW | …rojects/safing/portmaster-api/src/lib/network.types.ts | 261 | // TunnelContext holds additional data about the SPN tunnel used for | COMMENT |
| LOW | …rojects/safing/portmaster-api/src/lib/network.types.ts | 281 | LocalIPScope: IPScope; | COMMENT |
| LOW | …rojects/safing/portmaster-api/src/lib/network.types.ts | 301 | // VerdictPermanent is set to true if the connection was marked and | COMMENT |
| LOW | …projects/safing/portmaster-api/src/lib/config.types.ts | 221 | Key: string; | COMMENT |
| LOW | desktop/angular/src/app/pages/app-view/app-view.ts | 541 | this.highlightSettingKey = queryMap.get('setting'); | COMMENT |
| LOW | desktop/angular/src/app/services/notifications.types.ts | 141 | COMMENT | |
| LOW | desktop/angular/src/app/services/notifications.types.ts | 161 | Invalid = "invalid", | COMMENT |
| LOW | desktop/angular/src/app/services/notifications.types.ts | 181 | // markdown. | COMMENT |
| LOW | desktop/angular/src/i18n/helptexts.yaml | 201 | # How to use? In App settings, search for "Default Action" | COMMENT |
| LOW | desktop/angular/src/i18n/helptexts.yaml | 241 | COMMENT | |
| LOW | spn/ships/ship.go | 41 | // LoadSize returns the recommended data size that should be handed to Load(). | COMMENT |
| LOW | spn/unit/doc.go | 1 | // Package unit provides a "work unit" scheduling system for handling data sets that traverse multiple workers / gorouti | COMMENT |
| LOW | spn/unit/scheduler.go | 81 | type SchedulerConfig struct { | COMMENT |
| LOW | spn/tools/install.sh | 1 | #!/bin/sh | COMMENT |
| LOW | spn/tools/install.v2.sh | 1 | #!/bin/sh | COMMENT |
| LOW | spn/terminal/terminal.go | 41 | // Should not be overridden by implementations. | COMMENT |
| LOW | spn/terminal/operation.go | 41 | COMMENT | |
| LOW | spn/terminal/control_flow.go | 161 | // be ignored. | COMMENT |
| LOW | spn/terminal/testing.go | 221 | // Should not be overridden by implementations. | COMMENT |
| LOW | spn/navigator/optimize.go | 41 | COMMENT | |
| LOW | spn/navigator/state.go | 121 | // OR: | COMMENT |
| LOW | spn/docks/crane.go | 61 | cancelCtx context.CancelFunc | COMMENT |
| LOW | spn/hub/intel.go | 61 | COMMENT | |
| LOW | spn/hub/intel.go | 81 | COMMENT | |
| LOW | spn/hub/hub.go | 101 | // "smtp:587", | COMMENT |
| LOW | service/intel/geoip/country_info_test.go | 41 | } | COMMENT |
| LOW | service/intel/filterlists/index.go | 21 | // Category is used to group different list sources by the type | COMMENT |
| LOW | service/broadcasts/testdata/notifications.yaml | 1 | notifications: | COMMENT |
| LOW | service/interop/ivpn/hook_linux.go | 61 | } | COMMENT |
| LOW | service/interop/ivpn/hook_linux.go | 201 | return 0, fmt.Errorf("no rule entry found in nft output") | COMMENT |
| 132 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | windows_kext/test/BUILD_DEBUG.md | 22 | ## Step 1: Enable Test Signing (One-time Setup) | COMMENT |
| LOW | windows_kext/test/BUILD_DEBUG.md | 60 | ## Step 2: Enable Debug Logging in Driver | COMMENT |
| LOW | windows_kext/test/BUILD_DEBUG.md | 78 | ## Step 3: Build Driver in Release Mode | COMMENT |
| LOW | windows_kext/test/BUILD_DEBUG.md | 93 | ## Step 4: Link the Driver | COMMENT |
| LOW | windows_kext/test/BUILD_DEBUG.md | 111 | ## Step 5: Sign the Driver | COMMENT |
| LOW | windows_kext/test/BUILD_DEBUG.md | 113 | ## Step 5: Sign the Driver | COMMENT |
| LOW | windows_kext/test/BUILD_DEBUG.md | 130 | ## Step 6: View Driver Logs | COMMENT |
| LOW | cmds/observation-hub/observe.go | 119 | // Step 1: Wait for SPN to connect, if needed. | COMMENT |
| LOW | cmds/observation-hub/observe.go | 149 | // Step 2: Get current state. | COMMENT |
| LOW | cmds/observation-hub/observe.go | 185 | // Step 3: Monitor for changes. | COMMENT |
| LOW | spn/access/token/pblind.go | 352 | // Step 1: Process issued tokens. | COMMENT |
| LOW | spn/access/token/pblind.go | 394 | // Step 2: Randomize received tokens | COMMENT |
| LOW | spn/access/token/pblind.go | 407 | // Step 3: Add tokens to storage. | COMMENT |
| LOW⚡ | spn/navigator/state.go | 237 | // Step 1: Check if only one is active. | COMMENT |
| LOW⚡ | spn/navigator/state.go | 246 | // Step 2: Check if only one is reachable. | COMMENT |
| LOW⚡ | spn/navigator/state.go | 255 | // Step 3: Check which one has been seen first. | COMMENT |
| LOW⚡ | spn/patrol/http.go | 60 | // Step 1: Check 1 domain, require 100% | COMMENT |
| LOW⚡ | spn/patrol/http.go | 65 | // Step 2: Check 5 domains, require 80% | COMMENT |
| LOW⚡ | spn/patrol/http.go | 70 | // Step 3: Check 20 domains, require 70% | COMMENT |
| LOW⚡ | service/compat/selfcheck.go | 50 | // Step 0: Check if self-check makes sense. | COMMENT |
| LOW⚡ | service/compat/selfcheck.go | 55 | // Step 1: Check if the system integration sees a packet. | COMMENT |
| LOW | service/compat/selfcheck.go | 90 | // Step 2: Check if a DNS request arrives at the nameserver | COMMENT |
| LOW | service/compat/selfcheck.go | 159 | // Step 3: Have the nameserver respond with random data in the answer section. | COMMENT |
| LOW⚡ | service/network/clean.go | 74 | // Step 0: delete old incomplete connections | COMMENT |
| LOW⚡ | service/network/clean.go | 83 | // Step 1: check if still active | COMMENT |
| LOW | service/network/clean.go | 110 | // Step 2: mark as ended | COMMENT |
| LOW | service/network/clean.go | 127 | // Step 3: delete | COMMENT |
| LOW | service/updates/index_scan.go | 123 | // Step 1: Extract information and check ignores. | COMMENT |
| LOW | service/updates/index_scan.go | 163 | // Step 2: Check and compare file version. | COMMENT |
| LOW | service/updates/index_scan.go | 188 | // Step 3: Create new Artifact. | COMMENT |
| LOW⚡ | service/sync/util.go | 148 | // Step 1: Separate profile icon. | COMMENT |
| LOW⚡ | service/sync/util.go | 154 | // Step 2: Serialize main export. | COMMENT |
| LOW⚡ | service/sync/util.go | 160 | // Step 3: Serialize icon only. | COMMENT |
| LOW⚡ | service/sync/util.go | 166 | // Step 4: Stitch data together and add copyright notice for icon. | COMMENT |
| LOW | service/sync/util.go | 177 | // Step 4: Add checksum. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | desktop/tauri/src-tauri/Cargo.toml | 89 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | desktop/tauri/src-tauri/Cargo.toml | 102 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | service/splittun/proxy/cache.go | 11 | // ─── ConnContext ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/cache.go | 101 | // ─── Metrics ────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/cache.go | 115 | // ─── Session cache ──────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/cache.go | 262 | // ─── Shared helpers ─────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/udp_proxy.go | 162 | // ─── Inbound read loop ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/udp_proxy.go | 303 | // ─── Upstream → client forwarder ───────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/udp_proxy.go | 382 | // ─── Idle cleanup loop ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/udp_proxy.go | 433 | // ─── Error helpers ──────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/common.go | 11 | // ─── Public API types ──────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/common.go | 73 | // ─── Configuration ──────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/tcp_proxy.go | 152 | // ─── accept loop ────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/tcp_proxy.go | 189 | // ─── per-connection handler ─────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/proxy_test.go | 14 | // ─── helpers ────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/proxy_test.go | 86 | // ─── TCP tests ──────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/proxy_test.go | 275 | // ─── UDP tests ──────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/proxy_test.go | 476 | // ─── Misc ───────────────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/bench_test.go | 12 | // ─── TCP benchmarks ─────────────────────────────────────────────────────────── | COMMENT |
| MEDIUM | service/splittun/proxy/bench_test.go | 77 | // ─── UDP benchmarks ─────────────────────────────────────────────────────────── | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL⚡ | spn/unit/unit.go | 72 | u.scheduler.stats.progress.avgUnitLifeCnt.Add(1) | CODE |
| CRITICAL⚡ | spn/unit/unit.go | 73 | if u.scheduler.stats.progress.avgUnitLifeSum.Add(timeTaken) < 0 { | CODE |
| CRITICAL⚡ | spn/unit/unit.go | 75 | u.scheduler.stats.progress.avgUnitLifeCnt.Store(1) | CODE |
| CRITICAL⚡ | spn/unit/unit.go | 76 | u.scheduler.stats.progress.avgUnitLifeSum.Store(timeTaken) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | cmds/observation-hub/observe.go | 119 | // Step 1: Wait for SPN to connect, if needed. | COMMENT |
| LOW | cmds/observation-hub/observe.go | 149 | // Step 2: Get current state. | COMMENT |
| LOW | cmds/observation-hub/observe.go | 185 | // Step 3: Monitor for changes. | COMMENT |
| LOW | spn/access/token/pblind.go | 352 | // Step 1: Process issued tokens. | COMMENT |
| LOW | spn/access/token/pblind.go | 394 | // Step 2: Randomize received tokens | COMMENT |
| LOW | spn/access/token/pblind.go | 407 | // Step 3: Add tokens to storage. | COMMENT |
| LOW⚡ | spn/navigator/state.go | 237 | // Step 1: Check if only one is active. | COMMENT |
| LOW⚡ | spn/navigator/state.go | 246 | // Step 2: Check if only one is reachable. | COMMENT |
| LOW⚡ | spn/navigator/state.go | 255 | // Step 3: Check which one has been seen first. | COMMENT |
| LOW⚡ | spn/patrol/http.go | 60 | // Step 1: Check 1 domain, require 100% | COMMENT |
| LOW⚡ | spn/patrol/http.go | 65 | // Step 2: Check 5 domains, require 80% | COMMENT |
| LOW⚡ | spn/patrol/http.go | 70 | // Step 3: Check 20 domains, require 70% | COMMENT |
| LOW⚡ | service/compat/selfcheck.go | 50 | // Step 0: Check if self-check makes sense. | COMMENT |
| LOW⚡ | service/compat/selfcheck.go | 55 | // Step 1: Check if the system integration sees a packet. | COMMENT |
| LOW | service/compat/selfcheck.go | 90 | // Step 2: Check if a DNS request arrives at the nameserver | COMMENT |
| LOW | service/compat/selfcheck.go | 159 | // Step 3: Have the nameserver respond with random data in the answer section. | COMMENT |
| LOW⚡ | service/network/clean.go | 74 | // Step 0: delete old incomplete connections | COMMENT |
| LOW⚡ | service/network/clean.go | 83 | // Step 1: check if still active | COMMENT |
| LOW | service/network/clean.go | 110 | // Step 2: mark as ended | COMMENT |
| LOW | service/network/clean.go | 127 | // Step 3: delete | COMMENT |
| LOW | service/updates/index_scan.go | 123 | // Step 1: Extract information and check ignores. | COMMENT |
| LOW | service/updates/index_scan.go | 163 | // Step 2: Check and compare file version. | COMMENT |
| LOW | service/updates/index_scan.go | 188 | // Step 3: Create new Artifact. | COMMENT |
| LOW⚡ | service/sync/util.go | 148 | // Step 1: Separate profile icon. | COMMENT |
| LOW⚡ | service/sync/util.go | 154 | // Step 2: Serialize main export. | COMMENT |
| LOW⚡ | service/sync/util.go | 160 | // Step 3: Serialize icon only. | COMMENT |
| LOW⚡ | service/sync/util.go | 166 | // Step 4: Stitch data together and add copyright notice for icon. | COMMENT |
| LOW | service/sync/util.go | 177 | // Step 4: Add checksum. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | desktop/angular/README.md | 72 | ### Code scaffolding | COMMENT |
| MEDIUM | desktop/angular/projects/safing/ui/README.md | 5 | ## Code scaffolding | COMMENT |
| MEDIUM | …sktop/angular/projects/safing/portmaster-api/README.md | 5 | ## Code scaffolding | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | service/resolver/ipinfo.go | 35 | // Domain is the domain as requested by the application. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | service/netenv/environment_default.go | 15 | // TODO: implement using | COMMENT |
| LOW | service/netenv/online-status.go | 414 | // TODO: implement more methods | COMMENT |
| LOW | base/database/storage/fstree/fstree.go | 269 | // TODO: implement MaintainRecordStates | COMMENT |
| LOW | base/database/storage/badger/badger.go | 224 | // TODO: implement MaintainRecordStates | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | desktop/angular/package-lock.json | 18780 | "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", | CODE |
| MEDIUM | service/firewall/packet_handler.go | 396 | // Fast-tracking keeps the UI connection seamless when resuming from paused state. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | cmds/updatemgr/build.sh | 62 | # Check if UPX is installed and compress the binary | COMMENT |
| LOW | spn/tools/container-init.sh | 10 | # Check if data dir is mounted. | COMMENT |
| LOW | spn/testing/simple/run.sh | 33 | # Check if there is an old binary for testing. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …gular/projects/safing/portmaster-api/src/lib/module.ts | 26 | export function HttpClientProviderFactory() { | CODE |
| LOW | desktop/angular/src/app/app.module.ts | 75 | function loadAndSetLocaleInitializer(configService: ConfigService) { | CODE |
| LOW | desktop/angular/src/app/integration/factory.ts | 7 | export function integrationServiceFactory(): IntegrationService { | CODE |
| LOW | desktop/angular/src/app/services/notifications.types.ts | 138 | export function getNotificationTypeString(val: NotificationType): string { | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | desktop/tauri/src-tauri/Cargo.toml | 82 | # If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `bu | COMMENT |