Skip to content

Commit c56067e

Browse files
committed
chore: harden npm shrinkwrap release path
1 parent 56308a7 commit c56067e

18 files changed

Lines changed: 5832 additions & 9 deletions

.github/CODEOWNERS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
/.github/workflows/codeql-critical-quality.yml @openclaw/openclaw-secops
1414
/.github/workflows/dependency-change-awareness.yml @openclaw/openclaw-secops
1515
/test/scripts/dependency-change-awareness-workflow.test.ts @openclaw/openclaw-secops
16+
/package-lock.json @openclaw/openclaw-secops
17+
/npm-shrinkwrap.json @openclaw/openclaw-secops
18+
/pnpm-lock.yaml @openclaw/openclaw-secops
19+
/scripts/generate-npm-shrinkwrap.mjs @openclaw/openclaw-secops
1620
/src/security/ @openclaw/openclaw-secops
1721
/src/secrets/ @openclaw/openclaw-secops
1822
/src/config/*secret*.ts @openclaw/openclaw-secops

.github/workflows/dependency-change-awareness.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ jobs:
3434
3535
const isDependencyFile = (filename) =>
3636
filename === "package.json" ||
37+
filename === "package-lock.json" ||
38+
filename === "npm-shrinkwrap.json" ||
3739
filename === "pnpm-lock.yaml" ||
3840
filename === "pnpm-workspace.yaml" ||
3941
filename === "ui/package.json" ||
@@ -143,7 +145,8 @@ jobs:
143145
"",
144146
"Maintainer follow-up:",
145147
"- Review whether the dependency changes are intentional.",
146-
"- Inspect resolved package deltas when lockfile or workspace dependency policy changes are present.",
148+
"- Inspect resolved package deltas when lockfile, shrinkwrap, or workspace dependency policy changes are present.",
149+
"- Treat `package-lock.json` and `npm-shrinkwrap.json` diffs as security-review surfaces.",
147150
"- Run `pnpm deps:changes:report -- --base-ref origin/main --markdown /tmp/dependency-changes.md --json /tmp/dependency-changes.json` locally for detailed release-style evidence.",
148151
].join("\n");
149152

.github/workflows/labeler.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ jobs:
8989
per_page: 100,
9090
});
9191
92-
const excludedLockfiles = new Set(["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb"]);
92+
const excludedLockfiles = new Set(["pnpm-lock.yaml", "package-lock.json", "npm-shrinkwrap.json", "yarn.lock", "bun.lockb"]);
9393
const totalChangedLines = files.reduce((total, file) => {
9494
const path = file.filename ?? "";
9595
if (path.startsWith("docs/") || excludedLockfiles.has(path)) {
@@ -603,7 +603,7 @@ jobs:
603603
per_page: 100,
604604
});
605605
606-
const excludedLockfiles = new Set(["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb"]);
606+
const excludedLockfiles = new Set(["pnpm-lock.yaml", "package-lock.json", "npm-shrinkwrap.json", "yarn.lock", "bun.lockb"]);
607607
const totalChangedLines = files.reduce((total, file) => {
608608
const path = file.filename ?? "";
609609
if (path.startsWith("docs/") || excludedLockfiles.has(path)) {

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ Skills own workflows; root owns hard policy and routing.
161161
- Never commit real phone numbers, videos, credentials, live config.
162162
- Secrets: channel/provider creds in `~/.openclaw/credentials/`; model auth profiles in `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`.
163163
- Dependency patches/overrides/vendor changes need explicit approval. `pnpm-workspace.yaml` patched dependencies use exact versions only.
164+
- Lockfiles/shrinkwrap are security surface: review `pnpm-lock.yaml`, `npm-shrinkwrap.json`, `package-lock.json`; npm package ships shrinkwrap, not package-lock.
164165
- Carbon pins owner-only: do not change `@buape/carbon` unless Shadow (`@thewilloftheshadow`, verified by `gh`) asks.
165166
- Releases/publish/version bumps need explicit approval. Use `$openclaw-release-maintainer`.
166167
- GHSA/advisories: `$openclaw-ghsa-maintainer` / `$security-triage`. Secret scanning: `$openclaw-secret-scanning-maintainer`.

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Docs: https://docs.openclaw.ai
2828
- QA-Lab: include an opt-in `update.run` package self-upgrade sentinel for destructive latest-package recovery checks.
2929
- QA-Lab: add Codex plugin lifecycle and auth-profile fixture coverage for missing installs, pinned-version drift, first-turn install ordering, and doctor migration safety. (#80323, refs #80174) Thanks @100yenadmin.
3030
- Models/perf: pre-warm the provider auth-state map at gateway startup so `/models` and every model-listing call short-circuits the per-provider plugin / external-CLI discovery on the hot path. Per-call cost drops from ~20 s to ~5 ms (~4,100×); the one-time startup warm resets and re-warms after hot reloads. (#84816) Thanks @sjf.
31+
- Release/security: ship the root npm package and OpenClaw-owned npm plugins with generated shrinkwrap and require review for lockfile/shrinkwrap changes so published installs use locked dependency graphs.
3132
- Tests/perf: isolate doctor core health check unit coverage from real skills/workspace discovery so `doctor-core-checks` no longer dominates unit perf while keeping one real skills-readiness smoke. (#84493) Thanks @frankekn.
3233

3334
### Fixes

docs/gateway/security/index.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,48 @@ OpenClaw is both a product and an experiment: you're wiring frontier-model behav
5353

5454
Start with the smallest access that still works, then widen it as you gain confidence.
5555

56+
### Published package dependency lock
57+
58+
OpenClaw source checkouts use `pnpm-lock.yaml`. The published `openclaw` npm
59+
package also includes `npm-shrinkwrap.json`, npm's publishable dependency
60+
lockfile, so package installs use the reviewed transitive dependency graph
61+
from the release instead of resolving a fresh graph at install time.
62+
63+
This is a supply-chain hardening measure:
64+
65+
- release installs are more reproducible;
66+
- transitive dependency updates become visible review surfaces;
67+
- the package tarball contains the dependency graph that release validators
68+
checked;
69+
- `package-lock.json` stays out of the published package, because npm does not
70+
treat it as the publishable lock contract.
71+
72+
Shrinkwrap is not a sandbox and does not make every dependency trustworthy. It
73+
does not replace `openclaw security audit`, host isolation, npm provenance,
74+
signature/audit checks, or `--ignore-scripts` install smoke tests when those are
75+
appropriate. Treat it as a release reproducibility and review-control boundary.
76+
77+
Maintainers should update and verify the shrinkwrap whenever the root package's
78+
published dependency graph changes:
79+
80+
```bash
81+
pnpm deps:shrinkwrap:generate
82+
pnpm deps:shrinkwrap:check
83+
```
84+
85+
Review `pnpm-lock.yaml`, `npm-shrinkwrap.json`, and any `package-lock.json`
86+
diff as security-sensitive. The package validators require shrinkwrap in new
87+
tarballs and reject `package-lock.json`.
88+
89+
To inspect a published package:
90+
91+
```bash
92+
npm pack openclaw@<version> --json --pack-destination /tmp/openclaw-pack
93+
tar -tf /tmp/openclaw-pack/openclaw-<version>.tgz | grep '^package/npm-shrinkwrap.json$'
94+
```
95+
96+
Background: [npm-shrinkwrap.json](https://docs.npmjs.com/cli/v11/configuring-npm/npm-shrinkwrap-json).
97+
5698
### Deployment and host trust
5799

58100
OpenClaw assumes the host and config boundary are trusted:

0 commit comments

Comments
 (0)