@mondaydotcomorg/atp-provenance 0.17.14

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/README.md ADDED
@@ -0,0 +1,417 @@
1
+ # @mondaydotcomorg/atp-provenance
2
+
3
+ CAMEL-inspired provenance security for LLM applications - track data origin and enforce security policies to defend against prompt injection attacks.
4
+
5
+ ## Overview
6
+
7
+ This package implements provenance tracking and security policy enforcement inspired by Google Research's CAMEL paper. It provides three modes with different security/performance trade-offs to protect against prompt injection, data exfiltration, and other LLM security threats.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @mondaydotcomorg/atp-provenance
13
+ ```
14
+
15
+ ## Architecture
16
+
17
+ ```mermaid
18
+ graph TB
19
+ ProvenanceSystem[Provenance System] --> Modes[Three Modes]
20
+ Modes --> None[None Mode<br/>Zero overhead]
21
+ Modes --> Proxy[Proxy Mode<br/>Runtime tracking]
22
+ Modes --> AST[AST Mode<br/>Compile-time]
23
+
24
+ ProvenanceSystem --> Policy[Policy Engine]
25
+ Policy --> BuiltIn[Built-in Policies]
26
+ Policy --> Custom[Custom Policies]
27
+
28
+ Proxy --> ProxyAPI[createProvenanceProxy]
29
+ AST --> Compiler[instrumentCode]
30
+
31
+ Policy --> Actions[Policy Actions]
32
+ Actions --> Log[Log]
33
+ Actions --> Approve[Approve]
34
+ Actions --> Block[Block]
35
+ ```
36
+
37
+ ## Three Modes
38
+
39
+ ### None Mode (Default)
40
+
41
+ No provenance tracking, zero overhead.
42
+
43
+ ```typescript
44
+ // Default mode - no tracking
45
+ const user = { name: 'Alice', ssn: '123-45-6789' };
46
+ // Works normally with no overhead
47
+ ```
48
+
49
+ ### Proxy Mode
50
+
51
+ Runtime tracking with 5-10% overhead using JavaScript Proxies.
52
+
53
+ ```typescript
54
+ import { createProvenanceProxy, ProvenanceSource } from '@mondaydotcomorg/atp-provenance';
55
+
56
+ const user = createProvenanceProxy(
57
+ { name: 'Alice', ssn: '123-45-6789' },
58
+ {
59
+ type: ProvenanceSource.TOOL,
60
+ toolName: 'getUser',
61
+ apiGroup: 'users',
62
+ timestamp: Date.now(),
63
+ },
64
+ {
65
+ type: 'restricted',
66
+ readers: ['alice@company.com'],
67
+ }
68
+ );
69
+
70
+ // Provenance tracked automatically
71
+ console.log(user.name); // Proxy tracks access
72
+ ```
73
+
74
+ ### AST Mode
75
+
76
+ Compile-time instrumentation with 20-30% overhead, tracks primitive tainting.
77
+
78
+ ```typescript
79
+ import { instrumentCode, createTrackingRuntime } from '@mondaydotcomorg/atp-provenance';
80
+
81
+ const { code } = instrumentCode(`
82
+ const user = await api.users.getUser({ id: '123' });
83
+ const email = user.email; // Taint propagates to email
84
+ await api.email.send({ to: 'external@company.com', body: email });
85
+ `);
86
+
87
+ const runtime = createTrackingRuntime();
88
+ // Execute instrumented code with runtime
89
+ ```
90
+
91
+ ## Security Policy Engine
92
+
93
+ ### Quick Start
94
+
95
+ ```typescript
96
+ import {
97
+ SecurityPolicyEngine,
98
+ preventDataExfiltration,
99
+ requireUserOrigin,
100
+ } from '@mondaydotcomorg/atp-provenance';
101
+
102
+ const policyEngine = new SecurityPolicyEngine(
103
+ [preventDataExfiltration, requireUserOrigin],
104
+ console // Logger (pino, winston, or console)
105
+ );
106
+
107
+ // Check before sensitive operations
108
+ try {
109
+ await policyEngine.checkTool('send', 'email', {
110
+ to: 'attacker@evil.com',
111
+ body: user, // Contains provenance metadata
112
+ });
113
+ } catch (error) {
114
+ console.error('Security policy blocked:', error.message);
115
+ }
116
+ ```
117
+
118
+ ### Built-in Policies
119
+
120
+ ```typescript
121
+ import {
122
+ preventDataExfiltration, // Block data exfiltration
123
+ preventDataExfiltrationWithApproval, // Require approval for exfiltration
124
+ requireUserOrigin, // Require user-originated data
125
+ requireUserOriginWithApproval, // Require approval for non-user data
126
+ blockLLMRecipients, // Block LLM-extracted recipients
127
+ blockLLMRecipientsWithApproval, // Require approval for LLM recipients
128
+ auditSensitiveAccess, // Log all sensitive access
129
+ getBuiltInPolicies, // All block policies
130
+ getBuiltInPoliciesWithApproval, // All approval policies
131
+ } from '@mondaydotcomorg/atp-provenance';
132
+ ```
133
+
134
+ ### Custom Policies
135
+
136
+ ```typescript
137
+ import { createCustomPolicy, type SecurityPolicy } from '@mondaydotcomorg/atp-provenance';
138
+
139
+ const blockExternalAPIs: SecurityPolicy = createCustomPolicy({
140
+ name: 'blockExternalAPIs',
141
+ description: 'Block calls to external APIs',
142
+ check: async (toolName, apiGroup, args, metadata) => {
143
+ const externalAPIs = ['external-api', 'third-party'];
144
+
145
+ if (externalAPIs.includes(apiGroup)) {
146
+ return {
147
+ action: 'block',
148
+ reason: 'External API calls are not allowed',
149
+ };
150
+ }
151
+
152
+ return { action: 'approve' };
153
+ },
154
+ });
155
+
156
+ const engine = new SecurityPolicyEngine([blockExternalAPIs], console);
157
+ ```
158
+
159
+ ## Policy Actions
160
+
161
+ Policies can return three actions:
162
+
163
+ ```typescript
164
+ type PolicyAction = 'log' | 'approve' | 'block';
165
+
166
+ interface PolicyResult {
167
+ action: PolicyAction;
168
+ reason?: string;
169
+ metadata?: Record<string, unknown>;
170
+ }
171
+ ```
172
+
173
+ - **log**: Log the operation but allow it
174
+ - **approve**: Explicitly approve the operation
175
+ - **block**: Block the operation and throw error
176
+
177
+ ## Provenance Metadata
178
+
179
+ ### Track Data Sources
180
+
181
+ ```typescript
182
+ import { ProvenanceSource } from '@mondaydotcomorg/atp-provenance';
183
+
184
+ enum ProvenanceSource {
185
+ USER = 0, // User-provided data
186
+ LLM = 1, // LLM-generated data
187
+ TOOL = 2, // Tool/API response
188
+ SYSTEM = 3, // System-generated data
189
+ }
190
+
191
+ interface ProvenanceMetadata {
192
+ source: SourceMetadata;
193
+ readers?: ReaderPermissions;
194
+ timestamp: number;
195
+ }
196
+ ```
197
+
198
+ ### Get Provenance
199
+
200
+ ```typescript
201
+ import { getProvenance, hasProvenance } from '@mondaydotcomorg/atp-provenance';
202
+
203
+ const user = createProvenanceProxy(userData, source, readers);
204
+
205
+ // Check if object has provenance
206
+ if (hasProvenance(user)) {
207
+ const metadata = getProvenance(user);
208
+ console.log('Source:', metadata.source);
209
+ console.log('Readers:', metadata.readers);
210
+ }
211
+ ```
212
+
213
+ ## Pause/Resume Support
214
+
215
+ Provenance integrates with ATP's pause/resume mechanism:
216
+
217
+ ```typescript
218
+ import {
219
+ captureProvenanceState,
220
+ restoreProvenanceState,
221
+ setProvenanceExecutionId,
222
+ cleanupProvenanceForExecution,
223
+ } from '@mondaydotcomorg/atp-provenance';
224
+
225
+ // Before execution
226
+ setProvenanceExecutionId('exec-123');
227
+
228
+ // Capture state before pause
229
+ const state = captureProvenanceState();
230
+
231
+ // Later, restore state on resume
232
+ restoreProvenanceState(state);
233
+
234
+ // Cleanup after execution
235
+ cleanupProvenanceForExecution('exec-123');
236
+ ```
237
+
238
+ ## Integration with ATP Server
239
+
240
+ ```typescript
241
+ import { createServer, ProvenanceMode } from '@mondaydotcomorg/atp-server';
242
+ import { preventDataExfiltration, requireUserOrigin } from '@mondaydotcomorg/atp-server';
243
+
244
+ const server = createServer({
245
+ execution: {
246
+ provenanceMode: ProvenanceMode.PROXY, // or ProvenanceMode.AST
247
+ securityPolicies: [preventDataExfiltration, requireUserOrigin],
248
+ },
249
+ });
250
+
251
+ // All tool calls now enforce provenance policies
252
+ ```
253
+
254
+ ## Real-World Examples
255
+
256
+ ### Prevent Data Exfiltration
257
+
258
+ ```typescript
259
+ // User's sensitive data
260
+ const user = createProvenanceProxy(
261
+ { name: 'Alice', ssn: '123-45-6789' },
262
+ { type: ProvenanceSource.TOOL, toolName: 'getUser' },
263
+ { type: 'restricted', readers: ['alice@company.com'] }
264
+ );
265
+
266
+ const engine = new SecurityPolicyEngine([preventDataExfiltration], console);
267
+
268
+ // This will throw - external email with restricted data
269
+ await engine.checkTool('send', 'email', {
270
+ to: 'attacker@evil.com',
271
+ body: user,
272
+ });
273
+ // ❌ Throws: ProvenanceSecurityError
274
+
275
+ // This will succeed - internal email
276
+ await engine.checkTool('send', 'email', {
277
+ to: 'alice@company.com',
278
+ body: user,
279
+ });
280
+ // ✅ Allowed
281
+ ```
282
+
283
+ ### Require User Origin
284
+
285
+ ```typescript
286
+ // LLM-generated email address (untrusted)
287
+ const recipient = createProvenanceProxy(
288
+ 'external@untrusted.com',
289
+ { type: ProvenanceSource.LLM },
290
+ null
291
+ );
292
+
293
+ const engine = new SecurityPolicyEngine([requireUserOrigin], console);
294
+
295
+ // This will throw - LLM-generated recipient
296
+ await engine.checkTool('send', 'email', {
297
+ to: recipient,
298
+ subject: 'Hello',
299
+ });
300
+ // ❌ Throws: Non-user-originated data in sensitive field
301
+
302
+ // User-provided recipient (trusted)
303
+ const userRecipient = createProvenanceProxy(
304
+ 'verified@company.com',
305
+ { type: ProvenanceSource.USER },
306
+ null
307
+ );
308
+
309
+ await engine.checkTool('send', 'email', {
310
+ to: userRecipient,
311
+ subject: 'Hello',
312
+ });
313
+ // ✅ Allowed
314
+ ```
315
+
316
+ ### Approval Workflows
317
+
318
+ ```typescript
319
+ import { preventDataExfiltrationWithApproval } from '@mondaydotcomorg/atp-provenance';
320
+
321
+ const engine = new SecurityPolicyEngine([preventDataExfiltrationWithApproval], console);
322
+
323
+ // Set approval callback
324
+ engine.setApprovalCallback(async (request) => {
325
+ console.log(`Approval needed: ${request.reason}`);
326
+ // In production: show UI, send to Slack, etc.
327
+ const approved = await getUserApproval(request);
328
+ return { approved };
329
+ });
330
+
331
+ // This will request approval instead of blocking
332
+ await engine.checkTool('send', 'email', {
333
+ to: 'external@company.com',
334
+ body: sensitiveData,
335
+ });
336
+ // → Calls approval callback
337
+ // → Proceeds if approved, blocks if denied
338
+ ```
339
+
340
+ ## Performance
341
+
342
+ | Mode | Overhead | Use Case |
343
+ | ----- | -------- | ----------------------------------- |
344
+ | None | 0% | No security requirements |
345
+ | Proxy | 5-10% | Production with moderate security |
346
+ | AST | 20-30% | Maximum security, tracks primitives |
347
+
348
+ ## Primitive Taint Tracking (AST Mode)
349
+
350
+ ```typescript
351
+ import {
352
+ markPrimitiveTainted,
353
+ isPrimitiveTainted,
354
+ getProvenanceForPrimitive,
355
+ } from '@mondaydotcomorg/atp-provenance';
356
+
357
+ // Mark primitive as tainted
358
+ markPrimitiveTainted('sensitive-string', metadata);
359
+
360
+ // Check if primitive is tainted
361
+ if (isPrimitiveTainted('sensitive-string')) {
362
+ const provenance = getProvenanceForPrimitive('sensitive-string');
363
+ console.log('String is tainted:', provenance);
364
+ }
365
+ ```
366
+
367
+ ## API Reference
368
+
369
+ ### Core Functions
370
+
371
+ ```typescript
372
+ createProvenanceProxy<T>(value: T, source: SourceMetadata, readers: ReaderPermissions): Proxied<T>
373
+ getProvenance(value: unknown): ProvenanceMetadata | null
374
+ hasProvenance(value: unknown): boolean
375
+ getAllProvenance(value: unknown): ProvenanceMetadata[]
376
+ canRead(metadata: ProvenanceMetadata, reader: string): boolean
377
+ ```
378
+
379
+ ### AST Mode
380
+
381
+ ```typescript
382
+ instrumentCode(code: string): { code: string; metadata: unknown }
383
+ createTrackingRuntime(): Runtime
384
+ ```
385
+
386
+ ### Policy Engine
387
+
388
+ ```typescript
389
+ new SecurityPolicyEngine(policies: SecurityPolicy[], logger: Logger)
390
+ engine.checkTool(toolName: string, apiGroup: string, args: unknown): Promise<void>
391
+ engine.setApprovalCallback(callback: ApprovalCallback): void
392
+ ```
393
+
394
+ ### State Management
395
+
396
+ ```typescript
397
+ setProvenanceExecutionId(executionId: string): void
398
+ clearProvenanceExecutionId(): void
399
+ captureProvenanceState(): ProvenanceState
400
+ restoreProvenanceState(state: ProvenanceState): void
401
+ cleanupProvenanceForExecution(executionId: string): void
402
+ ```
403
+
404
+ ## TypeScript Support
405
+
406
+ Full TypeScript definitions with strict typing.
407
+
408
+ ## Credits
409
+
410
+ Inspired by Google Research's CAMEL paper:
411
+
412
+ - Paper: [CAMEL: Capability-Aware Machine Execution Language](https://arxiv.org/abs/2410.02904)
413
+ - GitHub: https://github.com/google-research/camel-prompt-injection
414
+
415
+ ## License
416
+
417
+ MIT
@@ -0,0 +1,37 @@
1
+ import type { ProvenanceMetadata, SourceMetadata } from '../types.js';
2
+ import { getProvenance, getProvenanceForPrimitive } from '../registry.js';
3
+ export { getProvenance, getProvenanceForPrimitive };
4
+ /**
5
+ * Instrument code to track provenance at AST level
6
+ */
7
+ export declare function instrumentCode(code: string): {
8
+ code: string;
9
+ metadata: {
10
+ trackingCalls: number;
11
+ };
12
+ };
13
+ /**
14
+ * Runtime tracking functions injected into sandbox
15
+ */
16
+ export declare class ASTProvenanceTracker {
17
+ private metadata;
18
+ private valueToId;
19
+ private nextId;
20
+ private getId;
21
+ track(value: unknown, source: SourceMetadata, dependencies?: string[]): unknown;
22
+ trackBinary(left: unknown, right: unknown, operator: string): unknown;
23
+ trackAssign(name: string, value: unknown): unknown;
24
+ trackMethod(object: unknown, method: string, args: unknown[]): unknown;
25
+ trackTemplate(expressions: unknown[], quasis: string[]): string;
26
+ getMetadata(value: unknown): ProvenanceMetadata | null;
27
+ getAllMetadata(): Map<string, ProvenanceMetadata>;
28
+ restoreMetadata(metadata: Map<string, ProvenanceMetadata>): void;
29
+ }
30
+ /**
31
+ * Create tracking runtime for sandbox injection
32
+ */
33
+ export declare function createTrackingRuntime(): {
34
+ tracker: ASTProvenanceTracker;
35
+ runtime: Record<string, Function>;
36
+ };
37
+ //# sourceMappingURL=instrumentor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumentor.d.ts","sourceRoot":"","sources":["../../src/ast/instrumentor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEtE,OAAO,EAEN,aAAa,EACb,yBAAyB,EAEzB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,yBAAyB,EAAE,CAAC;AAOpD;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC,CA6CA;AA8GD;;GAEG;AACH,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAA8C;IAC9D,OAAO,CAAC,SAAS,CAA0C;IAC3D,OAAO,CAAC,MAAM,CAAK;IAEnB,OAAO,CAAC,KAAK;IAYb,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,YAAY,GAAE,MAAM,EAAO,GAAG,OAAO;IAmBnF,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAsErE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO;IAQlD,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO;IActE,aAAa,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM;IAwB/D,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,GAAG,IAAI;IAUtD,cAAc,IAAI,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC;IAIjD,eAAe,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,IAAI;CAGhE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI;IACxC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CAClC,CAkBA"}