Skip to content

Security: ethan-kane-ops/cellcast

Security

SECURITY.md

Security Policy

cellcast issues credentials for production clusters. A vulnerability here is a route to cluster access rather than a defect in a tool that only observes.

Reporting a Vulnerability

Please do not open a public GitHub issue for security-related reports.

Report vulnerabilities privately via the GitHub Security Advisory page for this repository:

https://github.com/ethan-kane-ops/cellcast/security/advisories/new

When submitting a report, please include:

  • Affected component: hub, agent, client, or chart. The hub is the only one that can mint, so a finding there is more serious by default.
  • Description: what the vulnerability is, and its impact stated as what an attacker ends up holding.
  • Reproduction: step-by-step instructions, including the Cluster, PlacementPolicy and TrustConfig manifests, and the claims of the token presented. Redact token material; the claims are what matters.
  • Mitigation: any temporary workaround you have identified.

Response targets

Stage Target
Acknowledge receipt 48 hours
Triage and confirm severity 7 days
Fix released for critical severity 14 days

Reporters will be credited in the release notes for the fix unless they request anonymity.

What is in scope

The documented trust boundaries are in docs/threat-model.md, and anything that crosses one is in scope. In particular:

  • Authentication bypass. Any way to have the hub accept a token it should have rejected: a forged or replayed assertion, an issuer or audience that is not the configured one, a signature the hub does not actually verify.
  • Policy bypass. Any way to be placed on, or minted for, a cell that no matching PlacementPolicy permits. This includes reaching a DARK cell without a policy that allows it, and any path where a client-supplied value changes which policy applies.
  • TTL bypass. Any minted credential outliving --token-max-ttl, or a policy's own ceiling.
  • Credential disclosure. Token material reaching a log line, an audit record, a metric label, a Kubernetes Event, or an error returned to a caller. A test asserts that no field of the audit record can hold it; a way around that is a finding.
  • Confused deputy in capacity ingest. Any way for one cell's agent to publish capacity for a different cell, which steers real deploys.
  • Privilege escalation through the charts. RBAC in either chart that grants more than the component needs.

What is not in scope

  • An operator granting a policy more than they meant to. cellcast enforces the policy that is written, and --dry-run --explain shows what a policy does before it is relied on.
  • A compromised hub cluster. Whoever controls the hub's ServiceAccount can read the trust configuration it holds and mint what that configuration allows; that is the hub's whole job, and the threat model says so.
  • Denial of service by a caller who is already authenticated and permitted.
  • A cell whose service account issuer URL collides with another cell's, on a cluster that was configured that way. The hub binds a reporter identity to an issuer, so distinct issuers are a prerequisite the docs state plainly.

Supported Versions

Only the latest minor release line receives security updates. Today that is v0.1.x.

Version Supported
Latest minor Yes
Anything older No

Pre-1.0, the API and the CRD schema may change between minor versions.

Scanning

govulncheck runs over the source and over the built binaries. It reports only advisories reachable through the call graph rather than every advisory touching a dependency, so a non-empty result names something to fix rather than a list to triage. It runs in just check-all, which just release runs, so a release cannot ship a known reachable vulnerability.

CodeQL analyses the source on every push and weekly. OSSF Scorecard runs against main and publishes its result. Both are computed against a public repository, so neither produces a score until the repository is one.

The repository-side properties they inspect are already in place and held by tests: base images pinned by digest rather than tag, no compiled artefact in the tree, a private reporting route in this file, a declared licence matching the one the charts advertise, a release that signs everything it publishes, and fuzz targets over every parser that reads untrusted input. Every workflow declares a scoped token and pins each action to a commit rather than a tag, which just check enforces: a tag can be moved, and moving it hands a third party write access on the next run.

Release integrity

Every published image and chart is signed with cosign keyless signing, and every image carries an SBOM and SLSA build provenance as attestations. The exact cosign verify command, including the identity and issuer to expect, is in the README under Verifying what you install.

Keyless means the signature is tied to an identity rather than to a key, so a signature on its own proves nothing: verification has to name the expected signer. The release runs that verification against what it has just published and fails if the identity does not match.

Images are also reproducible from their tag. The base images are pinned by digest, the build runs with -trimpath, and the timestamps come from the commit rather than the build clock, so rebuilding a tag from source produces the same bytes. See Releasing.

There aren't any published security advisories