Skip to content

fix(helm): require API_KEY_HMAC_SECRET instead of deriving it from SECRET_KEY - #226

Merged
haksungjang merged 1 commit into
mainfrom
fix/helm-api-key-hmac-secret-failclosed
Aug 24, 2026
Merged

fix(helm): require API_KEY_HMAC_SECRET instead of deriving it from SECRET_KEY#226
haksungjang merged 1 commit into
mainfrom
fix/helm-api-key-hmac-secret-failclosed

Conversation

@haksungjang

Copy link
Copy Markdown
Contributor

Summary

security-reviewer follow-up on the A5 PR (#221, hash-migration to keyed
HMAC-SHA256 for API keys) flagged that charts/trustedoss/templates/secret.yaml
silently derived API_KEY_HMAC_SECRET from secretKey
(sha256sum "trustedoss-api-key-hmac-secret-v1:" + secretKey) instead of
failing the render, unlike secretKey itself, which already fails via
{{- fail ... -}} when unset. A derived value always looks "explicitly set"
to core.config.api_key_hmac_secret's APP_ENV != dev fail-closed check, so
that check could never fire against a chart-rendered Secret — silently
reopening the "leaked SECRET_KEY also exposes API-key hashing" risk A5 set
out to close.

  • secret.yaml: apiKeyHmacSecret now fails the render (same policy as
    secretKey) when unset and existingSecret is not set.
  • Every helm template/helm lint/helm install caller that previously
    only set secretKey now also sets apiKeyHmacSecret: the four golden
    test files, chart-release.yml's smoke render, ci/scan-values.yaml
    (Trivy IaC scan), and the installation docs (EN + KO mirror).
  • New guard test test_helm_api_key_hmac_secret_wiring.py: confirms
    API_KEY_HMAC_SECRET is wired via secretKeyRef into all four
    workloads (backend, worker-scan, worker-default, beat) when set, that the
    render fails with a clear message when unset, and that existingSecret
    still bypasses the requirement (mirrors secretKey's existing behavior).
    Same defect class as test_prod_failclosed_secrets_compose_wiring.py,
    which explicitly scoped itself out of Helm.
  • values.yaml and README.md (chart + docs-site, EN/KO) upgrade notes
    for operators relying on the old silent derivation.

Test plan

  • helm lint --strict charts/trustedoss with explicit values, and with
    -f ci/scan-values.yaml
  • helm template renders fail with the expected message when
    apiKeyHmacSecret is unset (full chart and --show-only)
  • ruff check / mypy clean (test-only change, no production Python
    touched — coverage-gate has nothing to diff)
  • node tools/em-dash/lint.mjs --base origin/main clean
  • node tools/ko-style/lint.mjs --all --fail-on S2 clean (0 findings)
  • node tools/docs-uat/extract.mjs --lint clean, and
    node tools/docs-uat/run.mjs --tier=nightly --doc=installation/helm.md
    passes with the updated command
  • actionlint .github/workflows/chart-release.yml clean
  • Targeted pytest (all Helm golden tests + the compose wiring guard):
    54 passed
  • Full local tests/unit (5613 passed) and tests/integration (1672
    passed) — remaining local-only failures are pre-existing disk-pressure
    and missing-local-worker artifacts on this laptop, none touching a file
    in this diff

…CRET_KEY

secret.yaml silently derived API_KEY_HMAC_SECRET from secretKey when
env.secret.apiKeyHmacSecret was left blank, so a chart-rendered Secret
always looked "explicitly set" to core.config.api_key_hmac_secret and
its fail-closed check never fired. That reopened the exact risk A5 was
meant to close: a leaked SECRET_KEY would also expose API-key hashing.
apiKeyHmacSecret now follows the same fail() policy as secretKey.

Updated every helm-template caller (golden tests, chart-release.yml,
scan-values.yaml, install/README docs) to pass an explicit value, and
added a security-reviewer follow-up guard test
(test_helm_api_key_hmac_secret_wiring.py) that renders all four
workloads and confirms the render fails cleanly when the value is
unset -- the Helm-side equivalent of
test_prod_failclosed_secrets_compose_wiring.py.

Ref: concurrency-scaling-tracker.md §2, A5 (27) Medium + Low follow-up.
@haksungjang
haksungjang merged commit b928f91 into main Aug 24, 2026
31 checks passed
@haksungjang
haksungjang deleted the fix/helm-api-key-hmac-secret-failclosed branch August 24, 2026 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant