Skip to main content

Webhooks & Events 📡

The Sandforge Supervisor can dispatch HTTP POST requests (webhooks) to notify your agent control plane about microVM state transitions, resource exhaustions, and policy violation attempts.


⚙️ Configuring Webhook Subscriptions

To receive webhooks, register your endpoint in the supervisor configuration or pass a --webhook parameter to the supervisor command:

./sandforge supervisor --webhook-url="https://api.my-agent.com/webhooks" --webhook-secret="sf_wh_secret_xyz123"

🏷️ Webhook Event Types

Event NameDescription
sandbox.createdThe guest VM metadata has been created and resource allocation is verified.
sandbox.startedThe guest VM has successfully booted and the VSOCK connection is established.
task.timeoutA command inside the guest VM exceeded its timeout_seconds allotment and was terminated.
security.violationThe Policy Engine intercepted an unapproved filesystem write or network access.
sandbox.destroyedThe guest VM was fully stopped and its CPU/RAM allocations returned to the host.

📦 Webhook Payload Examples

Security Violation Alert (security.violation)

Dispatched when a command attempts to read or write a blocked host directory:

{
"event": "security.violation",
"id": "evt_9a8b7c6d",
"timestamp": "2026-05-22T00:25:11Z",
"data": {
"sandbox_id": "sb_7f8g9h0i",
"violation_type": "filesystem_escape",
"attempted_command": "rm -rf /host/var/log",
"blocked_path": "/host/var/log",
"action": "terminated_sandbox"
}
}

Task Timeout Alert (task.timeout)

Dispatched when an agent command runs longer than its allowed limit:

{
"event": "task.timeout",
"id": "evt_1a2b3c4d",
"timestamp": "2026-05-22T00:27:00Z",
"data": {
"sandbox_id": "sb_7f8g9h0i",
"command": "npm install heavy-dependency-package",
"limit_seconds": 60,
"cpu_consumed": 12.4
}
}

🔒 Cryptographic Verification

To ensure that incoming webhook payloads originate from your trusted Sandforge Supervisor daemon and were not tampered with during transit, verify the X-Sandforge-Signature header.

The signature is computed using HMAC-SHA256 with your registered webhook secret:

X-Sandforge-Signature: t=1779435911,v1=a5c8e3c6f8a4...

Verification Example (Node.js/Express)

import crypto from 'crypto';

function verifyWebhook(req, res, next) {
const signatureHeader = req.headers['x-sandforge-signature'];
const secret = process.env.SANDFORGE_WEBHOOK_SECRET;

const [tPart, v1Part] = signatureHeader.split(',');
const timestamp = tPart.split('=')[1];
const signature = v1Part.split('=')[1];

// Prevent replay attacks
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
return res.status(400).send('Replay attack suspected.');
}

const signedPayload = `${timestamp}.${JSON.stringify(req.body)}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');

if (crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))) {
next(); // Authenticated successfully
} else {
res.status(403).send('Invalid signature.');
}
}