| Version | Supported |
|---|---|
| Latest release | Yes |
| Previous minor | Security fixes only |
We recommend always running the latest release.
Do not open a public issue for security vulnerabilities.
To report a security vulnerability, please use GitHub's private vulnerability reporting:
- Go to the Security Advisories page
- Click "Report a vulnerability"
- Fill in the description, steps to reproduce, and affected versions
This ensures the vulnerability is disclosed privately to maintainers and can be fixed before public disclosure. You will receive updates on the advisory as it is triaged and resolved.
If you are unable to use GitHub's reporting, email the maintainer directly.
- Encryption at rest via CSP services: Sensitive variables and VCS tokens are stored in PostgreSQL and protected by database encryption-at-rest (e.g. RDS encryption, Cloud SQL encryption, Azure Database encryption). State files are stored as-is in object storage and protected by object store encryption-at-rest (S3 SSE, Azure Storage encryption, GCS default encryption). For filesystem-backed storage, enable volume encryption at the infrastructure level.
- Session-based auth: Web sessions are server-side (Redis) with 12-hour sliding TTL. Revoking a session takes effect instantly.
- API tokens: Long-lived tokens for CLI and automation are SHA-256 hashed
at rest. Only the raw token value is returned once at creation time.
Configurable max TTL via
auth.api_token_max_ttl_hours. - Label-based RBAC: Hierarchical workspace permissions (read/plan/write/admin); the presets expand to fine-grained
resource:verbcapabilities for precise scoping (#585) with label-based access control. No teams — labels replace teams entirely. - MFA delegated to IdP: Terrapod never implements MFA directly. Your identity provider (Auth0, Okta, Azure AD) handles MFA enforcement.
- RFC3339 timestamps: All datetimes are timezone-aware UTC, serialized with
trailing
Z. No naive datetimes anywhere in the codebase. - Multi-replica safe: No leader election. All background tasks coordinate via Redis-based distributed scheduler with mutual exclusion.
- Certificate-based runner auth: Runner listeners authenticate via Ed25519 certificates issued by the built-in CA after joining a pool with a token.
- Container images are scanned with Trivy for HIGH/CRITICAL CVEs, and the scan blocks publication — an image carrying a fixable HIGH/CRITICAL never becomes a published tag.
pip-audit(Python) andnpm audit(frontend) gate dependencies; Dependabot raises upgrade pull requests continuously.- Static analysis via CodeQL and Semgrep with OWASP Top 10 and custom project rules.
- Dynamic application security testing via Nuclei with custom templates — run on demand against a live stack, not in CI, because no CI job stands one up. Treat it as a tool a maintainer reaches for, not a gate every change passes.
If you gate on HIGH/CRITICAL CVEs, read the CVE policy.
It states exactly what the image gate guarantees, the honest limits of
ignore-unfixed (a vulnerability becomes visible to the gate when a fix ships,
which may be after disclosure — we answer that with roughly weekly releases, not
a lower bar), why a scan of an older release legitimately reports findings a
newer one has already fixed, and the reasoning behind every entry in the
accepted-risk register. Those suppressions are local to our pipeline and
suppress nothing in your scanners, so each is written to be evaluated — and
disagreed with — from outside the project.
Every release is cryptographically verifiable. Each container image and the Helm chart are keyless-signed with cosign (via GitHub OIDC — no long-lived signing key), and each image carries an SBOM (SPDX) attestation and a SLSA build-provenance attestation, discoverable as OCI referrers on the image digest. SBOMs and a checksums file are also attached to every GitHub Release.
Verify before deploying:
# Image (or chart) signature — identity pinned to the release workflow's OIDC:
cosign verify ghcr.io/mattrobinsonsre/terrapod-api:vX.Y.Z \
--certificate-identity-regexp '^https://github.com/mattrobinsonsre/terrapod/\.github/workflows/ci\.yml@refs/tags/v.*$' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
# SBOM + build provenance:
gh attestation verify oci://ghcr.io/mattrobinsonsre/terrapod-api:vX.Y.Z --repo mattrobinsonsre/terrapodFull verification details, the complete artifact list, and admission-time
enforcement patterns (e.g. Kyverno) are in
Supply-chain Verification.
That guide also covers the other direction — how Terrapod verifies the
upstream terraform/tofu binaries and provider archives it caches against the
publisher's GPG-signed SHA256SUMS, with the runner re-verifying the
executable before it runs.
Terrapod includes a three-layer security testing framework. The first two layers also run in CI on every change; the third needs a live deployment to point at, so it is run on demand:
| Layer | Tool | What it covers |
|---|---|---|
| SAST | Semgrep | Source code analysis, OWASP Top 10, secrets detection, project-specific rules |
| Container scanning | Trivy | CVEs in Docker images (HIGH/CRITICAL) |
| DAST | Nuclei | Auth bypass, header injection, CORS, state endpoint security — local only, needs a running stack |
Run with:
make pentest-sast # Static analysis
make pentest-images # Container image CVE scan
make pentest-dast # Dynamic testing (requires running stack)
make pentest # All three layersSee the Security Hardening Guide for production hardening, including:
- TLS configuration (database, Redis, ingress)
- Authentication hardening (disable local auth, token TTL, SSO enforcement)
- Secrets management (Kubernetes Secrets, External Secrets Operator)
- Network policies (pod-to-pod traffic restriction)
- Pod Security Standards (namespace-level enforcement)
- Rate limiting (API and auth endpoint protection)
- Audit log retention and SIEM export
- Database and object storage hardening
- Runner isolation (dedicated nodes, security contexts)
- Backup strategy
See also the Deployment Guide for general production deployment guidance.