Skip to content
cronpad
Platform / Security

Security

cronpad isolates workspaces from each other, encrypts stored secrets, signs every outgoing webhook, and refuses to send requests to internal networks on the hosted service. Self-hosted servers trust their operators and enable powerful features (shell commands, private-network webhooks) by default; setting mode = "hosted" switches every one of them to the safe default for a public, multi-tenant server.

Accounts and access

  • Sign-in only through Google or GitHub (verified email required); no passwords are stored.
  • API keys are random, shown once and stored as SHA-256 hashes. Each belongs to one workspace and can be scoped read-only.
  • Session cookies are HttpOnly, SameSite=Lax and Secure over HTTPS; requests that change data with a cookie also need a CSRF token.
  • Every database query is scoped to the caller’s workspace. Requests for another workspace’s objects return 404, so IDs can’t be probed.
  • Every change (create, update, pause, delete, key creation, secret change, auto-disable) is written to the audit log with the actor.

Development authentication is opt-in with auth.dev_login = true. It trusts X-Dev-User (default developer) and creates a personal workspace for that identity; use it only on a trusted development server, never on a public deployment.

Secrets

Stored secrets are encrypted with AES-256-GCM, are write-only through the API, and are redacted from run history, logs and traces. Webhook signing secrets and cached idempotency responses are also encrypted with the same key. Protect the database, encryption key and backups as credentials.

Outgoing requests

  • Signed. Every webhook carries a Standard Webhooks HMAC signature and timestamp so receivers can reject forgeries and replays. See Verify signatures.
  • SSRF protection. In hosted mode, cronpad resolves each hostname itself and refuses loopback, private, link-local (including cloud metadata at 169.254.169.254), carrier-grade NAT, IPv6 unique-local and deprecated site-local, multicast, unspecified, documentation and benchmarking addresses, the IETF 192.0.0.0/24 range, and NAT64, 6to4, Teredo and deprecated IPv4-compatible translation/tunnel prefixes, on every connection and every redirect hop. Only ports 80 and 443 are allowed.
  • Bounded. Timeouts, response size caps, and auto-disable stop a job from hammering an endpoint indefinitely.

Hosted mode

mode = "hosted" is how cronpad Cloud runs, and what you should use if strangers can sign up to your server.

SettingSelf-hosted defaultHosted mode
Command sinkOnOff
Webhooks to private networksAllowedBlocked
Email alert channelsUsable immediatelyAddress must be verified
Sign-upOff after the first user (auth.allow_signup)Rate-limited per IP; turn on with auth.allow_signup = true
Retry attempts, timeouts, auto-disable thresholdUnlimited / per jobCapped by server limits
Usage limitsUnlimitedFrom [limits]

Each can still be overridden explicitly in configuration.

Reporting a vulnerability

Please report security issues privately through the repository’s security advisory page (Security → Report a vulnerability) rather than in a public issue.