Dependency Management¶
Statement¶
ClaimGuard treats third-party dependencies as part of its attack surface
and manages them through three controls in combination: a versioned
deferral policy (.snyk) with annual expiry, documented
load-bearing pin floors in the engineering README, and a
reproducible local rebuild path (scripts/refresh.sh --clean) that
forces fresh dependency resolution. Together they ensure that an
upgrade either lands cleanly across all environments or is caught
before merge.
This page describes the process: when we update, who reviews, how a new dependency is added, and how deferrals are renewed. The dependency inventory (what tooling, which manifests, the current pin floors) lives on the SCA page.
Implementation¶
When dependencies change¶
- A Snyk Open Source finding lands — either by manual
snyk testpass or, in the future, by CI. The finding is either fixed by an upgrade pin or formally deferred in.snyk. - A platform/runtime upgrade (Node, Python, framework majors). These are scheduled, not opportunistic.
- A new feature requires a new package. Any new direct dependency must be added to the appropriate manifest and is reviewed at PR time for license, maintenance status, and known CVEs.
- An annual
.snykexpiry sweep. Every entry has anexpires:field set one year out from creation. The next scheduled sweep is 2027-04-22.
There is no "auto-merge minor bumps" workflow today. Every upgrade is a deliberate human decision recorded in a PR.
Pin floors as invariants¶
Some dependency constraints are not just current versions — they are
documented invariants that close specific CVEs. They live in
docs/security/README.md under "Dependency pins" and a PR that drops a
pin below its floor fails review. The current floors are listed on the
SCA page.
Adding a new dependency¶
The PR that introduces a new direct dependency is expected to:
- Pin to a specific minimum version (no floating
latest). - Justify the choice in the PR description if the package is not already in widespread use in the JS or Python ecosystem.
- Note the license —
MIT,BSD-2/3,Apache-2.0,ISCare routine; copyleft (GPL family) requires founder review. - Include a Snyk pass for the affected manifest, either by running
snyk test --policy-path=.snyklocally or by waiting for CI once it is wired (roadmap).
Refreshing the local environment¶
scripts/refresh.sh rebuilds the running stack after a git pull. The
--clean variant additionally wipes node_modules and Python venvs,
forcing fresh dependency resolution from manifests:
This is the path engineers use to verify that a manifest change resolves cleanly on a fresh machine — important because npm and pip both have ways to silently use stale cached resolutions when only the lockfile is touched.
Deferring a finding¶
When Snyk flags a CVE that we choose not to fix in source — most often
because the finding is a scanner false positive against an already-fixed
direct pin, or because the vulnerable code path is provably non-reachable
in our usage — the entry goes in the root .snyk file with three
required fields:
- reason: what specifically dispositions the finding. The categories used today are listed on the SCA page.
- created: the date the deferral was decided.
- expires: one year out from
created, forcing annual re-review.
A PR that adds, modifies, or removes a .snyk entry must explain the
change. "Silently strip" is not an acceptable disposition.
Annual deferral renewal¶
When the expiry date approaches, the renewal pass:
- Re-runs
snyk test --all-projects --policy-path=.snykagainst the current manifests. - For each existing deferral, decides one of: still applicable (extend
expires:by one year, updatereason:if the rationale shifted), no longer applicable (the upstream vendor shipped a fix — bump the pin, delete the entry), or a new finding requiring its own decision. - Lands the renewal pass as a single PR with the same shape as any other dependency change.
Next renewal: 2027-04-22.
Selective .gitignore edge case¶
tools/ai_detect_baseline/requirements.txt is the only file in that
directory that git tracks (via a ! negation in .gitignore). 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
manifest file silently breaks the un-ignore — keep it where it is. This
is also called out on the SCA page.
Ownership¶
All dependency upgrades are reviewed by the founder pair. There is no named "dependency owner" sub-team because the team is too small for one to make sense. As the team grows, a named owner (or a Renovate-style automated bumper feeding into the same PR review) is the natural next step.
Status¶
implemented — verified 2026-04-29.
What's in place:
- A versioned
.snykpolicy file with annual expiry on every deferral. - Documented load-bearing pin floors in
docs/security/README.md. - A documented local refresh path (
scripts/refresh.sh --clean) that forces fresh manifest resolution. - A new-dependency review pattern at PR time.
- A scheduled annual renewal sweep (next: 2027-04-22).
Known gaps¶
- No continuous Snyk in CI. Today Snyk runs are operator-driven, not gating on PRs. A finding introduced by a new dependency is caught at the next manual scan, not at merge time. This is the largest gap on this page.
- No automated upgrade proposals (Renovate / Dependabot). Bumps are initiated by a person, not by a bot.
- No SBOM publication. A CycloneDX SBOM artifact per release would let downstream consumers track our dependency posture without our intermediation.
- No license-policy enforcement. Licenses are reviewed at PR time by inspection; there is no automated "block on copyleft" gate.
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. Cross-listed on SCA and Secure SDLC. - Renovate or Dependabot for proposal generation, gated by the same PR review and CI as a human-authored bump.
- CycloneDX SBOM generation on each
mainbuild. - License gate (e.g.,
license-checkerfor npm,pip-licensesfor Python) running in CI.