@agenshield/broker 0.5.0 → 0.6.1

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.
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Daemon Policy Forwarding
3
+ *
4
+ * Shared module for forwarding policy checks to the daemon's RPC endpoint.
5
+ * Used by both the policy_check handler and the top-level processRequest()
6
+ * in server.ts / http-fallback.ts when the broker's local enforcer denies
7
+ * a request but the daemon may have a user-defined policy that allows it.
8
+ */
9
+ export interface DaemonPolicyResult {
10
+ allowed: boolean;
11
+ policyId?: string;
12
+ reason?: string;
13
+ }
14
+ /**
15
+ * Forward a policy check to the daemon's RPC endpoint.
16
+ *
17
+ * The daemon evaluates user-defined policies (created in the UI).
18
+ * We only accept the daemon's result if it returns `allowed: true`
19
+ * AND includes a `policyId` (explicit user policy match).
20
+ * A default-allow (no policyId) is NOT trusted — we keep the broker denial.
21
+ *
22
+ * @returns The daemon's result if it explicitly allows, or null to keep broker denial.
23
+ */
24
+ export declare function forwardPolicyToDaemon(operation: string, target: string, daemonUrl: string): Promise<DaemonPolicyResult | null>;
25
+ //# sourceMappingURL=daemon-forward.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-forward.d.ts","sourceRoot":"","sources":["../src/daemon-forward.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAiDpC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Events Batch Handler
3
+ *
4
+ * Accepts batches of interceptor events for audit logging.
5
+ * The interceptor's EventReporter periodically flushes events
6
+ * to the broker via this RPC method.
7
+ */
8
+ import type { HandlerContext, HandlerResult } from '../types.js';
9
+ import type { HandlerDependencies } from './types.js';
10
+ export declare function handleEventsBatch(params: Record<string, unknown>, context: HandlerContext, deps: HandlerDependencies): Promise<HandlerResult<{
11
+ received: number;
12
+ }>>;
13
+ //# sourceMappingURL=events-batch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events-batch.d.ts","sourceRoot":"","sources":["../../src/handlers/events-batch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAc,MAAM,aAAa,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAOtD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,aAAa,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAuB9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/handlers/exec.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAc,UAAU,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AA+FtD,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CA0GpC"}
1
+ {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/handlers/exec.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAc,UAAU,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAgGtD,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CA+GpC"}
@@ -8,5 +8,7 @@ export { handleOpenUrl } from './open-url.js';
8
8
  export { handleSecretInject } from './secret-inject.js';
9
9
  export { handlePing } from './ping.js';
10
10
  export { handleSkillInstall, handleSkillUninstall } from './skill-install.js';
11
+ export { handlePolicyCheck } from './policy-check.js';
12
+ export { handleEventsBatch } from './events-batch.js';
11
13
  export type { HandlerDependencies } from './types.js';
12
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE9E,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Policy Check Handler
3
+ *
4
+ * Handles policy_check RPC calls from the interceptor.
5
+ * The interceptor sends { operation, target } and this handler
6
+ * evaluates the inner operation against the policy enforcer.
7
+ *
8
+ * If the broker's enforcer denies the request, we forward to the
9
+ * daemon's RPC endpoint which checks user-defined policies.
10
+ */
11
+ import type { HandlerContext, HandlerResult } from '../types.js';
12
+ import type { HandlerDependencies } from './types.js';
13
+ interface PolicyCheckResultData {
14
+ allowed: boolean;
15
+ policyId?: string;
16
+ reason?: string;
17
+ }
18
+ export declare function handlePolicyCheck(params: Record<string, unknown>, context: HandlerContext, deps: HandlerDependencies): Promise<HandlerResult<PolicyCheckResultData>>;
19
+ export {};
20
+ //# sourceMappingURL=policy-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-check.d.ts","sourceRoot":"","sources":["../../src/handlers/policy-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAQtD,UAAU,qBAAqB;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAKD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC,CAoE/C"}
@@ -24,5 +24,6 @@ export interface HandlerDependencies {
24
24
  commandAllowlist: CommandAllowlist;
25
25
  onExecMonitor?: (event: ExecMonitorEvent) => void;
26
26
  onExecDenied?: (command: string, reason: string) => void;
27
+ daemonUrl?: string;
27
28
  }
28
29
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/handlers/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1D"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/handlers/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
@@ -7,16 +7,19 @@
7
7
  import type { BrokerConfig } from './types.js';
8
8
  import type { PolicyEnforcer } from './policies/enforcer.js';
9
9
  import type { AuditLogger } from './audit/logger.js';
10
+ import type { CommandAllowlist } from './policies/command-allowlist.js';
10
11
  export interface HttpFallbackServerOptions {
11
12
  config: BrokerConfig;
12
13
  policyEnforcer: PolicyEnforcer;
13
14
  auditLogger: AuditLogger;
15
+ commandAllowlist: CommandAllowlist;
14
16
  }
15
17
  export declare class HttpFallbackServer {
16
18
  private server;
17
19
  private config;
18
20
  private policyEnforcer;
19
21
  private auditLogger;
22
+ private commandAllowlist;
20
23
  constructor(options: HttpFallbackServerOptions);
21
24
  /**
22
25
  * Start the HTTP fallback server
@@ -1 +1 @@
1
- {"version":3,"file":"http-fallback.d.ts","sourceRoot":"","sources":["../src/http-fallback.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAmBrD,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,YAAY,CAAC;IACrB,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,WAAW,CAAc;gBAErB,OAAO,EAAE,yBAAyB;IAM9C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B;;OAEG;YACW,aAAa;IA6C3B;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;YACW,cAAc;IAyH5B;;OAEG;IACH,OAAO,CAAC,UAAU;IAoBlB;;OAEG;IACH,OAAO,CAAC,aAAa;IAWrB;;OAEG;IACH,OAAO,CAAC,aAAa;CAWtB"}
1
+ {"version":3,"file":"http-fallback.d.ts","sourceRoot":"","sources":["../src/http-fallback.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAsBxE,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,YAAY,CAAC;IACrB,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,gBAAgB,CAAmB;gBAE/B,OAAO,EAAE,yBAAyB;IAO9C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B;;OAEG;YACW,aAAa;IA6C3B;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;YACW,cAAc;IAuI5B;;OAEG;IACH,OAAO,CAAC,UAAU;IAsBlB;;OAEG;IACH,OAAO,CAAC,aAAa;IAWrB;;OAEG;IACH,OAAO,CAAC,aAAa;CAWtB"}
package/index.js CHANGED
@@ -249,6 +249,47 @@ function matchPattern(name, pattern) {
249
249
  // libs/shield-broker/src/handlers/exec.ts
250
250
  import * as path2 from "node:path";
251
251
  import { spawn } from "node:child_process";
252
+
253
+ // libs/shield-broker/src/daemon-forward.ts
254
+ var DAEMON_RPC_TIMEOUT = 2e3;
255
+ async function forwardPolicyToDaemon(operation, target, daemonUrl) {
256
+ try {
257
+ const controller = new AbortController();
258
+ const timeout = setTimeout(() => controller.abort(), DAEMON_RPC_TIMEOUT);
259
+ const response = await fetch(`${daemonUrl}/rpc`, {
260
+ method: "POST",
261
+ headers: { "Content-Type": "application/json" },
262
+ body: JSON.stringify({
263
+ jsonrpc: "2.0",
264
+ id: `broker-fwd-${Date.now()}`,
265
+ method: "policy_check",
266
+ params: { operation, target }
267
+ }),
268
+ signal: controller.signal
269
+ });
270
+ clearTimeout(timeout);
271
+ if (!response.ok) {
272
+ return null;
273
+ }
274
+ const json = await response.json();
275
+ if (json.error || !json.result) {
276
+ return null;
277
+ }
278
+ const result = json.result;
279
+ if (result.policyId) {
280
+ return {
281
+ allowed: !!result.allowed,
282
+ policyId: result.policyId,
283
+ reason: result.reason
284
+ };
285
+ }
286
+ return null;
287
+ } catch {
288
+ return null;
289
+ }
290
+ }
291
+
292
+ // libs/shield-broker/src/handlers/exec.ts
252
293
  var MAX_OUTPUT_SIZE = 10 * 1024 * 1024;
253
294
  var DEFAULT_WORKSPACE = "/Users/clawagent/workspace";
254
295
  var FS_COMMANDS = /* @__PURE__ */ new Set([
@@ -381,12 +422,16 @@ async function handleExec(params, context, deps) {
381
422
  if (url) {
382
423
  const networkCheck = await deps.policyEnforcer.check("http_request", { url }, context);
383
424
  if (!networkCheck.allowed) {
384
- const reason = `URL not allowed: ${url} - ${networkCheck.reason}`;
385
- deps.onExecDenied?.(command, reason);
386
- return {
387
- success: false,
388
- error: { code: 1009, message: reason }
389
- };
425
+ const daemonUrl = deps.daemonUrl || "http://127.0.0.1:5200";
426
+ const override = await forwardPolicyToDaemon("http_request", url, daemonUrl);
427
+ if (!override || !override.allowed) {
428
+ const reason = `URL not allowed: ${url} - ${networkCheck.reason}`;
429
+ deps.onExecDenied?.(command, reason);
430
+ return {
431
+ success: false,
432
+ error: { code: 1009, message: reason }
433
+ };
434
+ }
390
435
  }
391
436
  }
392
437
  }
@@ -805,6 +850,86 @@ async function handleSkillUninstall(params, context, deps) {
805
850
  }
806
851
  }
807
852
 
853
+ // libs/shield-broker/src/handlers/policy-check.ts
854
+ var DEFAULT_DAEMON_URL = "http://127.0.0.1:5200";
855
+ async function handlePolicyCheck(params, context, deps) {
856
+ const { operation, target } = params;
857
+ if (!operation) {
858
+ return {
859
+ success: false,
860
+ error: { code: -32602, message: "Missing required parameter: operation" }
861
+ };
862
+ }
863
+ let checkParams;
864
+ switch (operation) {
865
+ case "http_request":
866
+ case "open_url":
867
+ checkParams = { url: target || "" };
868
+ break;
869
+ case "file_read":
870
+ case "file_write":
871
+ case "file_list":
872
+ checkParams = { path: target || "" };
873
+ break;
874
+ case "exec":
875
+ checkParams = { command: target || "" };
876
+ break;
877
+ case "secret_inject":
878
+ checkParams = { name: target || "" };
879
+ break;
880
+ default:
881
+ checkParams = { target: target || "" };
882
+ break;
883
+ }
884
+ const result = await deps.policyEnforcer.check(operation, checkParams, context);
885
+ if (result.allowed) {
886
+ return {
887
+ success: true,
888
+ data: {
889
+ allowed: true,
890
+ policyId: result.policyId,
891
+ reason: result.reason
892
+ }
893
+ };
894
+ }
895
+ const daemonUrl = deps.daemonUrl || DEFAULT_DAEMON_URL;
896
+ const daemonResult = await forwardPolicyToDaemon(operation, target || "", daemonUrl);
897
+ if (daemonResult && daemonResult.allowed) {
898
+ return { success: true, data: daemonResult };
899
+ }
900
+ return {
901
+ success: true,
902
+ data: {
903
+ allowed: false,
904
+ policyId: result.policyId,
905
+ reason: result.reason
906
+ }
907
+ };
908
+ }
909
+
910
+ // libs/shield-broker/src/handlers/events-batch.ts
911
+ async function handleEventsBatch(params, context, deps) {
912
+ const { events } = params;
913
+ const eventList = events || [];
914
+ for (const event of eventList) {
915
+ const entry = {
916
+ id: event.id || context.requestId,
917
+ timestamp: event.timestamp ? new Date(event.timestamp) : /* @__PURE__ */ new Date(),
918
+ operation: event.operation || "events_batch",
919
+ channel: "socket",
920
+ allowed: event.allowed ?? true,
921
+ target: event.target || "",
922
+ result: event.allowed === false ? "denied" : "success",
923
+ durationMs: 0
924
+ };
925
+ await deps.auditLogger.log(entry);
926
+ }
927
+ return {
928
+ success: true,
929
+ data: { received: eventList.length }
930
+ };
931
+ }
932
+
808
933
  // libs/shield-broker/src/server.ts
809
934
  var UnixSocketServer = class {
810
935
  server = null;
@@ -812,12 +937,14 @@ var UnixSocketServer = class {
812
937
  policyEnforcer;
813
938
  auditLogger;
814
939
  secretVault;
940
+ commandAllowlist;
815
941
  connections = /* @__PURE__ */ new Set();
816
942
  constructor(options) {
817
943
  this.config = options.config;
818
944
  this.policyEnforcer = options.policyEnforcer;
819
945
  this.auditLogger = options.auditLogger;
820
946
  this.secretVault = options.secretVault;
947
+ this.commandAllowlist = options.commandAllowlist;
821
948
  }
822
949
  /**
823
950
  * Start the Unix socket server
@@ -921,20 +1048,29 @@ var UnixSocketServer = class {
921
1048
  request.params,
922
1049
  context
923
1050
  );
924
- if (!policyResult.allowed) {
1051
+ let finalPolicy = policyResult;
1052
+ if (!policyResult.allowed && request.method !== "policy_check") {
1053
+ const target = this.extractTarget(request);
1054
+ const daemonUrl = this.config.daemonUrl || "http://127.0.0.1:5200";
1055
+ const override = await forwardPolicyToDaemon(request.method, target, daemonUrl);
1056
+ if (override) {
1057
+ finalPolicy = override;
1058
+ }
1059
+ }
1060
+ if (!finalPolicy.allowed) {
925
1061
  await this.auditLogger.log({
926
1062
  id: requestId,
927
1063
  timestamp: /* @__PURE__ */ new Date(),
928
1064
  operation: request.method,
929
1065
  channel: "socket",
930
1066
  allowed: false,
931
- policyId: policyResult.policyId,
1067
+ policyId: finalPolicy.policyId,
932
1068
  target: this.extractTarget(request),
933
1069
  result: "denied",
934
- errorMessage: policyResult.reason,
1070
+ errorMessage: finalPolicy.reason,
935
1071
  durationMs: Date.now() - startTime
936
1072
  });
937
- return this.errorResponse(request.id, 1001, policyResult.reason || "Policy denied");
1073
+ return this.errorResponse(request.id, 1001, finalPolicy.reason || "Policy denied");
938
1074
  }
939
1075
  const handler = this.getHandler(request.method);
940
1076
  if (!handler) {
@@ -943,7 +1079,9 @@ var UnixSocketServer = class {
943
1079
  const result = await handler(request.params, context, {
944
1080
  policyEnforcer: this.policyEnforcer,
945
1081
  auditLogger: this.auditLogger,
946
- secretVault: this.secretVault
1082
+ secretVault: this.secretVault,
1083
+ commandAllowlist: this.commandAllowlist,
1084
+ daemonUrl: this.config.daemonUrl
947
1085
  });
948
1086
  await this.auditLogger.log({
949
1087
  id: requestId,
@@ -951,7 +1089,7 @@ var UnixSocketServer = class {
951
1089
  operation: request.method,
952
1090
  channel: "socket",
953
1091
  allowed: true,
954
- policyId: policyResult.policyId,
1092
+ policyId: finalPolicy.policyId,
955
1093
  target: this.extractTarget(request),
956
1094
  result: result.success ? "success" : "error",
957
1095
  errorMessage: result.error?.message,
@@ -990,7 +1128,9 @@ var UnixSocketServer = class {
990
1128
  secret_inject: handleSecretInject,
991
1129
  ping: handlePing,
992
1130
  skill_install: handleSkillInstall,
993
- skill_uninstall: handleSkillUninstall
1131
+ skill_uninstall: handleSkillUninstall,
1132
+ policy_check: handlePolicyCheck,
1133
+ events_batch: handleEventsBatch
994
1134
  };
995
1135
  return handlerMap[method];
996
1136
  }
@@ -1021,7 +1161,9 @@ var HTTP_ALLOWED_OPERATIONS = /* @__PURE__ */ new Set([
1021
1161
  "file_read",
1022
1162
  "file_list",
1023
1163
  "open_url",
1024
- "ping"
1164
+ "ping",
1165
+ "policy_check",
1166
+ "events_batch"
1025
1167
  ]);
1026
1168
  var HTTP_DENIED_OPERATIONS = /* @__PURE__ */ new Set([
1027
1169
  "exec",
@@ -1033,10 +1175,12 @@ var HttpFallbackServer = class {
1033
1175
  config;
1034
1176
  policyEnforcer;
1035
1177
  auditLogger;
1178
+ commandAllowlist;
1036
1179
  constructor(options) {
1037
1180
  this.config = options.config;
1038
1181
  this.policyEnforcer = options.policyEnforcer;
1039
1182
  this.auditLogger = options.auditLogger;
1183
+ this.commandAllowlist = options.commandAllowlist;
1040
1184
  }
1041
1185
  /**
1042
1186
  * Start the HTTP fallback server
@@ -1157,20 +1301,29 @@ var HttpFallbackServer = class {
1157
1301
  request.params,
1158
1302
  context
1159
1303
  );
1160
- if (!policyResult.allowed) {
1304
+ let finalPolicy = policyResult;
1305
+ if (!policyResult.allowed && request.method !== "policy_check") {
1306
+ const target = this.extractTarget(request);
1307
+ const daemonUrl = this.config.daemonUrl || "http://127.0.0.1:5200";
1308
+ const override = await forwardPolicyToDaemon(request.method, target, daemonUrl);
1309
+ if (override) {
1310
+ finalPolicy = override;
1311
+ }
1312
+ }
1313
+ if (!finalPolicy.allowed) {
1161
1314
  await this.auditLogger.log({
1162
1315
  id: requestId,
1163
1316
  timestamp: /* @__PURE__ */ new Date(),
1164
1317
  operation: request.method,
1165
1318
  channel: "http",
1166
1319
  allowed: false,
1167
- policyId: policyResult.policyId,
1320
+ policyId: finalPolicy.policyId,
1168
1321
  target: this.extractTarget(request),
1169
1322
  result: "denied",
1170
- errorMessage: policyResult.reason,
1323
+ errorMessage: finalPolicy.reason,
1171
1324
  durationMs: Date.now() - startTime
1172
1325
  });
1173
- return this.errorResponse(request.id, 1001, policyResult.reason || "Policy denied");
1326
+ return this.errorResponse(request.id, 1001, finalPolicy.reason || "Policy denied");
1174
1327
  }
1175
1328
  const handler = this.getHandler(request.method);
1176
1329
  if (!handler) {
@@ -1179,8 +1332,10 @@ var HttpFallbackServer = class {
1179
1332
  const result = await handler(request.params, context, {
1180
1333
  policyEnforcer: this.policyEnforcer,
1181
1334
  auditLogger: this.auditLogger,
1182
- secretVault: null
1335
+ secretVault: null,
1183
1336
  // Not available over HTTP
1337
+ commandAllowlist: this.commandAllowlist,
1338
+ daemonUrl: this.config.daemonUrl
1184
1339
  });
1185
1340
  await this.auditLogger.log({
1186
1341
  id: requestId,
@@ -1188,7 +1343,7 @@ var HttpFallbackServer = class {
1188
1343
  operation: request.method,
1189
1344
  channel: "http",
1190
1345
  allowed: true,
1191
- policyId: policyResult.policyId,
1346
+ policyId: finalPolicy.policyId,
1192
1347
  target: this.extractTarget(request),
1193
1348
  result: result.success ? "success" : "error",
1194
1349
  errorMessage: result.error?.message,
@@ -1222,7 +1377,9 @@ var HttpFallbackServer = class {
1222
1377
  file_read: handleFileRead,
1223
1378
  file_list: handleFileList,
1224
1379
  open_url: handleOpenUrl,
1225
- ping: handlePing
1380
+ ping: handlePing,
1381
+ policy_check: handlePolicyCheck,
1382
+ events_batch: handleEventsBatch
1226
1383
  };
1227
1384
  return handlerMap[method];
1228
1385
  }
@@ -1261,6 +1418,34 @@ var PolicyEnforcer = class {
1261
1418
  this.policies = options.defaultPolicies;
1262
1419
  this.loadPolicies();
1263
1420
  }
1421
+ /**
1422
+ * Normalize a policy rule — infer operations from target when missing,
1423
+ * default priority to 0.
1424
+ */
1425
+ normalizeRule(rule) {
1426
+ const normalized = { ...rule };
1427
+ if (!normalized.priority && normalized.priority !== 0) {
1428
+ normalized.priority = 0;
1429
+ }
1430
+ if (normalized.operations && normalized.operations.length > 0) {
1431
+ return normalized;
1432
+ }
1433
+ switch (normalized.target) {
1434
+ case "url":
1435
+ normalized.operations = ["http_request", "open_url"];
1436
+ break;
1437
+ case "command":
1438
+ normalized.operations = ["exec"];
1439
+ break;
1440
+ case "skill":
1441
+ normalized.operations = ["skill_install", "skill_uninstall"];
1442
+ break;
1443
+ default:
1444
+ normalized.operations = ["*"];
1445
+ break;
1446
+ }
1447
+ return normalized;
1448
+ }
1264
1449
  /**
1265
1450
  * Load policies from disk
1266
1451
  */
@@ -1273,7 +1458,7 @@ var PolicyEnforcer = class {
1273
1458
  this.policies = {
1274
1459
  ...this.policies,
1275
1460
  ...loaded,
1276
- rules: [...this.policies.rules, ...loaded.rules || []]
1461
+ rules: [...this.policies.rules, ...(loaded.rules || []).map((r) => this.normalizeRule(r))]
1277
1462
  };
1278
1463
  this.lastLoad = Date.now();
1279
1464
  } catch (error) {
@@ -1289,7 +1474,7 @@ var PolicyEnforcer = class {
1289
1474
  const content = fs4.readFileSync(path4.join(customDir, file), "utf-8");
1290
1475
  const custom = JSON.parse(content);
1291
1476
  if (custom.rules) {
1292
- this.policies.rules.push(...custom.rules);
1477
+ this.policies.rules.push(...custom.rules.map((r) => this.normalizeRule(r)));
1293
1478
  }
1294
1479
  }
1295
1480
  }
@@ -1339,6 +1524,12 @@ var PolicyEnforcer = class {
1339
1524
  if (!constraintResult.allowed) {
1340
1525
  return constraintResult;
1341
1526
  }
1527
+ if (["file_read", "file_write", "file_list"].includes(operation) && this.policies.fsConstraints) {
1528
+ return { allowed: true, reason: "Allowed by file system constraints" };
1529
+ }
1530
+ if (operation === "http_request" && this.policies.networkConstraints) {
1531
+ return { allowed: true, reason: "Allowed by network constraints" };
1532
+ }
1342
1533
  return {
1343
1534
  allowed: this.policies.defaultAction === "allow",
1344
1535
  reason: this.policies.defaultAction === "deny" ? "No matching allow policy" : void 0
@@ -1518,6 +1709,28 @@ var BuiltinPolicies = [
1518
1709
  enabled: true,
1519
1710
  priority: 1e3
1520
1711
  },
1712
+ // Allow interceptor policy checks (internal RPC — must not be subject to policy gate)
1713
+ {
1714
+ id: "builtin-allow-policy-check",
1715
+ name: "Allow interceptor policy checks",
1716
+ action: "allow",
1717
+ target: "command",
1718
+ operations: ["policy_check"],
1719
+ patterns: ["*"],
1720
+ enabled: true,
1721
+ priority: 1e3
1722
+ },
1723
+ // Allow interceptor event reporting (internal RPC)
1724
+ {
1725
+ id: "builtin-allow-events-batch",
1726
+ name: "Allow interceptor event reporting",
1727
+ action: "allow",
1728
+ target: "command",
1729
+ operations: ["events_batch"],
1730
+ patterns: ["*"],
1731
+ enabled: true,
1732
+ priority: 1e3
1733
+ },
1521
1734
  // Allow skill installation/uninstallation (daemon management operations)
1522
1735
  {
1523
1736
  id: "builtin-allow-skill-management",
@@ -1538,9 +1751,13 @@ var BuiltinPolicies = [
1538
1751
  operations: ["http_request"],
1539
1752
  patterns: [
1540
1753
  "http://localhost:*",
1754
+ "http://localhost:*/**",
1541
1755
  "http://127.0.0.1:*",
1756
+ "http://127.0.0.1:*/**",
1542
1757
  "https://localhost:*",
1543
- "https://127.0.0.1:*"
1758
+ "https://localhost:*/**",
1759
+ "https://127.0.0.1:*",
1760
+ "https://127.0.0.1:*/**"
1544
1761
  ],
1545
1762
  enabled: true,
1546
1763
  priority: 100
@@ -1640,10 +1857,15 @@ var BuiltinPolicies = [
1640
1857
  target: "url",
1641
1858
  operations: ["http_request"],
1642
1859
  patterns: [
1860
+ "https://api.anthropic.com",
1643
1861
  "https://api.anthropic.com/**",
1862
+ "https://api.openai.com",
1644
1863
  "https://api.openai.com/**",
1864
+ "https://api.cohere.ai",
1645
1865
  "https://api.cohere.ai/**",
1866
+ "https://generativelanguage.googleapis.com",
1646
1867
  "https://generativelanguage.googleapis.com/**",
1868
+ "https://api.mistral.ai",
1647
1869
  "https://api.mistral.ai/**"
1648
1870
  ],
1649
1871
  enabled: true,
@@ -1657,10 +1879,15 @@ var BuiltinPolicies = [
1657
1879
  target: "url",
1658
1880
  operations: ["http_request"],
1659
1881
  patterns: [
1882
+ "https://registry.npmjs.org",
1660
1883
  "https://registry.npmjs.org/**",
1884
+ "https://pypi.org",
1661
1885
  "https://pypi.org/**",
1886
+ "https://files.pythonhosted.org",
1662
1887
  "https://files.pythonhosted.org/**",
1888
+ "https://crates.io",
1663
1889
  "https://crates.io/**",
1890
+ "https://rubygems.org",
1664
1891
  "https://rubygems.org/**"
1665
1892
  ],
1666
1893
  enabled: true,
@@ -1674,23 +1901,28 @@ var BuiltinPolicies = [
1674
1901
  target: "url",
1675
1902
  operations: ["http_request"],
1676
1903
  patterns: [
1904
+ "https://github.com",
1677
1905
  "https://github.com/**",
1906
+ "https://api.github.com",
1678
1907
  "https://api.github.com/**",
1908
+ "https://raw.githubusercontent.com",
1679
1909
  "https://raw.githubusercontent.com/**",
1910
+ "https://gist.github.com",
1680
1911
  "https://gist.github.com/**"
1681
1912
  ],
1682
1913
  enabled: true,
1683
1914
  priority: 50
1684
1915
  }
1685
1916
  ];
1686
- function getDefaultPolicies() {
1917
+ function getDefaultPolicies(options) {
1918
+ const agentHome = options?.agentHome || process.env["AGENSHIELD_AGENT_HOME"] || "/Users/clawagent";
1687
1919
  return {
1688
1920
  version: "1.0.0",
1689
1921
  defaultAction: "deny",
1690
1922
  rules: [...BuiltinPolicies],
1691
1923
  fsConstraints: {
1692
1924
  allowedPaths: [
1693
- "/Users/clawagent/workspace",
1925
+ agentHome,
1694
1926
  "/tmp/agenshield"
1695
1927
  ],
1696
1928
  deniedPatterns: [
@@ -2656,6 +2888,7 @@ export {
2656
2888
  SecretVault,
2657
2889
  UnixSocketServer,
2658
2890
  getDefaultPolicies,
2891
+ handleEventsBatch,
2659
2892
  handleExec,
2660
2893
  handleFileList,
2661
2894
  handleFileRead,
@@ -2663,6 +2896,7 @@ export {
2663
2896
  handleHttpRequest,
2664
2897
  handleOpenUrl,
2665
2898
  handlePing,
2899
+ handlePolicyCheck,
2666
2900
  handleSecretInject,
2667
2901
  handleSkillInstall,
2668
2902
  handleSkillUninstall