ci(security): scan source dependencies and built images for known vulnerabilities
- Dominant language
- TypeScript
- Stars
- 22.5k
- Forks
- 3.1k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 715
Description
## Problem Statement
NemoClaw does not currently have an end-to-end software composition analysis (SCA) control that reliably detects newly disclosed vulnerabilities in runtime dependencies.
The current controls cover adjacent risks but leave important gaps:
- CodeQL scans JavaScript/TypeScript and Python for vulnerable code patterns, but it is not a substitute for advisory-database dependency scanning.
- `.github/dependabot.yml` updates GitHub Actions only; neither npm project is configured.
- The regular CI/static-check workflow does not run `npm audit`, OSV-Scanner, GitHub dependency review, Trivy, Grype, or an equivalent SCA tool.
- NemoClaw has two npm dependency graphs (the repository root and `nemoclaw/`).
- The production image globally installs OpenClaw and plugins during the Docker build. Their nested runtime dependencies may not appear in either NemoClaw lockfile, so source-only scanning is insufficient.
- Existing tar security regression tests cover traversal, hard links, and symlink escapes, but not decompression ratio, extracted-byte, entry-count, or CPU/disk exhaustion limits.
CVE-2026-59873 / GHSA-23hp-3jrh-7fpw exposed this gap: an affected `tar` version could be installed transitively through OpenClaw without a checked-in CI control reliably flagging the resulting runtime image. The issue is public and fixed in `tar@7.5.19`.
Related: #665 added CodeQL and weekly code scanning. This proposal complements that work with dependency and image scanning.
## Proposed Design
Add a layered, fail-safe vulnerability-scanning workflow rather than relying on one signal.
### 1. Scan both source dependency graphs
- Configure Dependabot npm updates for `/` and `/nemoclaw`.
- Run an advisory-backed production-dependency scan for both lockfiles on pull requests and on a schedule.
- Prefer a tool that reports direct and transitive dependency paths, advisory identifiers, affected versions, and first fixed versions.
- Install dependencies with lifecycle scripts disabled wherever execution is unnecessary.
### 2. Review dependency changes on pull requests
- Add a SHA-pinned GitHub dependency-review action for pull requests that modify dependency manifests or lockfiles.
- Initially fail additions of known High or Critical production vulnerabilities.
- Report development-only and lower-severity findings without making the first rollout excessively noisy.
### 3. Scan the exact built runtime image
- Scan the image produced from NemoClaw's Dockerfile, including:
- OS packages;
- root NemoClaw runtime dependencies;
- the NemoClaw plugin dependency tree;
- globally installed OpenClaw and plugin dependencies under `/usr/local/lib/node_modules`.
- Generate an SPDX or CycloneDX SBOM for the immutable image and retain it as a workflow artifact.
- Publish findings as SARIF or another reviewable GitHub-native artifact.
- Preserve image digest/SHA provenance so the scan result identifies the exact artifact evaluated.
### 4. Detect newly disclosed vulnerabilities after merge
- Run the source and image scans on a scheduled workflow even when no dependency files change.
- Create a visible failure/alert when a newly published High or Critical advisory affects a shipped runtime.
- Cache vulnerability databases where appropriate, but define fail-safe behavior for stale or unavailable databases.
### 5. Add bounded archive resource-exhaustion regression coverage
Add a small deterministic fixture that exercises archive parsing/extraction limits without expanding gigabytes of data:
- maliciously high decompression ratio;
- oversized header-declared entry;
- excessive aggregate extracted bytes;
- excessive entry count;
- bounded wall-clock completion and cleanup.
The test should verify rejection before material disk or memory consumption. It should cover NemoClaw-owned archive boundaries and any installed OpenClaw extraction boundary that NemoClaw treats as part of the supported runtime contract.
### 6. Define an exception policy
Any vulnerability allowlist entry should require:
- advisory ID and affected component;
- reachability/mitigation rationale;
- owner;
- expiration date;
- link to remediation work.
Expired entries must fail the scan. Do not silently suppress scanner failures or database-update failures.
### Workflow trust requirements
- Pin all third-party Actions and scanner releases by immutable digest/SHA, consistent with repository policy.
- Do not execute PR-controlled package lifecycle scripts in privileged or secret-bearing jobs.
- Treat the candidate checkout and built image as untrusted scan inputs.
- Redact registry credentials and scanner output before artifact upload.
## Alternatives Considered
### Dependabot only
Useful for upgrade PRs, but it does not provide a deterministic merge gate or prove that the final globally assembled image is clean.
### `npm audit` only
Simple, but scanning only the repository lockfiles misses OS packages and OpenClaw dependencies installed globally during the image build.
### CodeQL only
CodeQL is valuable for source-level weakness detection but does not reliably alert on every newly published dependency advisory.
### Behavioral tests only
Regression tests prove known resource limits but cannot discover a new CVE published after the test was written.
## Acceptance Criteria
- [ ] Dependabot covers npm dependencies in both `/` and `/nemoclaw`.
- [ ] Pull requests adding a known High or Critical production vulnerability fail with the dependency path and fixed version.
- [ ] A scheduled scan detects a newly disclosed advisory without requiring a source change.
- [ ] The exact production image is scanned, including globally installed OpenClaw dependencies.
- [ ] The workflow generates an SBOM tied to the scanned image digest and source SHA.
- [ ] Findings are available through GitHub-native annotations, SARIF, summaries, or retained artifacts.
- [ ] A hermetic test proves the scanner flags a fixture containing a vulnerable transitive dependency and passes after upgrading it.
- [ ] Archive resource-limit tests cover decompression ratio, entry size/count, aggregate size, timeout, and cleanup without consuming excessive resources.
- [ ] High/Critical allowlist entries require an owner, rationale, remediation link, and expiration date.
- [ ] Scanner/tool/database failures cannot be reported as a clean result.
- [ ] Third-party Actions and scanner artifacts are immutable-pinned.
- [ ] Documentation identifies local reproduction commands and the vulnerability-response workflow.
## Category
Testing
## Checklist
- [x] I searched existing issues and this is not a duplicate.
- [x] This is a design proposal, not a "please build this" request.
## Related follow-up
- #7288 — Fix-forward hardening identified during review of #7276.
Contributor guide
Assessment
This issue has not been assessed yet.