@clawdreyhepburn/carapace 1.0.11 → 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 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 uses [Cedarling](https://github.com/JanssenProject/jans/tree/main/jans-cedarling), a high-performance Cedar engine compiled to WebAssembly, so policy checks run in under 6 milliseconds.
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
- | | | | Cedarling WASM | |
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
- - **Cedarling WASM** — The Cedar policy engine, running as WebAssembly for near-native speed. This is where your policies are evaluated.
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 # Cedarling WASM engine real Cedar 4.4.2 evaluation
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
- - **[Cedarling](https://github.com/JanssenProject/jans/tree/main/jans-cedarling)** — Cedar engine by [Gluu](https://gluu.org/), compiled to WebAssembly for speed.
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
- * Cedarling-powered Cedar engine for MCP tool authorization.
2
+ * Native Cedar engine for MCP tool authorization.
3
3
  *
4
- * Uses Gluu's Cedarling WASM module for proper Cedar evaluation,
5
- * JWT validation, and the Policy Store format. Falls back to the
6
- * homebrew engine if WASM loading fails.
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 lastPolicyMtimeMs;
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 using Cedarling WASM.
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
- * Enable a resource by adding a permit policy and rebuilding Cedarling.
50
- * resourceType: "Tool" | "Shell" | "API"
51
- * action: the Cedar action name (e.g., "call_tool", "exec_command", "call_api")
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
- enableResource(qualifiedName: string, resourceType?: string, action?: string): void;
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
- * Disable a resource by adding a forbid policy and rebuilding Cedarling.
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 (those without a specific tool name).
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,56 +107,46 @@ export declare class CedarlingEngine {
72
107
  raw: string;
73
108
  }>;
74
109
  /**
75
- * True when the Cedarling WASM engine is loaded and active. When false, the
76
- * engine uses the basic string-matching fallback, which cannot evaluate
77
- * `when { ... }` condition clauses (path globs etc.). Callers/tests that
78
- * rely on condition evaluation should check this.
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.
79
114
  */
80
115
  isWasmActive(): boolean;
81
116
  /**
82
- * Compute the newest mtime (ms) across *.cedar files in the policy dir, plus
83
- * a count so that deletions are also detected (count change flips the key).
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.
84
120
  */
85
121
  private policyDirSignature;
122
+ /** Recompute + store the signature after an in-process policy mutation. */
123
+ private refreshSignature;
86
124
  /**
87
- * Re-scan the policy directory and rebuild the Cedarling instance if the
88
- * on-disk policy set changed since the last load. Cheap when nothing
89
- * changed (a directory stat + per-file stat). This closes the gap where
90
- * policies added/edited after boot were never enforced until a restart.
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.
91
129
  */
92
130
  reloadIfChanged(): Promise<void>;
93
131
  getSchema(): CedarSchemaInfo;
94
132
  saveSchema(raw: string): void;
95
- verify(): Promise<VerifyResult>;
96
- private loadWasm;
97
- /**
98
- * Rebuild the Cedarling instance from current policies and schema.
99
- * Called after any policy or schema change.
100
- */
101
- private rebuildCedarling;
102
133
  /**
103
- * Build a Cedarling Policy Store JSON from current policies and schema.
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.
104
138
  */
105
- private buildPolicyStore;
139
+ verify(): Promise<VerifyResult>;
106
140
  private loadPoliciesFromDisk;
107
141
  private writePolicyFile;
108
142
  private removePolicyFile;
109
143
  private writeDefaultSchema;
110
144
  /**
111
- * Context attributes shared by tool-call actions.
112
- *
113
- * The before_tool_call hook cannot know every tool's parameter shape ahead
114
- * of time, and Cedar records are CLOSED (an undeclared attribute makes
115
- * Cedarling reject the whole context). So instead of surfacing the raw,
116
- * open params object, the hook serializes params to a single JSON string
117
- * (`params_json`) plus a couple of commonly-matched scalars (`path`,
118
- * `action`). Policies match with `like` globs, e.g.
119
- * when { context.path like "*openclaw.json*" }
120
- * when { context.params_json like "*\"secret\"*" }
121
- * All optional, so a call with empty context still validates.
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.
122
148
  */
123
149
  private toolContextAttributes;
124
150
  private buildDefaultSchemaJson;
125
- private authorizeBasic;
126
151
  private parseSchemaForGui;
127
152
  }