Trawl

Security

Trawl protects your credentials and integrations with layered controls — from the browser sandbox to your webhook receiver.

At-rest encryption

Credentials stored in the Account Namespace are encrypted at rest with AES-256-GCM. Saved authentication sessions (cookies, tokens, custom headers) use the same envelope encryption. No plaintext credential ever touches disk.

You do not need to manage keys — encryption is automatic and transparent.

API keys

API keys are stored as SHA-256 hashes — the plaintext key is shown once at creation and never persisted. Authentication uses a standard Authorization: Bearer <key> header:

Authorization: Bearer trawl_your_key_here

Every API key is created with:

  • Scoped access — keys are scoped per scrap or account-wide. A key scoped to specific scraps cannot read or trigger any other scrap in the organization.
  • Action scopes — optional scopes[] array narrows which actions the key can perform (trawl:scraps:read, trawl:scraps:run, trawl:history:read, …). A key with only trawl:scraps:read cannot trigger a run.
  • Configurable expiry — set any duration up to 2 years. Expired keys return 401 immediately.

Rotate keys at any time via the API. Keys can only be revoked, not updated — create a fresh key and revoke the old one to minimize the overlap window.

Webhook signatures

Outbound webhooks (scrap.success, scrap.failure) include an X-Webhook-Signature header containing an HMAC-SHA256 digest of the raw request body, keyed with your webhook secret. Your receiver should verify before processing:

Node
import crypto from 'crypto';

function verifySignature(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected),
  );
}

// Express example — use raw body middleware to preserve the buffer
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-webhook-signature'];
  if (!verifySignature(req.body, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  const payload = JSON.parse(req.body);
  // handle payload.scrapId / payload.status / payload.historyId …
  res.sendStatus(200);
});

Rotate your webhook secret at any time via the API. The old secret remains valid until the rotation completes.

Container isolation

Every scrap runs in a dedicated, ephemeral container with:

  • readOnlyRootFilesystem — the worker cannot modify its own image.
  • No host network access — the container reaches the internet through Trawl's proxy layer only.
  • Automatic teardown after each run — no data persists between executions.

Containers are single-tenant and start from a fresh image on every run.

TLS in transit

All API traffic, webhook deliveries, and dashboard interactions are served exclusively over HTTPS (TLS 1.3). Plain HTTP requests are redirected.

What you control

Control Where
Key creation / rotation API Keys endpoint
Key scope (per-scrap or account-wide) Set at key creation
Key action scopes Set at key creation
Key expiry Set at key creation (max 2 years)
Webhook secret rotation Webhooks endpoint
Credential encryption Automatic — no action needed

See also: API Keys · Webhooks · Account & Sessions

Next step → Scheduling