Documentation Index
Fetch the complete documentation index at: https://docs.agentfront.dev/llms.txt
Use this file to discover all available pages before exploring further.
This guide covers security best practices for hardening Enclave deployments in production environments.
Security Checklist
Critical
Recommended
Security Levels
Always use the appropriate security level:
| Level | Use Case | Restrictions |
|---|
STRICT | Untrusted AI/user code | Maximum restrictions |
SECURE | Semi-trusted automation | High restrictions |
STANDARD | Internal tools | Moderate restrictions |
PERMISSIVE | Testing only | Minimal restrictions |
import { Enclave } from '@enclave-vm/core';
// For untrusted code - always use STRICT
const enclave = new Enclave({
securityLevel: 'STRICT',
});
Defense in Depth
Validate code before it reaches Enclave:
import { z } from 'zod';
const executeSchema = z.object({
code: z
.string()
.min(1)
.max(100000) // Limit code size
.refine(
(code) => !code.includes('__proto__'),
'Suspicious code pattern detected'
),
timeout: z.number().min(1000).max(300000).optional(),
});
app.post('/execute', async (req, res) => {
const result = executeSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ error: 'Invalid request' });
}
// Proceed with validated input
});
Layer 2: Pre-Scanner
Block obvious attacks early:
import { PreScanner, createPreScannerConfig } from '@enclave-vm/ast';
const scanner = new PreScanner(createPreScannerConfig('agentscript'));
function preScreen(code: string): boolean {
const result = scanner.scan(code);
if (!result.valid) {
logger.warn('Pre-scan blocked code', {
issues: result.issues,
});
return false;
}
return true;
}
Layer 3: AST Validation
Strict AST validation:
import { JSAstValidator, createAgentScriptPreset } from '@enclave-vm/ast';
const validator = new JSAstValidator(
createAgentScriptPreset({
// Only allow specific globals
allowedGlobals: ['callTool', 'Math', 'JSON', 'console'],
// Block additional identifiers
additionalDisallowedIdentifiers: [
'fetch',
'XMLHttpRequest',
'WebSocket',
],
// Strict loop configuration
allowedLoops: {
allowFor: true,
allowForOf: true,
allowWhile: false,
allowDoWhile: false,
allowForIn: false,
},
})
);
Layer 4: AI Scoring Gate
Detect suspicious semantic patterns:
const enclave = new Enclave({
scoringGate: {
scorer: 'rule-based',
blockThreshold: 70,
warnThreshold: 40,
onScore: (result) => {
if (result.score >= 40) {
logger.warn('Suspicious code pattern', {
score: result.score,
signals: result.signals,
});
}
},
},
});
Layer 5: Runtime Isolation
Maximum runtime isolation:
const enclave = new Enclave({
// Memory limit
memoryLimit: 64 * 1024 * 1024, // 64MB
// Execution timeout
timeout: 30000, // 30 seconds
// Tool call limit
maxToolCalls: 50,
// Iteration limit
maxIterations: 10000,
// Use worker pool for OS-level isolation
adapter: createWorkerPoolAdapter({
poolSize: 4,
maxWorkerMemory: 128 * 1024 * 1024,
}),
});
Layer 6: Output Sanitization
Sanitize all outputs:
function sanitizeOutput(output: unknown): unknown {
// Remove circular references
const seen = new WeakSet();
function sanitize(value: unknown): unknown {
if (value === null || typeof value !== 'object') {
// Truncate long strings
if (typeof value === 'string' && value.length > 10000) {
return value.slice(0, 10000) + '... [truncated]';
}
return value;
}
if (seen.has(value)) {
return '[Circular]';
}
seen.add(value);
if (Array.isArray(value)) {
// Limit array size
const limited = value.slice(0, 1000);
return limited.map(sanitize);
}
const sanitized: Record<string, unknown> = {};
for (const [key, val] of Object.entries(value)) {
// Skip sensitive keys
if (key.match(/password|secret|token|key/i)) {
sanitized[key] = '[REDACTED]';
} else {
sanitized[key] = sanitize(val);
}
}
return sanitized;
}
return sanitize(output);
}
Always validate tool inputs:
import { z } from 'zod';
const toolSchemas = {
'users:get': z.object({
id: z.string().uuid(),
}),
'users:list': z.object({
limit: z.number().int().min(1).max(100).default(10),
offset: z.number().int().min(0).default(0),
}),
'email:send': z.object({
to: z.string().email(),
subject: z.string().max(200),
body: z.string().max(10000),
}),
};
const enclave = new Enclave({
toolHandler: async (name, args) => {
const schema = toolSchemas[name];
if (!schema) {
throw new Error(`Unknown tool: ${name}`);
}
const result = schema.safeParse(args);
if (!result.success) {
throw new Error(`Invalid arguments: ${result.error.message}`);
}
return executeTool(name, result.data);
},
});
Permission Control
Implement tool permissions per user:
interface UserPermissions {
tools: string[];
limits: {
maxToolCalls: number;
maxDataSize: number;
};
}
const enclave = new Enclave({
toolHandler: async (name, args, context) => {
const permissions = await getUserPermissions(context.userId);
// Check tool access
if (!permissions.tools.includes(name)) {
throw new Error(`Tool ${name} not allowed for user`);
}
// Check limits
if (context.toolCallCount >= permissions.limits.maxToolCalls) {
throw new Error('Tool call limit exceeded');
}
return executeTool(name, args);
},
});
Data Filtering
Filter sensitive data from tool responses:
function filterSensitiveData(data: unknown): unknown {
if (data === null || typeof data !== 'object') {
return data;
}
if (Array.isArray(data)) {
return data.map(filterSensitiveData);
}
const filtered: Record<string, unknown> = {};
const sensitiveKeys = ['password', 'secret', 'token', 'ssn', 'creditCard'];
for (const [key, value] of Object.entries(data)) {
if (sensitiveKeys.some(s => key.toLowerCase().includes(s))) {
continue; // Omit sensitive fields
}
filtered[key] = filterSensitiveData(value);
}
return filtered;
}
Network Security
Isolation
Run Enclave in isolated network:
# docker-compose.yml
services:
enclave-runtime:
networks:
- enclave-internal
# No external network access
enclave-broker:
networks:
- enclave-internal
- external
networks:
enclave-internal:
internal: true
external:
TLS Configuration
import { createServer } from 'https';
import { readFileSync } from 'fs';
const server = createServer({
key: readFileSync('/certs/server.key'),
cert: readFileSync('/certs/server.crt'),
ca: readFileSync('/certs/ca.crt'),
// Modern TLS settings
minVersion: 'TLSv1.2',
ciphers: [
'ECDHE-ECDSA-AES128-GCM-SHA256',
'ECDHE-RSA-AES128-GCM-SHA256',
'ECDHE-ECDSA-AES256-GCM-SHA384',
'ECDHE-RSA-AES256-GCM-SHA384',
].join(':'),
});
End-to-End Encryption
Enable E2E encryption for sensitive data:
const client = new EnclaveClient({
serverUrl: 'https://broker.example.com',
encryption: {
enabled: true,
curve: 'P-256',
},
});
Rate Limiting
Per-User Limits
import { RateLimiterRedis } from 'rate-limiter-flexible';
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
const rateLimiter = new RateLimiterRedis({
storeClient: redis,
keyPrefix: 'enclave_rl',
points: 100, // 100 requests
duration: 60, // per minute
});
app.use('/execute', async (req, res, next) => {
try {
await rateLimiter.consume(req.user.id);
next();
} catch {
res.status(429).json({ error: 'Too many requests' });
}
});
const toolLimits = new Map([
['email:send', { points: 10, duration: 60 }], // 10 emails per minute
['db:query', { points: 100, duration: 60 }], // 100 queries per minute
]);
async function checkToolLimit(userId: string, tool: string) {
const limit = toolLimits.get(tool);
if (!limit) return true;
const limiter = new RateLimiterRedis({
storeClient: redis,
keyPrefix: `tool_${tool}`,
...limit,
});
try {
await limiter.consume(userId);
return true;
} catch {
return false;
}
}
Audit Logging
Comprehensive Logging
interface AuditLog {
timestamp: string;
userId: string;
sessionId: string;
action: string;
details: Record<string, unknown>;
result: 'success' | 'failure';
errorCode?: string;
}
function logAudit(log: AuditLog) {
// Send to secure logging system
auditLogger.info(log);
// Store for compliance
auditStore.insert(log);
}
const enclave = new Enclave({
toolHandler: async (name, args, context) => {
const start = Date.now();
let result: unknown;
let error: Error | undefined;
try {
result = await executeTool(name, args);
return result;
} catch (e) {
error = e as Error;
throw e;
} finally {
logAudit({
timestamp: new Date().toISOString(),
userId: context.userId,
sessionId: context.sessionId,
action: `tool:${name}`,
details: {
args: sanitizeForLog(args),
duration: Date.now() - start,
},
result: error ? 'failure' : 'success',
errorCode: error?.message,
});
}
},
});
Log Retention
// Configure log retention
const logConfig = {
// Keep detailed logs for 30 days
detailedRetention: 30,
// Keep summary logs for 1 year
summaryRetention: 365,
// Archive to cold storage after 90 days
archiveAfter: 90,
};
Container Security
Dockerfile Best Practices
# Use specific version
FROM node:20.10-slim
# Run as non-root
RUN useradd -m -u 1001 enclave
# Set secure permissions
WORKDIR /app
COPY --chown=enclave:enclave . .
# Remove unnecessary packages
RUN apt-get purge -y --auto-remove \
&& rm -rf /var/lib/apt/lists/*
# Drop all capabilities
USER enclave
# Read-only filesystem
VOLUME ["/tmp"]
# Health check
HEALTHCHECK --interval=30s CMD curl -f http://localhost:3000/health || exit 1
EXPOSE 3000
CMD ["node", "--no-warnings", "dist/server.js"]
Security Context
# k8s/deployment.yaml
spec:
containers:
- name: enclave
securityContext:
runAsNonRoot: true
runAsUser: 1001
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
Secrets Management
Environment Variables
Never hardcode secrets:
// Bad
const apiKey = 'sk-1234567890';
// Good
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('API_KEY not configured');
}
Kubernetes Secrets
apiVersion: v1
kind: Secret
metadata:
name: enclave-secrets
type: Opaque
data:
api-key: base64-encoded-value
redis-url: base64-encoded-value
# deployment.yaml
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: enclave-secrets
key: api-key
Incident Response
Detection
Monitor for anomalies:
// Alert on unusual patterns
const alerts = {
highErrorRate: (rate: number) => rate > 0.1, // >10% error rate
unusualToolUsage: (count: number) => count > 1000, // >1000 calls/min
memorySpike: (mb: number) => mb > 500, // >500MB
longExecution: (ms: number) => ms > 60000, // >60s
};
Response Plan
- Detect - Automated monitoring alerts
- Contain - Isolate affected components
- Investigate - Review audit logs
- Remediate - Fix vulnerability
- Recover - Restore normal operation
- Learn - Post-incident review