SCA — Software Composition Analysis¶
Statement¶
ClaimGuard runs Snyk Open Source as the SCA tool over all package
manifests in the repository (npm and PyPI). Every dependency CVE flagged
by Snyk is either fixed by an upgrade pin or formally deferred in .snyk
with a per-CVE justification and a one-year expiry. The repository
enforces minimum-version pins on the load-bearing security-sensitive
dependencies.
Implementation¶
Tooling¶
- Engine: Snyk Open Source.
- Manifest coverage:
- npm:
package.json(root +server/). - PyPI:
tools/master_tool/requirements.txt,tools/c2pa/requirements.txt,tools/secondary_ai_detector/requirements.txt,tools/ai_detect_baseline/requirements.txt,tools/layover/requirements.txt,tools/dtect_image-0.1.0/requirements.txt,tools/provenance/requirements.txt. - Last full scan: 2026-04-22.
Load-bearing dependency pins¶
Some pins are not just "current versions" — they are documented invariants that close specific CVEs. Future bumps must stay at or above these floors.
| Dependency | Floor | What it closes |
|---|---|---|
undici |
latest minor | safeFetch keystone uses undici.Agent with connect.lookup pinning for DNS-rebinding defense. |
react-router-dom |
^6.30.3 |
Two Open Redirect CVEs and one DOM-XSS CVE in <6.30.x. |
h11 (Python) |
>=0.16.0 |
HTTP request smuggling. Pinned in tools/layover, tools/secondary_ai_detector, tools/ai_detect_baseline. |
urllib3 (Python) |
>=2.6.3 |
Data amplification + resource allocation CVEs. Same three Python tool dirs. |
python-multipart |
>=0.0.26 |
Directory traversal. Same dirs. |
requests |
>=2.33.0 |
Multiple CVEs. Same dirs. |
These floors are documented in docs/security/README.md ("Dependency
pins") and are part of the engineering protocol — a PR that drops a pin
below its floor fails review.
.snyk policy file¶
The root .snyk file lists every Snyk Open Source CVE that was decided
not to fix in source, each with a written reason:
- Scanner false positives.
h11,urllib3,python-multipartare pinned directly in ourrequirements.txtfiles at versions above the CVE thresholds. Snyk's Python resolver does not honor direct overrides of transitive deps against a parent's metadata constraint — it reports the parent's declared floor (e.g.,uvicorn@0.40.0'sh11>=0.8) as if our override were absent. Installed versions in all venvs are verified at the override target. - Upstream SDK transitives.
@base44/sdk > axiosand@base44/sdk > socket.io-client > socket.io-parserhave no released vendor fix; tracked. - Dev-only build-tool transitives. ESLint, Tailwind, Vite, Vitest chains; not in the production bundle.
- Non-reachable vectors. E.g.,
lodashhas no_.templatecall sites in this codebase; the CVE that requires that sink is not reachable.
Every entry has created: and expires: (one year) fields. The next
scheduled renewal pass is 2027-04-22.
CLI usage gotchas¶
- The root
.snykonly applies under--all-projectsif invoked assnyk test --all-projects --policy-path=.snyk. Without an explicit--policy-path, per-sub-project ignores don't propagate. - Output filtering: every CI / analysis job that consumes Snyk JSON must
drop entries with a
displayTargetFilestarting with.claude/to avoid counting findings from local agent worktrees.
Selective .gitignore — tools/ai_detect_baseline/¶
tools/ai_detect_baseline/requirements.txt is the only file in that
directory that git tracks (via a ! negation in .gitignore). This is
intentional: the venv, __pycache__, logs, and .py sources stay
ignored, but the pin manifest is tracked so SCA tooling can read it. A
PR that moves or renames the file breaks the selective un-ignore — keep
it where it is.
Status¶
implemented — verified 2026-04-26.
All 2026-04-22 Snyk Open Source findings disposed; .snyk policy file in
place; load-bearing pins enforced; annual renewal scheduled for
2027-04-22.
Roadmap¶
- Continuous SCA in CI —
snyk test --all-projects --policy-path=.snykon every PR; block merges that introduce a new high-severity CVE without a.snykentry. - SBOM — generate CycloneDX SBOM artifacts on each
mainbuild and publish alongside releases. - Dependency dashboard — surface aggregate counts (deferred vs unpatched vs current) on this page once CI is wired.