@cdot65/prisma-airs 0.2.2 → 0.2.4

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.
@@ -32,6 +32,7 @@ interface PluginConfig {
32
32
  config?: {
33
33
  tool_gating_enabled?: boolean;
34
34
  high_risk_tools?: string[];
35
+ api_key?: string;
35
36
  };
36
37
  };
37
38
  };
@@ -45,81 +46,84 @@ interface HookResult {
45
46
  blockReason?: string;
46
47
  }
47
48
 
49
+ // Shared tool lists
50
+ const ALL_EXTERNAL_TOOLS = [
51
+ "exec",
52
+ "Bash",
53
+ "bash",
54
+ "write",
55
+ "Write",
56
+ "edit",
57
+ "Edit",
58
+ "gateway",
59
+ "message",
60
+ "cron",
61
+ "browser",
62
+ "web_fetch",
63
+ "WebFetch",
64
+ "database",
65
+ "query",
66
+ "sql",
67
+ "eval",
68
+ "NotebookEdit",
69
+ ];
70
+ const DB_TOOLS = ["exec", "Bash", "bash", "database", "query", "sql", "eval"];
71
+ const CODE_TOOLS = [
72
+ "exec",
73
+ "Bash",
74
+ "bash",
75
+ "write",
76
+ "Write",
77
+ "edit",
78
+ "Edit",
79
+ "eval",
80
+ "NotebookEdit",
81
+ ];
82
+ const SENSITIVE_TOOLS = ["exec", "Bash", "bash", "gateway", "message", "cron"];
83
+ const WEB_TOOLS = ["web_fetch", "WebFetch", "browser", "Browser", "curl"];
84
+
48
85
  // Tool blocking rules by threat category
49
86
  const TOOL_BLOCKS: Record<string, string[]> = {
50
87
  // AI Agent threats - block ALL external actions
51
- "agent-threat": [
52
- "exec",
53
- "Bash",
54
- "bash",
55
- "write",
56
- "Write",
57
- "edit",
58
- "Edit",
59
- "gateway",
60
- "message",
61
- "cron",
62
- "browser",
63
- "web_fetch",
64
- "WebFetch",
65
- "database",
66
- "query",
67
- "sql",
68
- "eval",
69
- "NotebookEdit",
70
- ],
88
+ "agent-threat": ALL_EXTERNAL_TOOLS,
89
+ agent_threat: ALL_EXTERNAL_TOOLS,
90
+ agent_threat_prompt: ALL_EXTERNAL_TOOLS,
91
+ agent_threat_response: ALL_EXTERNAL_TOOLS,
71
92
 
72
93
  // SQL/Database injection - block database and exec tools
73
- "sql-injection": ["exec", "Bash", "bash", "database", "query", "sql", "eval"],
74
- db_security: ["exec", "Bash", "bash", "database", "query", "sql", "eval"],
75
- "db-security": ["exec", "Bash", "bash", "database", "query", "sql", "eval"],
94
+ "sql-injection": DB_TOOLS,
95
+ db_security: DB_TOOLS,
96
+ "db-security": DB_TOOLS,
97
+ db_security_response: DB_TOOLS,
76
98
 
77
99
  // Malicious code - block code execution and file writes
78
- "malicious-code": [
79
- "exec",
80
- "Bash",
81
- "bash",
82
- "write",
83
- "Write",
84
- "edit",
85
- "Edit",
86
- "eval",
87
- "NotebookEdit",
88
- ],
89
- malicious_code: [
90
- "exec",
91
- "Bash",
92
- "bash",
93
- "write",
94
- "Write",
95
- "edit",
96
- "Edit",
97
- "eval",
98
- "NotebookEdit",
99
- ],
100
+ "malicious-code": CODE_TOOLS,
101
+ malicious_code: CODE_TOOLS,
102
+ malicious_code_prompt: CODE_TOOLS,
103
+ malicious_code_response: CODE_TOOLS,
100
104
 
101
105
  // Prompt injection - block sensitive tools
102
- "prompt-injection": ["exec", "Bash", "bash", "gateway", "message", "cron"],
103
- prompt_injection: ["exec", "Bash", "bash", "gateway", "message", "cron"],
106
+ "prompt-injection": SENSITIVE_TOOLS,
107
+ prompt_injection: SENSITIVE_TOOLS,
104
108
 
105
109
  // Malicious URLs - block web access
106
- "malicious-url": ["web_fetch", "WebFetch", "browser", "Browser", "curl"],
107
- malicious_url: ["web_fetch", "WebFetch", "browser", "Browser", "curl"],
108
- url_filtering_prompt: ["web_fetch", "WebFetch", "browser", "Browser", "curl"],
110
+ "malicious-url": WEB_TOOLS,
111
+ malicious_url: WEB_TOOLS,
112
+ url_filtering_prompt: WEB_TOOLS,
113
+ url_filtering_response: WEB_TOOLS,
114
+
115
+ // Toxic content - block code/write tools
116
+ toxic_content: CODE_TOOLS,
117
+ toxic_content_prompt: CODE_TOOLS,
118
+ toxic_content_response: CODE_TOOLS,
119
+
120
+ // Topic violations - block sensitive tools
121
+ topic_violation: SENSITIVE_TOOLS,
122
+ topic_violation_prompt: SENSITIVE_TOOLS,
123
+ topic_violation_response: SENSITIVE_TOOLS,
109
124
 
110
125
  // Scan failure - block high-risk tools
111
- "scan-failure": [
112
- "exec",
113
- "Bash",
114
- "bash",
115
- "write",
116
- "Write",
117
- "edit",
118
- "Edit",
119
- "gateway",
120
- "message",
121
- "cron",
122
- ],
126
+ "scan-failure": SENSITIVE_TOOLS.concat(["write", "Write", "edit", "Edit"]),
123
127
  };
124
128
 
125
129
  // Default high-risk tools (blocked on any threat)
package/index.ts CHANGED
@@ -11,13 +11,17 @@
11
11
  */
12
12
 
13
13
  import { scan, isConfigured, ScanRequest } from "./src/scanner";
14
- import { fileURLToPath } from "url";
15
- import { dirname, join } from "path";
14
+ import guardHandler from "./hooks/prisma-airs-guard/handler";
15
+ import auditHandler from "./hooks/prisma-airs-audit/handler";
16
+ import contextHandler from "./hooks/prisma-airs-context/handler";
17
+ import outboundHandler from "./hooks/prisma-airs-outbound/handler";
18
+ import toolsHandler from "./hooks/prisma-airs-tools/handler";
16
19
 
17
20
  // Plugin config interface
18
21
  interface PrismaAirsConfig {
19
22
  profile_name?: string;
20
23
  app_name?: string;
24
+ api_key?: string;
21
25
  reminder_enabled?: boolean;
22
26
  }
23
27
 
@@ -72,7 +76,8 @@ interface PluginApi {
72
76
  execute: (_id: string, params: ScanRequest) => Promise<ToolResult>;
73
77
  }) => void;
74
78
  registerCli: (setup: (ctx: { program: unknown }) => void, opts: { commands: string[] }) => void;
75
- registerPluginHooksFromDir?: (dir: string) => void;
79
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
80
+ on: (hookName: string, handler: (...args: any[]) => any, opts?: { priority?: number }) => void;
76
81
  }
77
82
 
78
83
  // Get plugin config from OpenClaw config
@@ -91,6 +96,7 @@ function buildScanRequest(params: ScanRequest | undefined, config: PrismaAirsCon
91
96
  appName: params?.appName ?? config.app_name ?? "openclaw",
92
97
  appUser: params?.appUser,
93
98
  aiModel: params?.aiModel,
99
+ apiKey: config.api_key,
94
100
  };
95
101
  }
96
102
 
@@ -101,22 +107,71 @@ export default function register(api: PluginApi): void {
101
107
  `Prisma AIRS plugin loaded (reminder_enabled=${config.reminder_enabled ?? true})`
102
108
  );
103
109
 
104
- // Register hooks from the hooks directory
105
- if (api.registerPluginHooksFromDir) {
106
- const __filename = fileURLToPath(import.meta.url);
107
- const __dirname = dirname(__filename);
108
- const hooksDir = join(__dirname, "hooks");
109
- api.registerPluginHooksFromDir(hooksDir);
110
- api.logger.info(`Registered hooks from ${hooksDir}`);
111
- }
110
+ // Register lifecycle hooks via api.on()
111
+ // Each adapter injects api.config as cfg for handler compatibility.
112
+
113
+ // Guard: inject security scanning reminder at agent bootstrap
114
+ api.on(
115
+ "before_agent_start",
116
+ async () => {
117
+ const files: { path: string; content: string; source?: string }[] = [];
118
+ await guardHandler({
119
+ type: "agent",
120
+ action: "bootstrap",
121
+ context: { bootstrapFiles: files, cfg: api.config },
122
+ });
123
+ if (files.length > 0) {
124
+ return { systemPrompt: files.map((f) => f.content).join("\n\n") };
125
+ }
126
+ return undefined;
127
+ },
128
+ { priority: 100 }
129
+ );
130
+
131
+ // Audit: fire-and-forget inbound message scan logging
132
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
133
+ api.on("message_received", async (event: any, ctx: any) => {
134
+ await auditHandler(event, { ...ctx, cfg: api.config });
135
+ });
136
+
137
+ // Context: inject security warnings before agent processes message
138
+ api.on(
139
+ "before_agent_start",
140
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
141
+ async (event: any, ctx: any) => {
142
+ return await contextHandler(
143
+ {
144
+ sessionKey: ctx.sessionKey,
145
+ message: { content: event.prompt },
146
+ messages: event.messages,
147
+ },
148
+ { ...ctx, cfg: api.config }
149
+ );
150
+ },
151
+ { priority: 50 }
152
+ );
153
+
154
+ // Outbound: scan and block/mask outgoing responses
155
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
156
+ api.on("message_sending", async (event: any, ctx: any) => {
157
+ return await outboundHandler(event, { ...ctx, cfg: api.config });
158
+ });
159
+
160
+ // Tools: block dangerous tool calls during active threats
161
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
162
+ api.on("before_tool_call", async (event: any, ctx: any) => {
163
+ return await toolsHandler(event, { ...ctx, cfg: api.config });
164
+ });
165
+
166
+ api.logger.info("Registered 5 lifecycle hooks");
112
167
 
113
168
  // Register RPC method for status check
114
169
  api.registerGatewayMethod("prisma-airs.status", ({ respond }) => {
115
170
  const cfg = getPluginConfig(api);
116
- const hasApiKey = isConfigured();
171
+ const hasApiKey = isConfigured(cfg.api_key);
117
172
  respond(true, {
118
173
  plugin: "prisma-airs",
119
- version: "0.2.0",
174
+ version: "0.2.4",
120
175
  config: {
121
176
  profile_name: cfg.profile_name ?? "default",
122
177
  app_name: cfg.app_name ?? "openclaw",
@@ -159,7 +214,8 @@ export default function register(api: PluginApi): void {
159
214
  name: "prisma_airs_scan",
160
215
  description:
161
216
  "Scan content for security threats via Prisma AIRS. " +
162
- "Detects prompt injection, data leakage, malicious URLs, and other threats. " +
217
+ "Detects prompt injection, DLP, malicious URLs, toxic content, malicious code, " +
218
+ "agent threats, topic violations, DB security, and ungrounded responses. " +
163
219
  "Returns action (allow/warn/block), severity, and detected categories.",
164
220
  parameters: {
165
221
  type: "object",
@@ -212,16 +268,16 @@ export default function register(api: PluginApi): void {
212
268
  .description("Show Prisma AIRS plugin status")
213
269
  .action(() => {
214
270
  const cfg = getPluginConfig(api);
215
- const hasKey = isConfigured();
271
+ const hasKey = isConfigured(cfg.api_key);
216
272
  console.log("Prisma AIRS Plugin Status");
217
273
  console.log("-------------------------");
218
- console.log(`Version: 0.2.0`);
274
+ console.log(`Version: 0.2.4`);
219
275
  console.log(`Profile: ${cfg.profile_name ?? "default"}`);
220
276
  console.log(`App Name: ${cfg.app_name ?? "openclaw"}`);
221
277
  console.log(`Reminder: ${cfg.reminder_enabled ?? true}`);
222
278
  console.log(`API Key: ${hasKey ? "configured" : "MISSING"}`);
223
279
  if (!hasKey) {
224
- console.log("\nSet PANW_AI_SEC_API_KEY environment variable");
280
+ console.log("\nSet API key in plugin config");
225
281
  }
226
282
  });
227
283
 
@@ -266,7 +322,7 @@ export default function register(api: PluginApi): void {
266
322
  // Export plugin metadata for discovery
267
323
  export const id = "prisma-airs";
268
324
  export const name = "Prisma AIRS Security";
269
- export const version = "0.2.0";
325
+ export const version = "0.2.4";
270
326
 
271
327
  // Re-export scanner types and functions
272
328
  export { scan, isConfigured } from "./src/scanner";
@@ -2,7 +2,7 @@
2
2
  "id": "prisma-airs",
3
3
  "name": "Prisma AIRS Security",
4
4
  "description": "AI Runtime Security - full AIRS detection suite with audit logging, context injection, outbound blocking, and tool gating",
5
- "version": "0.2.2",
5
+ "version": "0.2.4",
6
6
  "entrypoint": "index.ts",
7
7
  "hooks": [
8
8
  "hooks/prisma-airs-guard",
@@ -63,12 +63,32 @@
63
63
  "high_risk_tools": {
64
64
  "type": "array",
65
65
  "items": { "type": "string" },
66
- "default": ["exec", "Bash", "write", "Write", "edit", "Edit", "gateway", "message", "cron"],
66
+ "default": [
67
+ "exec",
68
+ "Bash",
69
+ "bash",
70
+ "write",
71
+ "Write",
72
+ "edit",
73
+ "Edit",
74
+ "gateway",
75
+ "message",
76
+ "cron"
77
+ ],
67
78
  "description": "Tools to block on any detected threat"
79
+ },
80
+ "api_key": {
81
+ "type": "string",
82
+ "description": "Prisma AIRS API key from Strata Cloud Manager"
68
83
  }
69
84
  }
70
85
  },
71
86
  "uiHints": {
87
+ "api_key": {
88
+ "label": "API Key",
89
+ "sensitive": true,
90
+ "placeholder": "Enter your PANW AI Security API key"
91
+ },
72
92
  "profile_name": {
73
93
  "label": "Profile Name",
74
94
  "placeholder": "default"
@@ -109,8 +129,5 @@
109
129
  "description": "Tools blocked on any threat detection"
110
130
  }
111
131
  },
112
- "requires": {
113
- "env": ["PANW_AI_SEC_API_KEY"],
114
- "envOptional": ["PANW_AI_SEC_PROFILE_NAME"]
115
- }
132
+ "requires": {}
116
133
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdot65/prisma-airs",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Prisma AIRS (AI Runtime Security) plugin for OpenClaw - Full security suite with audit logging, context injection, outbound blocking, and tool gating",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -13,6 +13,7 @@ import {
13
13
  stopCleanup,
14
14
  startCleanup,
15
15
  } from "./scan-cache";
16
+ import { defaultPromptDetected, defaultResponseDetected } from "./scanner";
16
17
  import type { ScanResult } from "./scanner";
17
18
 
18
19
  // Mock scan result
@@ -23,9 +24,12 @@ const mockScanResult: ScanResult = {
23
24
  scanId: "scan_123",
24
25
  reportId: "report_456",
25
26
  profileName: "default",
26
- promptDetected: { injection: true, dlp: false, urlCats: false },
27
- responseDetected: { dlp: false, urlCats: false },
27
+ promptDetected: { ...defaultPromptDetected(), injection: true },
28
+ responseDetected: defaultResponseDetected(),
28
29
  latencyMs: 100,
30
+ timeout: false,
31
+ hasError: false,
32
+ contentErrors: [],
29
33
  };
30
34
 
31
35
  describe("scan-cache", () => {