| Version | Supported |
|---|---|
| Latest | Yes |
| Older | No |
We support only the current release. Please upgrade before reporting a vulnerability.
Do not open a public GitHub issue for security vulnerabilities.
Report vulnerabilities privately via GitHub's Security Advisories feature (Settings > Security > Advisories > New draft advisory).
Please include:
- A description of the vulnerability and its potential impact
- Steps to reproduce or a proof-of-concept (if safe to share)
- The version(s) affected
- Any suggested mitigations you are aware of
We aim to acknowledge reports within 3 business days and to provide a resolution timeline within 10 business days.
Once a fix is available we will:
- Release a patched version
- Publish a GitHub Security Advisory crediting the reporter (unless anonymity is requested)
- Add an entry to CHANGELOG.md
ballastd runs inside the cluster with permission to watch and mutate workloads,
so a compromised build or dependency would be a high-value foothold. We treat the
software supply chain as the primary attack surface and defend it in layers:
dependencies, the build pipeline, published artifacts, and the runtime. This
section is a living checklist of what is in place today and what is planned. It is
intentionally light on exploitable specifics; report anything sensitive privately
via the process above.
-
govulncheckgate in CI (symbol-level, tokenless) runs on every push and pull request, including Dependabot and fork PRs that cannot access secrets - Snyk (high-severity threshold) and SonarCloud scanning on trusted runs, on
main, and on a weekly schedule - Dependabot version updates across every ecosystem the repo ships from
(
gomod,github-actions,docker,devcontainers) - Dependabot alerts and automated security-update PRs enabled
-
dependency-review-actionon pull requests blocks newly introduced vulnerable or license-incompatible dependencies before merge - CodeQL static analysis (SAST) on pushes, pull requests, and a weekly schedule
- Every GitHub Action pinned to a full commit SHA (no mutable tags)
- Docker base images pinned by digest (
golangbuilder,distrolessruntime) - Reproducible build flags (
-trimpath, pinned-ldflags); Go toolchain single-sourced fromgo.modviago-version-file - Secret-dependent CI steps fail safe: they skip rather than run on untrusted (Dependabot/fork) runs, so repository secrets are never exposed to builds of untrusted dependency code
- Untrusted (fork) pull requests cannot reach registry credentials: the PR image build is restricted to same-repo pull requests
- Least-privilege
permissions:on every workflow (read-only by default; write scopes granted only to the jobs that need them) - Egress control on CI runners via
step-security/harden-runner: block-mode enforcement with observed-traffic allowlists on every workflow - OpenSSF Scorecard workflow
- Keyless (cosign/OIDC) signature for the released container image
- Keyless signature for the Helm chart, published as an OCI artifact to
ghcr.io/tight-line/charts/ballast(now the sole published Helm repo; the former GitHub Pages repo is frozen, see the README's "Older releases") - SLSA build-provenance attestation for the released image and chart (OCI + GitHub)
- Software Bill of Materials (SBOM) attached to the image as an attestation
Verify a released image (all keyless, no public key needed):
IMAGE=ghcr.io/tight-line/ballast:<tag> # use the tag you pulled
IDENTITY='^https://github\.com/Tight-Line/ballast/\.github/workflows/release\.yml@refs/tags/v'
ISSUER=https://token.actions.githubusercontent.com
# signature
cosign verify "$IMAGE" \
--certificate-identity-regexp "$IDENTITY" \
--certificate-oidc-issuer "$ISSUER"
# SLSA build provenance
cosign verify-attestation "$IMAGE" --type slsaprovenance1 \
--certificate-identity-regexp "$IDENTITY" \
--certificate-oidc-issuer "$ISSUER"
# SBOM (syft emits a versioned SPDX predicate type; the `spdxjson` shorthand
# does NOT match it)
cosign verify-attestation "$IMAGE" --type https://spdx.dev/Document/v2.3 \
--certificate-identity-regexp "$IDENTITY" \
--certificate-oidc-issuer "$ISSUER"Or verify the image's attestations with the GitHub CLI, which resolves the identity for you:
gh attestation verify oci://ghcr.io/tight-line/ballast:<tag> --repo Tight-Line/ballastThe Helm chart is signed the same way (same $IDENTITY / $ISSUER):
cosign verify ghcr.io/tight-line/charts/ballast:<version> \
--certificate-identity-regexp "$IDENTITY" \
--certificate-oidc-issuer "$ISSUER"
# install (or pull) the signed chart via OCI
helm install ballast oci://ghcr.io/tight-line/charts/ballast --version <version>- Distroless, non-root runtime image (
USER 65532, no shell) - Least-privilege review of the operator's RBAC (scoped to the verbs and resources it actually uses; ConfigMap access narrowed to the operator's own namespace rather than cluster-wide)
- Explicit hardened pod
securityContextin the Helm chart (readOnlyRootFilesystem, drop all capabilities,seccompProfile: RuntimeDefault,runAsNonRoot,allowPrivilegeEscalation: false) - Deployment guidance for admission-time verification (Kyverno and
policy-controller examples in
examples/admission) so clusters admit only signed, provenanced images
-
mainprotected: pull request required, status checks (test,lint,build,snyk,govulncheck) must pass and be up to date, force-pushes and deletions blocked - Secret scanning with push protection enabled
- Pre-commit hooks (
gitleakssecret scan,golangci-lint,shellcheck, end-of-file and trailing-whitespace fixers)