Security

Security

Cronable runs entirely on your machine. There’s no telemetry, and your data, secrets and job history never leave your infrastructure. The one optional cloud touchpoint is the webhook relay (below), used only if you choose inbound webhook triggers — and even then it carries the inbound event on its way in, never your data on its way out.

Highlights

  • Local-first. The engine binds to 127.0.0.1 and runs as a dedicated low-privilege user. Your code, prompts and outputs stay on your box.
  • Encrypted secrets. Secret values and typed credentials are AES-256-GCM encrypted at rest with a key derived from your own encryption key — never written to git, masked from logs.
  • Authenticated dashboard. Per-user logins (or your identity provider via OIDC SSO), brute-force lockout, and an append-only audit trail of logins, secret changes and settings edits.
  • Your own AI accounts. Bring your own AI accounts and MCP connections — however you authenticate. Nothing is routed through us.
  • Signed updates. Only vendor-signed builds are ever applied (verify → atomic swap → rollback).

Back up your encryption key

Your CRONABLE_ENCRYPTION_KEY protects all stored secrets. Back it up separately from the database — lose it and secrets are unrecoverable by design.

How the dashboard is reached

The daemon (the engine) binds to 127.0.0.1 and is not meant to be exposed to the network. The browser never talks to it directly: the Next.js app forwards same-origin requests through its /engine proxy, attaching your login session cookie. To reach the dashboard from another machine, put it behind an authenticated reverse proxy or an SSH tunnel — never publish the daemon’s port. See Deployment for the reverse-proxy and TLS notes (CRONABLE_SESSION_COOKIE_SECURE, the __Host- cookie prefix).

The webhook relay

Inbound webhook triggers reach your daemon through Cronable’s hosted relay at hooks.cronable.ai — the daemon holds an outbound connection and the event is pushed down it, so you never open an inbound port. What this means for your data boundary:

  • Only the inbound event transits the relay, in flight, to reach your daemon. It is not stored.
  • Nothing else leaves. Your jobs, secrets, credentials, AI accounts, logs and job output all stay on your machine.
  • It’s opt-in. No webhook triggers, no relay connection. The polling triggers (inbox, calendar-watch, folder-watch, telegram-watch, sheet-watch, hostaway-watch) reach out from your server and never touch the relay.
  • Only your licensed daemon can receive your events. The connection is gated on your license, and every hook is bound to it: a hook is claimed by exactly one license and delivery is scoped to that verified license, in both directions. Even another licensed customer who learned your hookId could neither take it over nor receive its events.
  • Two secrets guard every call, with no oracle. The public URL needs an unguessable hookId (≥ 32 random characters) and a per-hook token that the relay checks (constant-time) before routing. Unknown hook, wrong token, disabled, or malformed all return the same generic 401, and repeated failures from an IP earn a temporary ban — so a hook can’t be found or brute-forced.

See Webhook relay for the full model — how to turn it on, the security layers, and exactly what data crosses.

HTTP security headers

The dashboard sends a baseline set of HTTP security headers on every response:

HeaderValueWhy
X-Frame-OptionsDENYThe dashboard can trigger job runs — it must never be framed (clickjacking).
X-Content-Type-OptionsnosniffNo MIME-type sniffing of responses.
Referrer-Policystrict-origin-when-cross-originDon’t leak full dashboard URLs to other origins.
Permissions-Policycamera=(), microphone=(), geolocation=()Deny device APIs the dashboard never uses.

A full Content-Security-Policy is on the roadmap; until it ships you can add one at your reverse proxy if your threat model calls for it. The marketing site (cronable.ai) already sends a strict CSP.