feat(policy): add OpenClaw install policy adapter - #35
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Codex review: needs maintainer review before merge. Reviewed July 31, 2026, 12:27 AM ET / 04:27 UTC. ClawSweeper reviewWhat this changesThis PR adds a Merge readinessKeep this PR open for maintainer coordination rather than closing or mechanically repairing it. The adapter is coherent and its tests/docs describe the intended fail-closed behavior, but its useful Priority: P2 Review scores
Verification
How this fits togetherOpenClaw stages a third-party skill or plugin and invokes a trusted external install-policy command before committing the install. This adapter feeds the staged path through ClawScan scanners and maps the resulting gate to an allow, warn, or block response that the OpenClaw host must interpret. flowchart LR
A[Staged skill or plugin] --> B[OpenClaw protocol request]
B --> C[Trusted ClawScan policy command]
C --> D[Built-in policy profile]
D --> E[Static scanner and sandboxed scanners]
E --> F[Gate aggregation]
F --> G[Allow warn or block response]
G --> H[OpenClaw install commit or confirmation]
Decision needed
Why: The branch deliberately introduces a protocol response that older released hosts reject; choosing whether to merge an intentionally non-deployable-by-default integration ahead of its host dependency is a product and release-coordination decision, not a mechanical code repair. Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Coordinate and land the OpenClaw host support for protocol-v1 warning confirmation, then verify this adapter against that host on both ordinary and containerized Gateway deployments and document the minimum compatible host release before operator rollout. Do we have a high-confidence way to reproduce the issue? Not applicable: this PR proposes a new opt-in install-policy integration rather than reporting broken existing behavior. The branch supplies focused protocol and staging tests, while the remaining question is compatibility with the coordinating OpenClaw host. Is this the best way to solve the issue? Unclear: the adapter is a focused use of the existing external-policy boundary, but it is not yet the complete deployable solution until the host accepts AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 13c6cb59b581. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (23 earlier review cycles; latest 8 shown)
|
f0a2669 to
735c244
Compare
|
/clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
…y' into jesse/openclaw-install-gate-plugin # Conflicts: # scripts/build-docs-site.mjs
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: feat(policy): add OpenClaw install policy adapter This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
New behavior
OpenClaw operators can configure the trusted ClawScan binary directly as
security.installPolicy.execfor both skill and plugin installs. The command reads OpenClaw's protocol-v1 request from stdin, scans the staged source with an operator-owned profile, and returns a bounded protocol-v1allow,warn, orblockresponse. Invalid requests, incomplete scanner evidence, scanner failures, unsafe dependency layouts, unsupported judge-backed profiles, and unknown gate results fail closed.passallowwarnwarnwith a non-empty reasonblockblockwith a non-empty reasonOpenClaw owns all prompting and acknowledgement UI. The policy process adds no prompts, approval tokens, capability negotiation, phase IDs, or other approval machinery. Optional findings are bounded and contain only
ruleId,severity,message, and optionalevidence.openclaw-install-policyprofile deterministically composes SkillSpector andclawscan-static; custom profiles remain operator-owned composition points.skillandplugintarget kinds are preserved even when staged files do not contain a manifest.Important
This integration requires the coordinated OpenClaw host change that accepts protocol-v1
warnand performs confirmation before install commit. There is not yet a released OpenClaw version floor to name. Older allow/block-only hosts rejectwarnand fail closed. Do not deploy or enable this adapter until the matching host contract lands.End-to-end operator flow
flowchart LR A["OpenClaw stages a skill or plugin"] --> B["Protocol-v1 request with sourcePath"] B --> C["Trusted security.installPolicy.exec process"] C --> D["clawscan-static in the policy process"] C --> E["SkillSpector in ClawScan's Docker sandbox"] D --> F["Combine scanner gate rules"] E --> F F --> G{"Policy decision"} G -- "allow" --> H["Commit install"] G -- "warn" --> I["OpenClaw requests explicit confirmation"] G -- "block" --> J["Reject install"]OpenClaw first stages the candidate instead of mutating the installed location. It supplies the staged path and target metadata over JSON stdin; ClawScan returns exactly one protocol response over stdout. OpenClaw remains the owner of install commit and warning confirmation.
OpenClaw configuration
After resolving the package's real, non-symlink native executable path, configure the Gateway with that absolute path and its containing trusted directory:
The command path and any interpreter script arguments must pass OpenClaw's ownership, permission, non-symlink, and trusted-directory checks.
PATHlets ClawScan find Docker;DOCKER_HOSTis needed only for non-default Docker setups.openclaw doctor --deepperforms a synthetic policy probe after configuration.Host contract required by ClawScan
ClawScan uses only the existing external install-policy request fields:
protocolVersion: 1targetType: "skill" | "plugin"andtargetNamesourcePathandsourcePathKindrequest.kind,request.mode, and optionalrequest.requestedSpecifiercontentTypeIt returns
protocolVersion,decision, a required non-emptyreasonforwarnandblock, and optional boundedfindings. No parallel hook contract or activation mechanism is introduced.Sandbox and containerized Gateway behavior
security.installPolicy.execruns as a trusted local child of the OpenClaw Gateway/install process; the normal agent tool sandbox does not isolate it. ClawScan then applies its own Docker sandbox to command-backed scanners such as SkillSpector. It automatically mounts the stagedsourcePathread-only at the same absolute path and mounts its temporary scanner-result directory writable, so the default host installation needs no manual target--sandbox-mount.A containerized Gateway using the host Docker socket must make both path classes visible to the Docker daemon. The supported nested-Docker setup uses one temporary root bind-mounted from the host into the Gateway at the same absolute path, sets the Gateway's
TMPDIRto that root, and addsTMPDIRtoexec.passEnv. This keeps OpenClaw staging paths and ClawScan result paths mountable by scanner containers. A container-only/tmpdoes not work in this topology.The documented alternative is to treat an intentionally isolated, disposable Gateway container as the sandbox, install every selected scanner inside it, and configure
--sandbox off. This removes ClawScan's inner Docker boundary and is not a workaround for an ordinary missing daemon or mismatched staging path.npm install-stage behavior
One npm plugin install can invoke the policy more than once. Each call has a distinct purpose:
clawscan-staticwithout Dockernode_modulesexclusions, omits only OpenClaw's host-validated peer symlink, then runs the full profileA local
plugin-filerequest never matches the metadata shortcut. Dependency materialization is capped by package count, filesystem entries, per-file bytes, and aggregate bytes before untrusted content can exhaust the temporary scan area.Protocol proof
A successful scan returns:
{"protocolVersion":1,"decision":"allow"}A warning returns control to the host for confirmation:
{ "protocolVersion": 1, "decision": "warn", "reason": "ClawScan gate reported warnings for the staged installation", "findings": [ { "ruleId": "clawscan-static/example", "severity": "warn", "message": "Review this finding before installing" } ] }A malformed request or failed required scanner returns a non-overridable fail-closed response:
{ "protocolVersion": 1, "decision": "block", "reason": "ClawScan install policy failed closed: ..." }JSON responses are written to stdout; diagnostics stay on stderr. Reasons and finding text are length-bounded and control-character sanitized before OpenClaw logs or displays them.
How to verify
The focused multi-stage test creates valid and malformed metadata, package, transitive-dependency, and dependency-free payloads and checks the distinct protocol responses:
TMPDIR=/private/tmp go test -count=1 ./cmd/clawscan \ -run TestRunOpenClawInstallPolicyHandlesNPMInstallStagesSeparatelyThe dependency tests additionally prove nested package code is visible outside normal
node_modulesexclusions, the exact host peer link is omitted, safe in-tree symlink targets are copied into the scan view, other escaping symlinks fail closed, and all copy budgets are enforced:TMPDIR=/private/tmp go test -count=1 ./internal/installpolicyOperator setup, executable trust checks, automatic target mounts, containerized-Gateway path sharing, custom-profile composition, request/response semantics, multi-call npm behavior, and scope boundaries are documented in
docs/openclaw-install-policy.md.Checks
TMPDIR=/private/tmp go test -count=1 ./...TMPDIR=/private/tmp go vet ./...node --test npm/clawscan/test/*.test.mjs scripts/build-npm-package.test.mjs(15 tests)actionlint .github/workflows/npm-release.yml .github/workflows/release.ymlnode scripts/build-npm-package.mjs --version v0.0.0 --pack --smokemake release VERSION=v0.0.0-testmake docs-site(7 pages)git diff --checkImplementation notes
PR #34 is now merged; this branch is restacked directly on
mainso the net diff contains only the install-policy adapter. The policy command does not claim a singleton scanner: operators can select multiple ClawScan adapters or place ClawScan behind a broader policy wrapper and combine decisions deterministically. Judge-backed profiles fail closed until a canonical judge-to-policy mapping exists. Skill Workshop authoring and manual filesystem copies remain outside OpenClaw's supply-chain install boundary.