Skip to content

Security: ossko/colonies

Security

docs/Security.md

Security model and hardening

ColonyOS uses zero-trust, signature-based authentication: every authenticated RPC is signed with the caller's secp256k1 private key and the server recovers the caller's identity from the signature. The only exceptions are the version and server-info messages (versionmsg, getserverinfomsg), which are answered before signature verification. There are no cookies or sessions, so CSRF is not a concern; authorization is checked per handler against the recovered identity.

This document covers the transport- and protocol-level hardening added in v2.0 and the settings that control it. All settings live in the Security config section and can be set with COLONIES_SECURITY_* environment variables (or the config file). Defaults are chosen to be safe without breaking existing executors and SDKs.

HTTP transport

Setting Env Default Notes
Read-header timeout COLONIES_SECURITY_READ_HEADER_TIMEOUT 20 s Slowloris defense. Does not affect the response side, so the executor long-poll assign is unaffected. 0 disables.
Idle timeout COLONIES_SECURITY_IDLE_TIMEOUT 120 s Keep-alive idle bound. 0 disables.
Max body bytes COLONIES_SECURITY_MAX_BODY_BYTES 104857600 (100 MiB) Caps request bodies so an unauthenticated caller cannot exhaust memory. Also caps a single websocket message. 0 disables.
CORS allowlist COLONIES_SECURITY_CORS_ALLOW_ORIGINS empty Comma-separated browser origin allowlist. Empty installs no CORS middleware, so cross-origin browser requests get no allow header and are blocked by the browser; non-browser clients (executors, SDKs, CLI) send no Origin header and are always allowed. A non-* allowlist permits only GET/POST methods and the Origin, Content-Type, Accept headers. * restores allow-all.
WebSocket origin allowlist COLONIES_SECURITY_WS_ALLOW_ORIGINS empty Same semantics for /pubsub. Empty allows no-Origin (non-browser) and same-origin requests only. * allows any.
Rate limit COLONIES_SECURITY_RATE_LIMIT 0 (off) Per-client-IP requests/second on all routes; only /health is exempt. The assign long-poll and /pubsub subscribe count against the limit, so size it for the number of executors sharing a source IP.
Rate-limit burst COLONIES_SECURITY_RATE_LIMIT_BURST 0 (= rate) Allowed burst above the rate. 0 or negative falls back to the rate value.

The server always runs gin in release mode. When TLS is configured it is served with a minimum version of TLS 1.2.

Deliberately, no ReadTimeout/WriteTimeout is set on the HTTP server: the executor long-poll assign holds the response open, and /pubsub websockets are long-lived, so a blanket read/write deadline would break legitimate connections.

RPC replay protection

Signed RPC messages carry an optional nonce and timestamp. When the nonce is non-empty, the signed bytes are payload + "|" + timestamp + "|" + nonce, binding them against tampering; when the nonce is empty, only the payload is signed (the legacy scheme). The server rejects a message whose timestamp is outside the allowed skew window or whose nonce has already been seen.

Setting Env Default Notes
Mode COLONIES_SECURITY_REPLAY_PROTECTION advisory off (aliases disabled, none): ignore replay fields. advisory: check messages that carry replay fields, still accept legacy messages that omit them. enforce (aliases enforced, strict): additionally reject messages that lack replay fields. Any unrecognized value silently falls back to advisory, so a typo will not raise an error.
Window COLONIES_SECURITY_REPLAY_WINDOW 300 s Allowed timestamp skew. Nonces are retained for twice the window, since a message timestamped up to one window in the future stays valid until now + 2x the window.

Rollout is staged: v2.0 defaults to advisory so v2.0 clients are protected immediately while pre-v2.0 clients keep working. A later release is expected to default to enforce. Old clients that sign the payload only remain valid in off/advisory modes.

Cluster (multi-node only)

Single-node deployments run no relay or etcd. Multi-node clusters do, and those ports must be reachable only from trusted peers.

  • COLONIES_CLUSTER_SECRET authenticates the cluster relay: peers HMAC-sign each broadcast (sent in the X-Colonies-Relay-Auth header) and the receiver rejects unsigned or mismatched posts. Set the same value on every node. When unset, the relay logs a warning at startup.
  • The embedded etcd peer/client ports have no TLS or authentication. Restrict them to a private/firewalled network. The server logs a warning when etcd binds to all interfaces in a multi-node configuration. (Full etcd mTLS is planned; see the modernization backlog.)

S3 credentials

S3 credentials are read from server/executor configuration (AWS_S3_*), never from per-file database records. The server does not persist or return S3 access keys, secret keys, or encryption keys; a migration blanks any that older versions stored. See modernization/DB-MIGRATION-NOTES.md.

There aren't any published security advisories