Security
Security
Section titled “Security”This page describes ShipSquares’ security architecture, threat model, and hardening guidance.
Reporting vulnerabilities
Section titled “Reporting vulnerabilities”If you discover a security vulnerability, please report it privately — do not open a public issue. Contact the maintainers directly or use the project’s security advisory feature.
Trust boundaries
Section titled “Trust boundaries”Internet (untrusted: webhooks, browsers, API clients) │ HTTPS only ▼Caddy (reverse proxy) — auto-HTTPS via ACME, on-demand TLS for custom domains │ localhost ▼Control plane (Node/TS) — session + API-key auth, RBAC per route, audit log, │ sealed secrets (AES-256-GCM) ├── PostgreSQL (job queue, sealed secrets, audit trail) └── Docker socket / SSH → deployed apps, managed DBs, worker serversAuthentication
Section titled “Authentication”- Sessions — secure, HttpOnly cookies,
SameSite=Strict. - API keys —
ss_live_*bearer tokens, SHA-256 hashed before storage. - 2FA / TOTP — optional per-user two-factor.
- SSO — OAuth with GitHub / Google when configured.
- Passkeys — WebAuthn support.
Authorization (RBAC)
Section titled “Authorization (RBAC)”Four roles with decreasing privilege:
| Role | Capabilities |
|---|---|
| owner | Full access: org settings, member management |
| admin | App/server management, secrets, deploys — no org admin |
| deployer | Deploy, view logs, restart apps — no secrets or server access |
| viewer | Read-only access to apps, logs, metrics |
API keys default to the deployer role and can be scoped to specific permissions.
Secrets
Section titled “Secrets”- At rest: AES-256-GCM with a master key (
SHIPSQUARES_MASTER_KEY, 256-bit). - Sealed values are stored as
{iv, ciphertext, tag, version}and resolved only at deploy time — never logged; values are masked in logs. - SSH keys are platform-generated Ed25519 keypairs with the private half sealed.
Tenant isolation
Section titled “Tenant isolation”- Every resource query is scoped by
organizationId. - Cross-tenant access returns
404(not403) to avoid leaking existence. - API keys are org-scoped; sessions track the active org and verify membership per request.
Threat model (selected)
Section titled “Threat model (selected)”| Threat | Mitigation |
|---|---|
| Credential theft | Secrets encrypted at rest, never logged; SSH keys sealed |
| Session hijacking | HttpOnly + SameSite cookies; HTTPS enforced |
| CSRF | SameSite=Strict; API uses bearer tokens |
| XSS | CSP headers; framework auto-escaping; no inline scripts |
| SQL injection | ORM with parameterized queries |
| SSRF | Database Studio validates hostnames against private ranges |
| Webhook spoofing | HMAC (SHA-256) signature verification |
Trust assumption: as with every Docker-based PaaS, the control plane holds access to the host Docker socket (root-equivalent). Protect the control-plane host and the master key accordingly.
Hardening checklist
Section titled “Hardening checklist”- Generate a strong master key (
openssl rand -hex 32) and set it via the environment. - Run the control plane as a non-root user with a least-privilege Postgres role.
- Allow only 80/443 inbound; restrict SSH.
- Set
ALLOW_SIGNUP=falseafter initial setup and invite members instead. - Require 2FA for
admin/owner, and configure SSO for org login. - Review the built-in audit log periodically.