@clawdreyhepburn/carapace 1.0.10 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/README.md +5 -5
- package/dist/cedar-engine-cedarling.d.ts +83 -37
- package/dist/cedar-engine-cedarling.js +322 -371
- package/dist/cedar-engine-cedarling.js.map +1 -1
- package/dist/index.js +190 -13
- package/dist/index.js.map +1 -1
- package/dist/llm-proxy.js +32 -3
- package/dist/llm-proxy.js.map +1 -1
- package/dist/shell-parse.d.ts +39 -0
- package/dist/shell-parse.js +248 -0
- package/dist/shell-parse.js.map +1 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -1
- package/src/cedar-engine-cedarling.ts +352 -423
- package/src/index.ts +211 -14
- package/src/llm-proxy.ts +32 -3
- package/src/shell-parse.ts +256 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.12] - 2026-07-20
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- **Shell-parse false denials from quoted patterns / args.** `extractShellBinaries`
|
|
7
|
+
no longer treats quote interiors or command arguments as binaries
|
|
8
|
+
(e.g. grep with a quoted alternation pattern returns only grep;
|
|
9
|
+
compound destroy commands no longer promote args to binaries).
|
|
10
|
+
Strips quotes/`$()`/backticks before operator split; stops segment scan
|
|
11
|
+
after a non-wrapper binary.
|
|
12
|
+
- **Hook schema lockouts from garbage binary tokens.** `before_tool_call` now
|
|
13
|
+
sanity-filters binary names, skips schema-ish authorize failures, and falls
|
|
14
|
+
back to first-token authz instead of hard-denying the whole command with a
|
|
15
|
+
Cedar entity/schema error.
|
|
16
|
+
- **`carapace_exec` compound-command bypass (C7).** Agent-facing shell tool now
|
|
17
|
+
uses the same multi-binary authorize helper as the hook (was first-token only).
|
|
18
|
+
- **`mcp_call` closed-schema brick.** No longer passes raw nested `arguments`
|
|
19
|
+
object as Cedar context; uses `params_json` + lifted scalars (same pattern as
|
|
20
|
+
the generic tool path).
|
|
21
|
+
- **LLM proxy shell path first-token only.** Proxy evaluation now multi-checks
|
|
22
|
+
compound shell commands via `extractShellBinaries`.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
- Eval engine docs: live path is native `@cedar-policy/cedar-wasm` (Cedarling kept
|
|
26
|
+
as a legacy/test dependency only). Package version **must** be 1.0.12 — local
|
|
27
|
+
1.0.11 already diverged from npm 1.0.11 (security packaging integrity).
|
|
28
|
+
|
|
29
|
+
|
|
3
30
|
## [1.0.8] - 2026-07-13
|
|
4
31
|
|
|
5
32
|
### Fixed
|
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ forbid(
|
|
|
58
58
|
|
|
59
59
|
Cedar has one critical property: **forbid always wins.** If any rule says "no," the action is blocked — no matter how many other rules say "yes." This means you can't accidentally create a loophole by adding a new "allow" rule that overrides your safety restrictions.
|
|
60
60
|
|
|
61
|
-
Carapace
|
|
61
|
+
Carapace evaluates policies with the official [`@cedar-policy/cedar-wasm`](https://www.npmjs.com/package/@cedar-policy/cedar-wasm) engine (fail-closed, boot self-test). Policy checks are sub-millisecond for typical agent tool calls.
|
|
62
62
|
|
|
63
63
|
### What is OpenClaw?
|
|
64
64
|
|
|
@@ -122,7 +122,7 @@ Open it at [http://localhost:19820](http://localhost:19820) after starting Carap
|
|
|
122
122
|
| | | every tool call |------->| (GitHub) |
|
|
123
123
|
| | | | | +-----------------+
|
|
124
124
|
| | | +----------------------+ |
|
|
125
|
-
| | | |
|
|
125
|
+
| | | | cedar-wasm | |
|
|
126
126
|
| | | | (Cedar 4.4.2) | |
|
|
127
127
|
| | | +----------------------+ |
|
|
128
128
|
| | | +----------------------+ |
|
|
@@ -139,7 +139,7 @@ Open it at [http://localhost:19820](http://localhost:19820) after starting Carap
|
|
|
139
139
|
**Key components:**
|
|
140
140
|
|
|
141
141
|
- **`before_tool_call` hook** — Registered in OpenClaw's plugin system. Every tool call passes through this hook before executing. Denied calls never reach the tool.
|
|
142
|
-
- **
|
|
142
|
+
- **Cedar WASM** — Official `@cedar-policy/cedar-wasm` engine. Fail-closed evaluation with a boot self-test that verifies `when`-clause gating.
|
|
143
143
|
- **Control GUI** — A local web dashboard for managing tools and policies. Single HTML file, no build step, dark theme.
|
|
144
144
|
|
|
145
145
|
---
|
|
@@ -372,7 +372,7 @@ npx tsx test/test-block-myself.mjs # End-to-end cp block demo
|
|
|
372
372
|
carapace/
|
|
373
373
|
├── src/
|
|
374
374
|
│ ├── index.ts # OpenClaw plugin entry — registers before_tool_call hook
|
|
375
|
-
│ ├── cedar-engine-cedarling.ts #
|
|
375
|
+
│ ├── cedar-engine-cedarling.ts # Native cedar-wasm engine (class name kept for compat)
|
|
376
376
|
│ ├── cedar-engine.ts # Fallback engine (string matching, no WASM needed)
|
|
377
377
|
│ ├── policy-source.ts # PolicySource for OVID-ME integration
|
|
378
378
|
│ ├── types.ts # Shared TypeScript types
|
|
@@ -411,7 +411,7 @@ More at [clawdrey.com](https://clawdrey.com).
|
|
|
411
411
|
### Built with
|
|
412
412
|
|
|
413
413
|
- **[Cedar](https://www.cedarpolicy.com/)** — Policy language by AWS. Human-readable rules with formal guarantees.
|
|
414
|
-
- **[
|
|
414
|
+
- **[@cedar-policy/cedar-wasm](https://www.npmjs.com/package/@cedar-policy/cedar-wasm)** — Official Cedar WASM engine. (Legacy Cedarling dependency retained only for older test harnesses.)
|
|
415
415
|
- **[MCP](https://modelcontextprotocol.io/)** — Open protocol for connecting AI agents to tools.
|
|
416
416
|
- **[OpenClaw](https://github.com/openclaw/openclaw)** — Open-source AI agent platform.
|
|
417
417
|
- **[OVID](https://github.com/clawdreyhepburn/ovid)** — Cryptographic identity + Cedar mandates for sub-agents (JWTs with EdDSA/Ed25519).
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Native Cedar engine for MCP tool authorization.
|
|
3
3
|
*
|
|
4
|
-
* Uses
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Uses the official `@cedar-policy/cedar-wasm` build of the AWS/cedar-policy
|
|
5
|
+
* Rust engine — the same crate family as the `cedar` CLI. It exposes
|
|
6
|
+
* `isAuthorized(call)` directly, so we no longer need Gluu's Cedarling policy
|
|
7
|
+
* store, JWT/OIDC machinery, JSONLogic principal-boolean-op, two-phase init,
|
|
8
|
+
* or the fragile `import.meta.resolve` WASM-path lookup.
|
|
9
|
+
*
|
|
10
|
+
* SECURITY MODEL (see carapace-engine-review-fable.md, MUST-FIX):
|
|
11
|
+
* 1. FAIL CLOSED on any evaluation error — never degrade to a string matcher
|
|
12
|
+
* that ignores `when { ... }` clauses.
|
|
13
|
+
* 2. HARD ERROR at startup if the engine cannot load or self-test — never
|
|
14
|
+
* boot into a degraded mode that prints "active".
|
|
15
|
+
* 3. BOOT SELF-TEST: evaluate a known `when`-gated deny against a matching
|
|
16
|
+
* context (expect DENY) and a non-matching context (expect ALLOW) and
|
|
17
|
+
* refuse to serve if the gate misbehaves.
|
|
18
|
+
*
|
|
19
|
+
* The class name `CedarlingEngine` is retained for drop-in compatibility with
|
|
20
|
+
* `src/index.ts` and the existing test suite; internally it is a native Cedar
|
|
21
|
+
* evaluator with no Cedarling dependency.
|
|
7
22
|
*/
|
|
8
23
|
import type { Logger, AuthzRequest, CedarDecision, VerifyResult, CedarSchemaInfo } from "./types.js";
|
|
9
24
|
export interface CedarlingEngineOpts {
|
|
@@ -21,46 +36,66 @@ export declare class CedarlingEngine {
|
|
|
21
36
|
private logger;
|
|
22
37
|
private namespace;
|
|
23
38
|
private agentEntityType;
|
|
24
|
-
private cedarling;
|
|
25
|
-
private wasmModule;
|
|
26
39
|
private policies;
|
|
27
40
|
private schemaJson;
|
|
28
41
|
private schemaRaw;
|
|
29
|
-
private
|
|
42
|
+
private lastPolicySignature;
|
|
30
43
|
private reloadInFlight;
|
|
31
44
|
private initialized;
|
|
45
|
+
private initInFlight;
|
|
46
|
+
private engineReady;
|
|
32
47
|
constructor(opts: CedarlingEngineOpts);
|
|
33
48
|
init(): Promise<void>;
|
|
34
49
|
/**
|
|
35
|
-
* Idempotently ensure policies are loaded from disk.
|
|
36
|
-
*
|
|
37
|
-
* The background service calls init() at startup, but read-only callers
|
|
38
|
-
* (the `carapace status`/`check`/`verify` CLI commands) run in a process
|
|
39
|
-
* where the service never started. Without this, getPolicies() returns an
|
|
40
|
-
* empty map and the CLI falsely reports "0 policies loaded" even though the
|
|
41
|
-
* live hook enforces correctly. Safe to call multiple times.
|
|
50
|
+
* Idempotently ensure policies are loaded from disk. Read-only CLI callers
|
|
51
|
+
* (status/check/verify) run in a process where the service never started.
|
|
42
52
|
*/
|
|
43
53
|
ensureLoaded(): Promise<void>;
|
|
44
54
|
/**
|
|
45
|
-
* Authorize a request
|
|
55
|
+
* Authorize a request with the native Cedar engine.
|
|
56
|
+
*
|
|
57
|
+
* FAIL CLOSED: any evaluation error, engine-not-ready, or parse failure
|
|
58
|
+
* returns a DENY. There is no string-matching fallback — degrading to a
|
|
59
|
+
* matcher that ignores `when` clauses is what the review flagged as worse
|
|
60
|
+
* than no guardrail.
|
|
46
61
|
*/
|
|
47
62
|
authorize(request: AuthzRequest): Promise<CedarDecision>;
|
|
48
63
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
64
|
+
* The single evaluation call site. Resolves entity references to the native
|
|
65
|
+
* engine's {type, id} shape and ALWAYS fully qualifies the type with the
|
|
66
|
+
* configured namespace (finding a: the hook may send unqualified refs like
|
|
67
|
+
* `Tool::"write"`; policies use `Jans::Tool::"write"`). Qualifying here — at
|
|
68
|
+
* the one call site — keeps entity identity consistent.
|
|
52
69
|
*/
|
|
53
|
-
|
|
70
|
+
private evaluate;
|
|
71
|
+
/**
|
|
72
|
+
* Fully qualify an entity {type, id}. If `type` is empty (a bare id) use the
|
|
73
|
+
* supplied default type. If `type` has no `::` namespace segment, prefix the
|
|
74
|
+
* configured namespace. Already-qualified types (containing `::`) pass
|
|
75
|
+
* through unchanged so callers can override the namespace explicitly.
|
|
76
|
+
*/
|
|
77
|
+
private qualify;
|
|
78
|
+
/** Build the Record<id, cedarText> static policy set for the native engine. */
|
|
79
|
+
private buildStaticPolicies;
|
|
80
|
+
/** Convert a native AuthorizationAnswer into Carapace's CedarDecision. */
|
|
81
|
+
private decisionFromAnswer;
|
|
54
82
|
/**
|
|
55
|
-
*
|
|
83
|
+
* BOOT SELF-TEST. Evaluates a known `when`-gated forbid against a matching
|
|
84
|
+
* and a non-matching context using an in-memory policy+schema (independent
|
|
85
|
+
* of on-disk policies). If condition evaluation regresses, `matching` would
|
|
86
|
+
* come back ALLOW (the exact silent-fallback failure) and we refuse to serve.
|
|
56
87
|
*/
|
|
88
|
+
private bootSelfTest;
|
|
89
|
+
/** Confirm the native engine module is callable; HARD ERROR otherwise. */
|
|
90
|
+
private loadEngine;
|
|
91
|
+
enableResource(qualifiedName: string, resourceType?: string, action?: string): void;
|
|
57
92
|
disableResource(qualifiedName: string, resourceType?: string, action?: string): void;
|
|
58
93
|
/** Backwards-compatible aliases */
|
|
59
94
|
enableTool(qualifiedName: string): void;
|
|
60
95
|
disableTool(qualifiedName: string): void;
|
|
61
96
|
/**
|
|
62
97
|
* Check if a tool is enabled (synchronous check against local policy state).
|
|
63
|
-
* Checks both specific tool policies AND blanket policies
|
|
98
|
+
* Checks both specific tool policies AND blanket policies.
|
|
64
99
|
*/
|
|
65
100
|
isToolEnabled(qualifiedName: string): boolean;
|
|
66
101
|
savePolicy(id: string, raw: string): void;
|
|
@@ -72,35 +107,46 @@ export declare class CedarlingEngine {
|
|
|
72
107
|
raw: string;
|
|
73
108
|
}>;
|
|
74
109
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
110
|
+
* True when the native Cedar engine is loaded, self-tested, and serving.
|
|
111
|
+
* With the native engine there is no degraded string-matcher mode: this is
|
|
112
|
+
* either fully active or the process refused to start. Retained for the
|
|
113
|
+
* existing test suite / GUI which query engine health.
|
|
114
|
+
*/
|
|
115
|
+
isWasmActive(): boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Content hash of the policy dir: sorted (name,size,content-hash) across
|
|
118
|
+
* *.cedar files. Unlike mtime+count this catches same-tick edits and edits
|
|
119
|
+
* that don't change file count or byte length.
|
|
77
120
|
*/
|
|
78
121
|
private policyDirSignature;
|
|
122
|
+
/** Recompute + store the signature after an in-process policy mutation. */
|
|
123
|
+
private refreshSignature;
|
|
79
124
|
/**
|
|
80
|
-
* Re-scan the policy directory and
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
125
|
+
* Re-scan the policy directory and reload if the on-disk policy set changed
|
|
126
|
+
* since the last load, keyed on a content hash (finding b). No engine
|
|
127
|
+
* rebuild is needed — the native engine takes policies per call — so this
|
|
128
|
+
* just refreshes the in-memory policy map.
|
|
84
129
|
*/
|
|
85
130
|
reloadIfChanged(): Promise<void>;
|
|
86
131
|
getSchema(): CedarSchemaInfo;
|
|
87
132
|
saveSchema(raw: string): void;
|
|
88
|
-
verify(): Promise<VerifyResult>;
|
|
89
|
-
private loadWasm;
|
|
90
|
-
/**
|
|
91
|
-
* Rebuild the Cedarling instance from current policies and schema.
|
|
92
|
-
* Called after any policy or schema change.
|
|
93
|
-
*/
|
|
94
|
-
private rebuildCedarling;
|
|
95
133
|
/**
|
|
96
|
-
*
|
|
134
|
+
* Verify that policies + schema evaluate cleanly. Runs a probe authorize per
|
|
135
|
+
* resource type; a native evaluation FAILURE (bad policy/schema) surfaces as
|
|
136
|
+
* an issue. Also re-asserts the boot self-test so `verify` is a full health
|
|
137
|
+
* gate.
|
|
97
138
|
*/
|
|
98
|
-
|
|
139
|
+
verify(): Promise<VerifyResult>;
|
|
99
140
|
private loadPoliciesFromDisk;
|
|
100
141
|
private writePolicyFile;
|
|
101
142
|
private removePolicyFile;
|
|
102
143
|
private writeDefaultSchema;
|
|
144
|
+
/**
|
|
145
|
+
* Context attributes shared by tool-call actions. Cedar records are CLOSED,
|
|
146
|
+
* so the hook serializes params to `params_json` plus a couple of commonly
|
|
147
|
+
* matched scalars (`path`, `action`). Policies match with `like` globs.
|
|
148
|
+
*/
|
|
149
|
+
private toolContextAttributes;
|
|
103
150
|
private buildDefaultSchemaJson;
|
|
104
|
-
private authorizeBasic;
|
|
105
151
|
private parseSchemaForGui;
|
|
106
152
|
}
|