Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions agents/openclaw/dependency-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,22 @@ Update it and `agents/openclaw/mcporter-runtime/package*.json` together whenever
- Security override: `fast-uri@3.1.4` (`sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==`) replaces Ajv's vulnerable `3.1.3` resolution for `GHSA-v2hh-gcrm-f6hx`. It remains within Ajv's declared `^3.0.1` range and preserves the reviewed v3 API boundary. Remove the override when the declared graph resolves to a reviewed patched release.

Both image paths install the committed graph with `npm ci --ignore-scripts --omit=dev` because the published package declares no install-time lifecycle script and NemoClaw needs only its already-built CLI.
The reviewed audit wrapper reports lower-severity production findings and blocks unaccepted high or critical advisories. The default `ci/npm-audit-exceptions.json` registry is empty. Any future exception must match one advisory, graph, package, installed version, and severity; identify an owner and NemoClaw tracking issue; state a decision, rationale, and expiry no more than 30 days away; and include compensating controls for temporary risk acceptance. Missing, malformed, expired, overlong, mismatched, or unused exceptions fail closed. The repository-wide audit also rejects exceptions for unknown graph IDs. Registry signature verification remains a separate control.
The reviewed audit wrapper reports lower-severity production findings and
blocks unaccepted high or critical advisories.
The `ci/npm-audit-exceptions.json` registry is empty by default outside an
explicitly bounded transition.
Any exception must match one advisory, graph, package, installed version, and
severity; identify an owner and NemoClaw tracking issue; state a decision,
rationale, and expiry no more than 30 days away; and include compensating
controls for temporary risk acceptance.
Missing, malformed, expired, overlong, mismatched, or unused exceptions fail
closed.
The repository-wide audit also rejects exceptions for unknown graph IDs.
The seven current `temporary-risk-acceptance` entries are documented in the
[OpenClaw 2026.7.1 dependency review](../../docs/security/openclaw-2026.7.1-dependency-review.md).
Pull request (PR) #8156 must remove all seven entries when it merges the
successor locks and updated archive remediator.
Registry signature verification remains a separate control.

## WeChat plugin runtime graph

Expand All @@ -42,7 +57,7 @@ The lock records the exact version, registry URL, and integrity for every transi
## Source-of-Truth Boundary

- `invalidState`: the image installs a package graph, tarball, license, or advisory state that differs from the independently queried npm registry records for `mcporter@0.7.3`, resolves `@hono/node-server` to any version other than exact `2.0.11`, or resolves `fast-uri` to any version other than exact `3.1.4`.
- `sourceBoundary`: npm owns registry metadata, tarball integrity, provenance signatures, and advisory responses; NemoClaw owns the exact lock, script-disabled install, Docker integrity assertion, empty-by-default audit exception registry, and review record.
- `sourceBoundary`: npm owns registry metadata, tarball integrity, provenance signatures, and advisory responses; NemoClaw owns the exact lock, script-disabled install, Docker integrity assertion, the audit exception registry's empty default and bounded seven-entry transition, and the review record.
- `whyNotSourceFix`: a repository note cannot make external registry state trustworthy, so image builds execute `npm audit` and `npm audit signatures` against the locked production graph and reviewers compare the lock with the registry response.
- `regressionTest`: `test/mcporter-supply-chain.test.ts` keeps the version, integrity, lock metadata, Docker install flags, audit commands, and this review synchronized; `test/reviewed-npm-audit.test.ts` proves exact matching and fail-closed exception validation.
- `removalCondition`: remove this runtime dependency and review when OpenClaw provides the required authenticated Streamable HTTP client lifecycle without mcporter, or repeat the independent review for a newly pinned version.
115 changes: 114 additions & 1 deletion ci/npm-audit-exceptions.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,117 @@
{
"schemaVersion": 1,
"exceptions": []
"exceptions": [
{
"advisory": "GHSA-4cwx-7wf7-3272",
"package": "undici",
"installedVersion": "8.5.0",
"graph": "reviewed-archive-graph",
"severity": "high",
"decision": "temporary-risk-acceptance",
"expires": "2026-08-10",
"owner": "NemoClaw security maintainers",
"trackingIssue": "https://github.com/NVIDIA/NemoClaw/pull/8156",
"rationale": "The base-owned archive audit cannot apply PR #8156's undici 8.10.0 remediation until that trusted implementation merges. PR #8156 removes this transition exception.",
"compensatingControls": [
"PR #8156 binds the OpenClaw core and Discord manifests and shrinkwraps, the physical Discord bundle, the replacement archive, remediated package tree, and OpenClaw runtime lock to undici 8.10.0 before image assembly.",
"The separately audited successor OpenClaw runtime lock contains undici 8.10.0 and no high or critical advisory."
]
},
{
"advisory": "GHSA-rgw5-rvv9-x895",
"package": "brace-expansion",
"installedVersion": "5.0.8",
"graph": "openclaw-runtime",
"severity": "high",
"decision": "temporary-risk-acceptance",
"expires": "2026-08-10",
"owner": "NemoClaw security maintainers",
"trackingIssue": "https://github.com/NVIDIA/NemoClaw/pull/8156",
"rationale": "PR #8156 upgrades the reviewed OpenClaw runtime lock to brace-expansion 5.0.9 and removes this transition exception.",
"compensatingControls": [
"PR #8165 authorizes the exact reviewed successor lock without changing the current runtime lock.",
"PR #8156 validates the replacement archive identity and remediated package-tree digest before image assembly."
]
},
{
"advisory": "GHSA-7p8r-x3mc-p8w7",
"package": "fast-uri",
"installedVersion": "3.1.4",
"graph": "openclaw-runtime",
"severity": "high",
"decision": "temporary-risk-acceptance",
"expires": "2026-08-10",
"owner": "NemoClaw security maintainers",
"trackingIssue": "https://github.com/NVIDIA/NemoClaw/pull/8156",
"rationale": "PR #8156 upgrades the reviewed OpenClaw runtime lock to fast-uri 3.1.5 and removes this transition exception.",
"compensatingControls": [
"PR #8165 authorizes the exact reviewed successor lock without changing the current runtime lock.",
"PR #8156 validates the replacement archive identity and remediated package-tree digest before image assembly."
]
},
{
"advisory": "GHSA-mwp4-54f8-5fhr",
"package": "ip-address",
"installedVersion": "10.2.0",
"graph": "openclaw-runtime",
"severity": "high",
"decision": "temporary-risk-acceptance",
"expires": "2026-08-10",
"owner": "NemoClaw security maintainers",
"trackingIssue": "https://github.com/NVIDIA/NemoClaw/pull/8156",
"rationale": "PR #8156 upgrades the reviewed OpenClaw runtime lock to ip-address 10.3.1 and removes this transition exception.",
"compensatingControls": [
"PR #8165 authorizes the exact reviewed successor lock without changing the current runtime lock.",
"PR #8156 validates the replacement archive identity and remediated package-tree digest before image assembly."
]
},
{
"advisory": "GHSA-4cwx-7wf7-3272",
"package": "undici",
"installedVersion": "8.5.0",
"graph": "openclaw-runtime",
"severity": "high",
"decision": "temporary-risk-acceptance",
"expires": "2026-08-10",
"owner": "NemoClaw security maintainers",
"trackingIssue": "https://github.com/NVIDIA/NemoClaw/pull/8156",
"rationale": "PR #8156 upgrades the reviewed OpenClaw runtime lock to undici 8.10.0 and removes this transition exception.",
"compensatingControls": [
"PR #8165 authorizes the exact reviewed successor lock without changing the current runtime lock.",
"PR #8156 validates the manifest, shrinkwrap, replacement archive, and installed lock before image assembly."
]
},
{
"advisory": "GHSA-7p8r-x3mc-p8w7",
"package": "fast-uri",
"installedVersion": "3.1.4",
"graph": "mcporter-runtime",
"severity": "high",
"decision": "temporary-risk-acceptance",
"expires": "2026-08-10",
"owner": "NemoClaw security maintainers",
"trackingIssue": "https://github.com/NVIDIA/NemoClaw/pull/8156",
"rationale": "PR #8156 upgrades the reviewed mcporter runtime lock to fast-uri 3.1.5 and removes this transition exception.",
"compensatingControls": [
"PR #8165 authorizes the exact reviewed successor lock without changing the current runtime lock.",
"PR #8156 pins the replacement through an exact override and validates the installed lock before image assembly."
]
},
{
"advisory": "GHSA-mwp4-54f8-5fhr",
"package": "ip-address",
"installedVersion": "10.2.0",
"graph": "mcporter-runtime",
"severity": "high",
"decision": "temporary-risk-acceptance",
"expires": "2026-08-10",
"owner": "NemoClaw security maintainers",
"trackingIssue": "https://github.com/NVIDIA/NemoClaw/pull/8156",
"rationale": "PR #8156 upgrades the reviewed mcporter runtime lock to ip-address 10.3.1 and removes this transition exception.",
"compensatingControls": [
"PR #8165 authorizes the exact reviewed successor lock without changing the current runtime lock.",
"PR #8156 pins the replacement through an exact override and validates the installed lock before image assembly."
]
}
]
}
5 changes: 5 additions & 0 deletions ci/source-shape-test-budget.json
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@
"test": "%s keeps the full plan in build processes but not final runtime environments (#5896)",
"category": "security"
},
{
"file": "test/mcp-tool-discovery-image-contract.test.ts",
"test": "pins the audited MCP discovery transitive graph (#8156)",
"category": "security"
},
{
"file": "test/mcp-openshell-workflow.test.ts",
"test": "keeps the setup docs aligned with the stable default",
Expand Down
22 changes: 20 additions & 2 deletions docs/security/openclaw-2026.6.10-dependency-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,25 @@ The current remediation does not silently extend its authority to those graphs.

This review is an advisory snapshot for the direct OpenClaw runtime package, the locked `mcporter@0.7.3` graph, Codex ACP runtime helper, optional plugins, messaging plugins, and their npm dependency graphs at review time. Default PR and main CI now rematerialize those exact direct packages from SRI-verified reviewed local archives under Node `22.23.1`, install with lifecycle scripts disabled, run `npm audit --omit=dev --json` through `scripts/lib/reviewed-npm-audit.mts`, and upload both the raw reports and normalized policy results from `coverage/reviewed-npm-audit`. The configured threshold in `ci/reviewed-npm-audit.json` is `high`. Lower-severity findings remain visible without blocking. The same job independently installs and audits the committed mcporter production lock. This gate complements, but does not replace, the committed npm integrity pins, registry signature verification, and install-time archive checks.

The exception registry at `ci/npm-audit-exceptions.json` is empty by default. It is not a global npm-audit bypass: each entry must exactly match one advisory, audited graph, package, installed version, and reported severity. It must also record an expiring `not-affected` or `temporary-risk-acceptance` decision, rationale, owner, and NemoClaw issue or PR. Expiry is limited to 30 days. Temporary risk acceptance additionally requires compensating controls. Missing, malformed, expired, overlong, duplicate, mismatched, and unused entries fail the audit. The repository-wide audit also rejects exceptions for unknown graph IDs. The policy file hash, evaluation status, and accepted advisory IDs are bound into OpenClaw base-image provenance, so a child image cannot silently reuse a base built under a different exception set. The registry contains no exception for `GHSA-v2hh-gcrm-f6hx` or any other current advisory.
The exception registry at `ci/npm-audit-exceptions.json` is empty by default
outside an explicitly bounded transition.
It is not a global npm-audit bypass: each entry must exactly match one
advisory, audited graph, package, installed version, and reported severity.
It must also record an expiring `not-affected` or
`temporary-risk-acceptance` decision, rationale, owner, and NemoClaw issue or
PR.
Expiry is limited to 30 days.
Temporary risk acceptance additionally requires compensating controls.
Missing, malformed, expired, overlong, duplicate, mismatched, and unused
entries fail the audit.
The repository-wide audit also rejects exceptions for unknown graph IDs.
The policy file hash, evaluation status, and accepted advisory IDs are bound
into OpenClaw base-image provenance, so a child image cannot silently reuse a
base built under a different exception set.
The seven current `temporary-risk-acceptance` entries are documented in the
[OpenClaw 2026.7.1 dependency review](./openclaw-2026.7.1-dependency-review.md).
PR #8156 must remove all seven entries when it merges the successor locks and
updated archive remediator.

## Transitive Dependency Graph Rationale

Expand Down Expand Up @@ -235,7 +253,7 @@ Removal condition: retain these provenance checks in the shared installer and up

The Codex ACP, runtime OpenClaw, base-image OpenClaw, optional-plugin, and messaging-plugin boundaries consume one reviewed implementation with thin shell or TypeScript callers. Every archive boundary retains exact reviewed package identity, registry SRI, reviewed registry tarball URL, packed-byte SRI, a nonempty regular-file basename contained in a fresh pack directory, install from the resolved local archive only, cleanup, and failure before install on any mismatch. Runtime OpenClaw either executes that full transaction or consumes the exact protected result of the base-image transaction under the bounded provenance checks above; it never substitutes a floating package-spec install. Runtime mcporter verifies the same exact registry metadata and then either installs and audits the committed lock or consumes the marker-bound result of that exact locked and audited base-image transaction.

Invalid state: a caller bypasses the helper, the audit inventory diverges from a production pin, CI audits a graph other than the verified local archives and committed mcporter lock, an exception is missing required review metadata or does not exactly match a current finding, base provenance uses a different exception policy, or audit evidence is lost when the threshold fails. Source boundary: `scripts/lib/reviewed-npm-archive.mts`, `scripts/lib/reviewed-npm-audit.mts`, the thin Docker and messaging callers, `ci/reviewed-npm-audit.json`, `ci/npm-audit-exceptions.json`, `scripts/audit-reviewed-npm-graph.mts`, and `.github/actions/ci-reviewed-npm-audit/action.yaml`. Source-fix constraint: #5242 retains general dependency-pin and canary design ownership; this slice records only the current production audit inventory and tests it against the caller-owned pins. Regression tests: the integrity-pin suites and `test/messaging-build-applier-integrity.test.ts` retain malicious filename, registry drift, packed-SRI drift, and local-install proof at each caller; `test/reviewed-npm-archive.test.ts` tests the shared archive primitive; and `test/reviewed-npm-audit.test.ts` pins the empty default, exact exception matching, expiry, threshold behavior, and fail-closed validation. Removal condition: keep the shared helpers and audit gate while reviewed npm archives remain production build inputs.
Invalid state: a caller bypasses the helper, the audit inventory diverges from a production pin, CI audits a graph other than the verified local archives and committed mcporter lock, an exception is missing required review metadata or does not exactly match a current finding, base provenance uses a different exception policy, or audit evidence is lost when the threshold fails. Source boundary: `scripts/lib/reviewed-npm-archive.mts`, `scripts/lib/reviewed-npm-audit.mts`, the thin Docker and messaging callers, `ci/reviewed-npm-audit.json`, `ci/npm-audit-exceptions.json`, `scripts/audit-reviewed-npm-graph.mts`, and `.github/actions/ci-reviewed-npm-audit/action.yaml`. Source-fix constraint: #5242 retains general dependency-pin and canary design ownership; this slice records only the current production audit inventory and tests it against the caller-owned pins. Regression tests: the integrity-pin suites and `test/messaging-build-applier-integrity.test.ts` retain malicious filename, registry drift, packed-SRI drift, and local-install proof at each caller; `test/reviewed-npm-archive.test.ts` tests the shared archive primitive; and `test/reviewed-npm-audit.test.ts` pins the bounded seven-entry transition, exact exception matching, expiry, threshold behavior, and fail-closed validation. Removal condition: keep the shared helpers and audit gate while reviewed npm archives remain production build inputs.

### OpenClaw Compiled-Dist Patch Runtime Boundary

Expand Down
Loading
Loading