# Source-Sink Flow Analysis Summary **Generated**: 2026-05-28 **Phase**: L3 (SAST — Greppable Fallback) **Target**: Kordant monorepo (web/, browser-ext/) --- ## Scan Overview | Metric | Value | |--------|-------| | Files scanned | 730 | | Candidate files | 218 | | Candidate matches | 1412 | | Draft findings produced | 12 | | Keep (enriched) | 10 | | Drop (enriched) | 2 | ## Candidate Classes Breakdown | Class | Matches | High-Score Examples | Enriched | Kept | Dropped | |-------|---------|---------------------|----------|------|---------| | `raw-sql-query` | 611 | admin.ts, billing.ts, blog.ts (`.query()` calls) | N/A | 0 | 0 | | `path-traversal-file-access` | 638 | blog/[slug].tsx, ext_bench.py, api.js (`.join()`) | 2 | 1 | 1 | | `hidden-control-channel` | 42 | middleware.ts (CORS origin), trpc.ts (auth headers) | 4 | 3 | 1 | | `command-execution` | 55 | test files, benchmarks (subprocess.Popen, exec.Command) | N/A | 0 | 0 | | `dynamic-code-execution` | 12 | honker-bun/raw.exec(), test_sqlite_versions.py | N/A | 0 | 0 | | `secret-literal` | 9 | billing.test.ts, auth routes (password error messages) | N/A | 0 | 0 | | `unsafe-html-or-template` | 17 | blog/[slug].tsx (innerHTML), auth test files | 1 | 1 | 0 | | `ssrf-capable-request` | 10 | billing/return.tsx (fetch), scan.engine.ts (external API) | 1 | 1 | 0 | | `webhook-without-obvious-signature` | 6 | stripe/webhook.ts | 1 | 1 | 0 | | `open-redirect` | 2 | blog/index.tsx, app.tsx | 1 | 1 | 0 | | `weak-token-or-crypto` | 5 | PasswordInput.tsx (Math.random) | 1 | 0 | 1 | | `public-entrypoint` | 5 | extensionRouter procedures | N/A | 0 | 0 | ## Key Filtering Decisions ### Dropped: `raw-sql-query` (611 matches) - **Reason**: False positives — 99%+ are tRPC `.query()` method calls (not raw SQL), not Drizzle `sql<>` tag usage. The tRPC router `.query()` method is a framework method, not a SQL execution sink. - **Exception**: The one real `sql<>` usage in admin.ts:47 was separately assessed as p4-012 (low severity, latent risk). ### Dropped: `command-execution` (55 matches) - **Reason**: All matches are in test files (`test_*.py`, `*_test.go`, `*_spec.rb`) or benchmark scripts. These are development-time subprocess calls, not production attack surface. ### Dropped: `dynamic-code-execution` (12 matches) - **Reason**: All matches are SQLite raw SQL execution methods (`raw.exec()`, `exec()`) in the honker package or test files. These are database operations, not code execution sinks. ### Dropped: `secret-literal` (9 matches) - **Reason**: All matches are test data (`billing.test.ts`, `notification.service.test.ts`) or password validation error messages (`login.tsx`, `signup.tsx` — `"Password is required"` is not a secret). ### Dropped: `path-traversal-file-access` — 1 kept, 1 dropped - **Kept (p4-005)**: `voiceprint/storage.ts` — `userId` not validated before `path.join()`, enabling arbitrary file write - **Dropped**: `blog/[slug].tsx` — false positives from `.join("")` string concatenation (not filesystem path joins) ### Dropped: `weak-token-or-crypto` — 0 kept, 1 dropped - **Dropped**: `PasswordInput.tsx` — `Math.random()` is used for generating HTML input element IDs, not for CSRF tokens or cryptographic purposes. The id is only used for `