Keyorix is a secrets manager. We hold ourselves to the standard we ask you to trust us with: every control described here is verifiable in this repository's CI configuration and release artifacts.
| Version | Supported |
|---|---|
| Latest release | ✅ Security fixes |
| Older releases | ❌ Upgrade to latest |
Keyorix is pre-1.0 and has not yet declared a support period under the EU Cyber Resilience Act. Pre-1.0 tags are development releases: they carry no declared support period and no Declaration of Conformity.
From v1.0, LTS releases receive five years of security updates, delivered to air-gapped deployments as signed offline bundles with an SBOM and a VEX document. See SUPPORT.md for the full policy and ADR-067 for the rationale.
Do not open a public GitHub issue for security vulnerabilities.
- Email: security@keyorix.com
- Or use GitHub's private vulnerability reporting on this repository
We acknowledge within 48 hours and provide an initial assessment within 7 days.
Please include: a description, reproduction steps, and the affected version
(keyorix --version / keyorix-server --version).
We follow coordinated disclosure: we'll agree a disclosure timeline with you, credit you in the advisory unless you prefer otherwise, and publish a fix and advisory together. As an EU vendor we operate under the EU Cyber Resilience Act reporting regime for actively exploited vulnerabilities.
Once a report is acknowledged and assessed (see above), here's what to expect through to a fix:
| Commitment | Detail |
|---|---|
| Fix, all severities | Within 90 days of a validated report |
| High / Critical severity | 1 week advance notice before the security release ships |
| Advisory | A GitHub Security Advisory with a requested CVE, published the same day as the fix |
| Supported versions | Latest release only (see Supported Versions above) |
The 90-day figure is a ceiling, not a target — most fixes ship well inside it. We publish one commitment across all severities rather than a severity-tiered deadline: a severity call made under public time pressure is exactly the kind of promise a one-person team without redundancy shouldn't be making a clock out of. We do not publish a release cadence — releases ship as fixes are ready, not on a calendar.
This is a current operating commitment, not a CRA-declared support period. It says how fast we fix things once a version is receiving fixes at all; it does not change which versions that is, or for how long — that is governed separately by the Supported Versions table above and SUPPORT.md, and remains undeclared pre-1.0 regardless of this commitment.
See ADR-104 for the reasoning, the competitor research behind these numbers, and the internal CRITICAL/HIGH definition used for prioritization. This table is the authoritative, current source for the published commitment above; ADR-104 also states it for the record, but if the two ever disagree, this page is current and ADR-104's copy is stale.
Keyorix server runs entirely within your perimeter:
- No telemetry, no usage metering, no "phone home" — ever. Air-gapped operation is a first-class deployment model, not a degraded mode.
- All secret values encrypted at rest with AES-256-GCM (authenticated encryption, AAD-bound to secret identity). Envelope encryption: the data key is wrapped by a key derived from an operator passphrase (PBKDF2-SHA256, 600k iterations); no plaintext key material is ever written to disk.
- Session tokens, API tokens, and client secrets are encrypted at rest.
- Every secret access and every administrative action is written to an append-only audit log in your database.
- RBAC is enforced at the API level, not the UI.
What Keyorix never does: open outbound connections to us, embed third-party analytics, or require internet access for any cryptographic operation.
A full STRIDE threat model is maintained internally and shared with customers and prospects under evaluation — ask via hello@keyorix.com.
Every release ships with checksums.txt:
sha256sum --check --ignore-missing checksums.txtEvery release also ships one CycloneDX SBOM per binary (e.g.
keyorix-server_linux_amd64_sbom.cdx.json, 8 total across the CLI and server
binaries × linux/darwin × amd64/arm64) — a full dependency and licence
inventory, the component list needed to assess CVE exposure under the EU CRA.
The four server binaries embed a built React dashboard (server/webui); each
of their SBOMs links to one shared, production-scope frontend SBOM
(keyorix-server_frontend_sbom.cdx.json) via a hashed CycloneDX
externalReferences entry, so a scanner pointed at a server binary's own SBOM
can follow the link rather than needing a separate download step (ADR-073).
All 9 SBOMs are covered by checksums.txt.
Release binaries are built with -trimpath and CGO_ENABLED=0 from the tagged
commit. checksums.txt and every container image are keylessly signed with
Sigstore/cosign via GitHub's OIDC token — no
long-lived signing key exists to leak. Verify with cosign installed:
# checksums.txt (release binaries)
cosign verify-blob \
--certificate checksums.txt.pem --signature checksums.txt.sig \
--certificate-identity-regexp 'https://github.com/keyorixhq/keyorix/\.github/workflows/release\.yml@.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
checksums.txt
# container images (also carries an SBOM + SLSA build provenance attestation)
cosign verify \
--certificate-identity-regexp 'https://github.com/keyorixhq/keyorix/\.github/workflows/docker-publish\.yml@.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/keyorixhq/keyorix-server:<tag>Download releases only from github.com/keyorixhq/keyorix/releases over HTTPS.
- Pre-commit gates:
gofmt,go vet,go build,gosec(MEDIUM+ severity) - CI gates on every push and pull request (11+ required checks, see
CONTRIBUTING.md for the full list):
go vet, race-enabled tests,govulncheck,gosec(pinned version),golangci-lint,gitleakssecret scan (scoped to the PR's own commit history),CodeQL(dataflow/taint analysis, both Go modules), Helm chart schema validation (kubeconform) and security-policy scanning (checkov— pod security context, RBAC-escalation checks), Go dependency license compliance (rejects any dependency outside an explicit permissive-license allowlist), and DCO sign-off verification - Continuous fuzzing: native Go fuzz targets (
go test -fuzz) at the codebase's highest-risk parsing/escaping boundaries (Shamir secret-share reconstruction, JWT/OIDC verification, rotation-credential SQL escaping and ref interpolation, secret-template parsing) run for hours at a time on dedicated infrastructure, well beyond what a CI job's budget allows — seescripts/fuzzing/README.md - Recurring bug classes get a permanent, blocking check, not just a one-off
fix: every confirmed vulnerability is checked against the fix history for
the same underlying pattern recurring 3+ times, and each one that does gets
a custom CodeQL query or Semgrep rule modeled on the real fix and validated
against it before merge — see
.semgrep/RULE-MINING-PROCESS.mdfor the process and.github/codeql/go-queries//.semgrep/keyorix-rules.ymlfor the current rule set. Everyfix(security)PR is required to carry a regression test proving the specific bug is closed, not just that the static pattern is gone from the diff. - CODEOWNERS requires review on cryptography, auth/RBAC, middleware, database migrations, the CI/CD pipeline itself, and this policy
- GitHub-native repository security: secret scanning, push protection (blocks a commit containing a detected secret before it lands), Dependabot security updates, and private vulnerability reporting are all enabled
- Any change to the encryption layer requires a written Architecture Decision Record before implementation
- External contributions require DCO sign-off (
git commit -s— see CONTRIBUTING.md) and maintainer review. Branch protection onmainrequires every required CI check to pass (enforced for maintainers too, no bypass) before a PR can merge.
KEYORIX_MASTER_PASSWORDis the root credential — inject it via systemd credentials/EnvironmentFile(0600) or a Kubernetes Secret, never a config file.- Run
keyorix-serveras a non-root service user. - TLS is required in production; the CLI
--insecureflag is for local development only.