Assets: the user's source code and secrets, the integrity of a verification verdict, the host machine running VeriPatch.
Trust boundaries:
- The scanned project's files — attacker-controlled input. A
package.json,package-lock.json, or installed package can be hostile (crafted to exploit the parser, or to run malicious code during install). - OSV.dev's network data — trusted but validated; a malformed or malicious-looking advisory is dropped and counted, never trusted blindly.
- The Docker sandbox — untrusted execution. Anything that runs during
verify(the project's ownnpm ci, build, and test commands) is assumed hostile.
| Vector | Mitigation |
|---|---|
Malicious postinstall in a scanned/bumped dependency |
npm ci --ignore-scripts during the sandboxed install step — the script never executes at all, regardless of the container's network state at that point. |
| Sandbox container itself | Non-root user (1000:1000), --cap-drop=ALL, --security-opt=no-new-privileges, pid/memory/cpu limits, --rm on teardown. Bind-mounts a staged copy of the project (adapters/sandbox/copy.ts), excluding node_modules, .git, and any .env* file — the container never touches the original working tree or secrets. |
| Sandbox network | Two phases: a dedicated per-run bridge network during install, then fully disconnected before build/test. This constrains which network the container is attached to, not which domains it can reach — see the residual risk below. |
Hostile package.json / lockfiles (npm, yarn, pnpm) |
Size-capped before parsing (50MB default), JSON.parse/YAML/strict-grammar parsers only (never eval), recursive __proto__/constructor/prototype stripping so no later object spread can pollute a prototype, package names validated against the real npm name grammar. yarn classic is parsed by a deliberately rigid grammar — anything outside it is a hard error, never a guess. |
| Poisoned advisory data | HTTPS with certificate validation; every advisory is zod-validated at the OSV adapter boundary; the rule engine's same-package invariant means a "fix" can only ever be a version bump of the same package, never a substitution — enforced structurally in core/rules/fix-resolver.ts and covered by property-based tests. |
| Dependency confusion | npm ci resolves strictly from the lockfile's recorded URLs and integrity hashes; a missing integrity entry is a finding, not silently accepted. |
| Report/terminal injection | Every externally sourced string (advisory text, package names, sandboxed process output) is ANSI-stripped and, in Markdown reports, metacharacter-escaped before it renders (shared/sanitize.ts). |
| VeriPatch's own supply chain | Minimal dependencies, committed lockfile, GitHub Actions pinned by commit SHA, npm publish --provenance. |
| Privilege on the host | VeriPatch itself only ever writes inside .veripatch/ (project-local) and ~/.veripatch/ (the advisory cache) — zero telemetry, no secrets handled. |
- Network isolation is bridge-level, not domain-level. The install phase's network gives
the container general egress (matching what installing from the real npm registry requires),
not an allowlist restricted to the registry alone. A postinstall script could attempt
network egress during that phase — the actual defense against that specific attack is
--ignore-scripts, not the network boundary. If a future release needs domain-level filtering (e.g. for registries not reachable in the container's DNS), that's a real enhancement, not a solved problem today. - Verdict integrity reflects the project's own checks, not their honesty. A HIGH or MEDIUM
confidence verdict means "the project's own build/test commands exited 0" — a project could
have a build script that always exits 0 regardless of what actually happened. VeriPatch's
rescan step independently re-checks that the vulnerability itself is gone (that part is not
self-reported), but it does not re-verify the project's own test assertions. This is stated
explicitly in every
VerificationResult.residualRisks. - Kernel-sharing. Docker containers share the host kernel; a container-escape vulnerability in the Docker runtime itself is out of scope for VeriPatch to mitigate. A future SaaS/multi-tenant phase would need gVisor or Firecracker-level isolation for untrusted repos at scale (see docs/ROADMAP.md).
Please email security@veripatch.dev (or open a private GitHub Security Advisory if you'd rather not email) with a description and reproduction steps. We aim to acknowledge within 48 hours and to ship a fix or mitigation within 90 days of confirmation, whichever is sooner. Please don't open a public issue for undisclosed vulnerabilities.