mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
fix(security): re-evaluate forced policy warnings
This commit is contained in:
+1
-1
@@ -198,7 +198,7 @@ non-npm sources are not rewritten.
|
||||
`--pin` applies to npm installs only and records the resolved exact `<name>@<version>`. It is not supported with `git:` installs (pin the ref in the spec instead, e.g. `git:github.com/acme/plugin@v1.2.3`) or with `--marketplace` (marketplace installs persist marketplace source metadata instead of an npm spec).
|
||||
</Accordion>
|
||||
<Accordion title="--dangerously-force-unsafe-install">
|
||||
When `security.installPolicy` returns `warn` in an interactive terminal, OpenClaw prints the reason and findings, then uses the same acknowledgement copy as a suspicious ClawHub release: `type: '<plugin>' to install anyway`. A matching answer re-evaluates the staged source before continuing. A declined or non-interactive install stops before commit; after review, it can be rerun with `--dangerously-force-unsafe-install`. Neither form overrides `block` or a policy failure.
|
||||
When `security.installPolicy` returns `warn` in an interactive terminal, OpenClaw prints the reason and findings, then uses the same acknowledgement copy as a suspicious ClawHub release: `type: '<plugin>' to install anyway`. A matching answer re-evaluates the staged source before continuing. A declined or non-interactive install stops before commit; after review, `--dangerously-force-unsafe-install` is the explicit noninteractive approval. Every approved warning is re-evaluated before continuing. Neither form overrides `block` or a policy failure.
|
||||
|
||||
If a plugin you published on ClawHub is hidden or blocked by a registry scan, use the publisher steps in [ClawHub publishing](/clawhub/publishing). `--dangerously-force-unsafe-install` does not ask ClawHub to rescan the plugin or make a blocked release public.
|
||||
|
||||
|
||||
+3
-2
@@ -104,8 +104,9 @@ When `security.installPolicy` returns `warn` in an interactive terminal,
|
||||
OpenClaw prints the reason and findings, then asks `type: '<skill>' to install
|
||||
anyway` (or `update anyway`). A matching answer evaluates the staged skill
|
||||
again before continuing. Declined and non-interactive commands stop before
|
||||
commit; after review, rerun with `--dangerously-force-unsafe-install`. `block`
|
||||
and policy failures remain terminal.
|
||||
commit; after review, `--dangerously-force-unsafe-install` is the explicit
|
||||
noninteractive approval, and every approved warning is re-evaluated before
|
||||
continuing. `block` and policy failures remain terminal.
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
@@ -340,7 +340,7 @@ Plugins run in-process with the Gateway - treat them as trusted code.
|
||||
- npm and git plugin installs run package-manager dependency convergence only during the explicit install/update flow. Local paths and archives are treated as self-contained packages; OpenClaw copies/references them without running `npm install`.
|
||||
- Prefer pinned exact versions (`@scope/pkg@1.2.3`) and inspect the unpacked code before enabling.
|
||||
- `security.installPolicy` lets operators run a trusted local command to return `allow`, `warn`, or `block` for skill and plugin installs. It runs after source material is staged but before install continues and applies to ClawHub skills too.
|
||||
- A `warn` result stops before commit. Interactive CLI commands ask the operator to type the plugin or skill name using the same wording as suspicious ClawHub releases, then re-evaluate policy before continuing. Declined and non-interactive commands can be rerun with `--dangerously-force-unsafe-install` after review. `block` and policy failures remain terminal.
|
||||
- A `warn` result stops before commit. Interactive CLI commands ask the operator to type the plugin or skill name using the same wording as suspicious ClawHub releases, then re-evaluate policy before continuing. Declined and non-interactive commands can use `--dangerously-force-unsafe-install` as explicit approval after review; every approved warning is re-evaluated before continuing. `block` and policy failures remain terminal.
|
||||
|
||||
Details: [Plugins](/tools/plugin)
|
||||
|
||||
|
||||
@@ -181,7 +181,8 @@ write one JSON object on stdout with an `allow`, `warn`, or `block` decision.
|
||||
plugin and skill commands ask the operator to type the target name using the
|
||||
same `install anyway` or `update anyway` copy as suspicious ClawHub releases,
|
||||
then run policy again before continuing. Declined and non-interactive commands
|
||||
may be rerun with `--dangerously-force-unsafe-install` after review.
|
||||
may use `--dangerously-force-unsafe-install` as explicit approval after review;
|
||||
every approved warning is re-evaluated before continuing.
|
||||
Gateway-backed and automatic installs remain
|
||||
blocked on warnings because they have no operator-confirmation flow. A `block`, non-zero
|
||||
exit, timeout, malformed JSON, missing field, or unsupported protocol version
|
||||
|
||||
@@ -393,6 +393,24 @@ describe("legacy file install scan compatibility", () => {
|
||||
}),
|
||||
});
|
||||
expect(acknowledgedAttempt).toBeUndefined();
|
||||
expect(runInstallPolicyMock).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it("keeps a block from forced policy re-evaluation terminal", async () => {
|
||||
runInstallPolicyMock
|
||||
.mockResolvedValueOnce({ warning: { reason: "review this plugin" } })
|
||||
.mockResolvedValueOnce({
|
||||
blocked: { code: "security_scan_blocked", reason: "now blocked" },
|
||||
});
|
||||
|
||||
const result = await scanFileInstallSourceRuntime({
|
||||
dangerouslyForceUnsafeInstall: true,
|
||||
filePath: "/tmp/payload.js",
|
||||
logger: {},
|
||||
pluginId: "payload",
|
||||
});
|
||||
|
||||
expect(result?.blocked).toEqual({ code: "security_scan_blocked", reason: "now blocked" });
|
||||
expect(runInstallPolicyMock).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
|
||||
@@ -739,11 +739,7 @@ async function runOperatorInstallPolicy(params: {
|
||||
logPolicyResult(result);
|
||||
return undefined;
|
||||
}
|
||||
if (params.dangerouslyForceUnsafeInstall) {
|
||||
logPolicyResult(result);
|
||||
return undefined;
|
||||
}
|
||||
if (!params.onInstallPolicyWarning) {
|
||||
if (!params.dangerouslyForceUnsafeInstall && !params.onInstallPolicyWarning) {
|
||||
return {
|
||||
blocked: {
|
||||
code: "security_scan_blocked",
|
||||
@@ -763,11 +759,13 @@ async function runOperatorInstallPolicy(params: {
|
||||
};
|
||||
}
|
||||
logPolicyResult(result);
|
||||
const acknowledged = await params.onInstallPolicyWarning({
|
||||
targetName: params.targetName,
|
||||
targetType: params.targetType,
|
||||
requestMode: params.requestMode,
|
||||
});
|
||||
const acknowledged =
|
||||
params.dangerouslyForceUnsafeInstall ||
|
||||
(await params.onInstallPolicyWarning?.({
|
||||
targetName: params.targetName,
|
||||
targetType: params.targetType,
|
||||
requestMode: params.requestMode,
|
||||
}));
|
||||
if (acknowledged) {
|
||||
const reevaluated = await evaluatePolicy();
|
||||
if (reevaluated?.blocked) {
|
||||
|
||||
Reference in New Issue
Block a user