Skip to content

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

  1. A Snyk Open Source finding lands — either by manual snyk test pass or, in the future, by CI. The finding is either fixed by an upgrade pin or formally deferred in .snyk.
  2. A platform/runtime upgrade (Node, Python, framework majors). These are scheduled, not opportunistic.
  3. 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.
  4. An annual .snyk expiry sweep. Every entry has an expires: 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, ISC are routine; copyleft (GPL family) requires founder review.
  • Include a Snyk pass for the affected manifest, either by running snyk test --policy-path=.snyk locally 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:

scripts/refresh.sh --clean

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:

  1. Re-runs snyk test --all-projects --policy-path=.snyk against the current manifests.
  2. For each existing deferral, decides one of: still applicable (extend expires: by one year, update reason: 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.
  3. 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 .snyk policy 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 CIsnyk test --all-projects --policy-path=.snyk on every PR; block merges that introduce a new high-severity CVE without a .snyk entry. 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 main build.
  • License gate (e.g., license-checker for npm, pip-licenses for Python) running in CI.