@mondaydotcomorg/atp-provenance
v0.19.8
Published
CAMEL-inspired provenance security for LLM applications - track data origin and enforce security policies
Maintainers
Readme
@mondaydotcomorg/atp-provenance
CAMEL-inspired provenance security for LLM applications - track data origin and enforce security policies to defend against prompt injection attacks.
Overview
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.
Installation
npm install @mondaydotcomorg/atp-provenanceArchitecture
graph TB
ProvenanceSystem[Provenance System] --> Modes[Three Modes]
Modes --> None[None Mode<br/>Zero overhead]
Modes --> Proxy[Proxy Mode<br/>Runtime tracking]
Modes --> AST[AST Mode<br/>Compile-time]
ProvenanceSystem --> Policy[Policy Engine]
Policy --> BuiltIn[Built-in Policies]
Policy --> Custom[Custom Policies]
Policy --> Declarative[Declarative Policies]
Proxy --> ProxyAPI[createProvenanceProxy]
AST --> Compiler[instrumentCode]
Policy --> Actions[Policy Actions]
Actions --> Log[Log]
Actions --> Approve[Approve]
Actions --> Block[Block]Three Modes
None Mode (Default)
No provenance tracking, zero overhead.
// Default mode - no tracking
const user = { name: 'Alice', ssn: '123-45-6789' };
// Works normally with no overheadProxy Mode
Runtime tracking with 5-10% overhead using JavaScript Proxies.
import { createProvenanceProxy, ProvenanceSource } from '@mondaydotcomorg/atp-provenance';
const user = createProvenanceProxy(
{ name: 'Alice', ssn: '123-45-6789' },
{
type: ProvenanceSource.TOOL,
toolName: 'getUser',
apiGroup: 'users',
timestamp: Date.now(),
},
{
type: 'restricted',
readers: ['[email protected]'],
}
);
// Provenance tracked automatically
console.log(user.name); // Proxy tracks accessAST Mode
Compile-time instrumentation with 20-30% overhead, tracks primitive tainting.
import { instrumentCode, createTrackingRuntime } from '@mondaydotcomorg/atp-provenance';
const { code } = instrumentCode(`
const user = await api.users.getUser({ id: '123' });
const email = user.email; // Taint propagates to email
await api.email.send({ to: '[email protected]', body: email });
`);
const runtime = createTrackingRuntime();
// Execute instrumented code with runtimeSecurity Policy Engine
Quick Start
import {
SecurityPolicyEngine,
preventDataExfiltration,
requireUserOrigin,
} from '@mondaydotcomorg/atp-provenance';
const policyEngine = new SecurityPolicyEngine(
[preventDataExfiltration, requireUserOrigin],
console // Logger (pino, winston, or console)
);
// Check before sensitive operations
try {
await policyEngine.checkTool('send', 'email', {
to: '[email protected]',
body: user, // Contains provenance metadata
});
} catch (error) {
console.error('Security policy blocked:', error.message);
}Built-in Policies
import {
preventDataExfiltration, // Block data exfiltration
preventDataExfiltrationWithApproval, // Require approval for exfiltration
requireUserOrigin, // Require user-originated data
requireUserOriginWithApproval, // Require approval for non-user data
blockLLMRecipients, // Block LLM-extracted recipients
blockLLMRecipientsWithApproval, // Require approval for LLM recipients
auditSensitiveAccess, // Log all sensitive access
getBuiltInPolicies, // All block policies
getBuiltInPoliciesWithApproval, // All approval policies
} from '@mondaydotcomorg/atp-provenance';Declarative Policies (JSON Configuration)
Designed for security teams to define policies without writing code. Supports AWS IAM-style JSON configuration.
import { createDeclarativePolicy, SecurityPolicyEngine } from '@mondaydotcomorg/atp-provenance';
const config = {
id: 'block-external-emails',
scope: { toolName: 'send' },
rules: [
{
action: 'block',
conditions: [
// Check argument value
{ field: 'args.to', operator: 'notEndsWith', value: '@company.com' },
// Check provenance of argument
{ field: 'provenance.args.body.source.type', operator: 'equals', value: 'user' },
],
reason: 'Cannot send internal user data to external email addresses',
},
],
};
const policy = createDeclarativePolicy(config);
const engine = new SecurityPolicyEngine([policy], console);JSON Schema Structure:
{
"policies": [
{
"id": "policy-id",
"scope": { "toolName": "^send.*" },
"rules": [
{
"action": "block", // or "approve", "log"
"conditions": [
{
"field": "args.param",
"operator": "equals", // equals, contains, startsWith, matches...
"value": "expected-value"
}
]
}
]
}
]
}Custom Policies (Code)
import { createCustomPolicy, type SecurityPolicy } from '@mondaydotcomorg/atp-provenance';
const blockExternalAPIs: SecurityPolicy = createCustomPolicy({
name: 'blockExternalAPIs',
description: 'Block calls to external APIs',
check: async (toolName, apiGroup, args, metadata) => {
const externalAPIs = ['external-api', 'third-party'];
if (externalAPIs.includes(apiGroup)) {
return {
action: 'block',
reason: 'External API calls are not allowed',
};
}
return { action: 'approve' };
},
});
const engine = new SecurityPolicyEngine([blockExternalAPIs], console);Policy Actions
Policies can return three actions:
type PolicyAction = 'log' | 'approve' | 'block';
interface PolicyResult {
action: PolicyAction;
reason?: string;
metadata?: Record<string, unknown>;
}- log: Log the operation but allow it
- approve: Explicitly approve the operation
- block: Block the operation and throw error
Provenance Metadata
Track Data Sources
import { ProvenanceSource } from '@mondaydotcomorg/atp-provenance';
enum ProvenanceSource {
USER = 0, // User-provided data
LLM = 1, // LLM-generated data
TOOL = 2, // Tool/API response
SYSTEM = 3, // System-generated data
}
interface ProvenanceMetadata {
source: SourceMetadata;
readers?: ReaderPermissions;
timestamp: number;
}Get Provenance
import { getProvenance, hasProvenance } from '@mondaydotcomorg/atp-provenance';
const user = createProvenanceProxy(userData, source, readers);
// Check if object has provenance
if (hasProvenance(user)) {
const metadata = getProvenance(user);
console.log('Source:', metadata.source);
console.log('Readers:', metadata.readers);
}Pause/Resume Support
Provenance integrates with ATP's pause/resume mechanism:
import {
captureProvenanceState,
restoreProvenanceState,
setProvenanceExecutionId,
cleanupProvenanceForExecution,
} from '@mondaydotcomorg/atp-provenance';
// Before execution
setProvenanceExecutionId('exec-123');
// Capture state before pause
const state = captureProvenanceState();
// Later, restore state on resume
restoreProvenanceState(state);
// Cleanup after execution
cleanupProvenanceForExecution('exec-123');Integration with ATP Server
import { createServer, ProvenanceMode } from '@mondaydotcomorg/atp-server';
import { preventDataExfiltration, requireUserOrigin } from '@mondaydotcomorg/atp-server';
const server = createServer({
execution: {
provenanceMode: ProvenanceMode.PROXY, // or ProvenanceMode.AST
securityPolicies: [preventDataExfiltration, requireUserOrigin],
},
});
// All tool calls now enforce provenance policiesReal-World Examples
Prevent Data Exfiltration
// User's sensitive data
const user = createProvenanceProxy(
{ name: 'Alice', ssn: '123-45-6789' },
{ type: ProvenanceSource.TOOL, toolName: 'getUser' },
{ type: 'restricted', readers: ['[email protected]'] }
);
const engine = new SecurityPolicyEngine([preventDataExfiltration], console);
// This will throw - external email with restricted data
await engine.checkTool('send', 'email', {
to: '[email protected]',
body: user,
});
// ❌ Throws: ProvenanceSecurityError
// This will succeed - internal email
await engine.checkTool('send', 'email', {
to: '[email protected]',
body: user,
});
// ✅ AllowedRequire User Origin
// LLM-generated email address (untrusted)
const recipient = createProvenanceProxy(
'[email protected]',
{ type: ProvenanceSource.LLM },
null
);
const engine = new SecurityPolicyEngine([requireUserOrigin], console);
// This will throw - LLM-generated recipient
await engine.checkTool('send', 'email', {
to: recipient,
subject: 'Hello',
});
// ❌ Throws: Non-user-originated data in sensitive field
// User-provided recipient (trusted)
const userRecipient = createProvenanceProxy(
'[email protected]',
{ type: ProvenanceSource.USER },
null
);
await engine.checkTool('send', 'email', {
to: userRecipient,
subject: 'Hello',
});
// ✅ AllowedApproval Workflows
import { preventDataExfiltrationWithApproval } from '@mondaydotcomorg/atp-provenance';
const engine = new SecurityPolicyEngine([preventDataExfiltrationWithApproval], console);
// Set approval callback
engine.setApprovalCallback(async (request) => {
console.log(`Approval needed: ${request.reason}`);
// In production: show UI, send to Slack, etc.
const approved = await getUserApproval(request);
return { approved };
});
// This will request approval instead of blocking
await engine.checkTool('send', 'email', {
to: '[email protected]',
body: sensitiveData,
});
// → Calls approval callback
// → Proceeds if approved, blocks if deniedPerformance
| Mode | Overhead | Use Case | | ----- | -------- | ----------------------------------- | | None | 0% | No security requirements | | Proxy | 5-10% | Production with moderate security | | AST | 20-30% | Maximum security, tracks primitives |
Primitive Taint Tracking (AST Mode)
import {
markPrimitiveTainted,
isPrimitiveTainted,
getProvenanceForPrimitive,
} from '@mondaydotcomorg/atp-provenance';
// Mark primitive as tainted
markPrimitiveTainted('sensitive-string', metadata);
// Check if primitive is tainted
if (isPrimitiveTainted('sensitive-string')) {
const provenance = getProvenanceForPrimitive('sensitive-string');
console.log('String is tainted:', provenance);
}API Reference
Core Functions
createProvenanceProxy<T>(value: T, source: SourceMetadata, readers: ReaderPermissions): Proxied<T>
getProvenance(value: unknown): ProvenanceMetadata | null
hasProvenance(value: unknown): boolean
getAllProvenance(value: unknown): ProvenanceMetadata[]
canRead(metadata: ProvenanceMetadata, reader: string): booleanAST Mode
instrumentCode(code: string): { code: string; metadata: unknown }
createTrackingRuntime(): RuntimePolicy Engine
new SecurityPolicyEngine(policies: SecurityPolicy[], logger: Logger)
engine.checkTool(toolName: string, apiGroup: string, args: unknown): Promise<void>
engine.setApprovalCallback(callback: ApprovalCallback): voidDeclarative Policies
createDeclarativePolicy(config: DeclarativePolicyConfig): SecurityPolicy
loadDeclarativePolicies(config: PolicyConfiguration): SecurityPolicy[]State Management
setProvenanceExecutionId(executionId: string): void
clearProvenanceExecutionId(): void
captureProvenanceState(): ProvenanceState
restoreProvenanceState(state: ProvenanceState): void
cleanupProvenanceForExecution(executionId: string): voidTypeScript Support
Full TypeScript definitions with strict typing.
Credits
Inspired by Google Research's CAMEL paper:
- Paper: CAMEL: Capability-Aware Machine Execution Language
- GitHub: https://github.com/google-research/camel-prompt-injection
License
MIT
