Skip to content

feat(config): require each secret whose feature is in use, with no service token fallback #447

Open

Description

@Bccorb

Why

REFRESH_TOKEN_LOOKUP_SECRET, TOTP_SECRET_ENCRYPTION_KEY, OAUTH_STATE_SECRET and DECOY_SUBJECT_SECRET fall back to the service token, which the server adapter also holds. Rotating it after a leak then signs everyone out and makes stored TOTP secrets unreadable. v0.19 warns about this and marks the fallback deprecated (#432, #445); v0.20 removes it.

What

  • Remove the service token fallback from all four (src/lib/token.ts, src/services/totpService.ts, src/services/oauthService.ts, src/services/decoyPrincipal.ts)
  • Require each secret when the feature that uses it is in use, checked at boot after bootstrapSystemConfig and on config writes:
    • REFRESH_TOKEN_LOOKUP_SECRET: always (every session)
    • DECOY_SUBJECT_SECRET: always (every /login for an unknown identifier)
    • TOTP_SECRET_ENCRYPTION_KEY: when totp is in login_methods or any totp_credentials row exists; TOTP enrollment refuses while it is unset
    • OAUTH_STATE_SECRET: when any OAuth provider is configured; adding a provider refuses while it is unset
  • A config write that would turn a feature on without its secret answers 409 naming the variable
  • Boot errors name each missing variable and say to set it to the current service token value to keep existing data valid
  • Development mode follows the same rule, so local stacks set what they use. Development mode is already refused off localhost (fix(boot): refuse development mode settings outside localhost #431)

Ripple (merge before the API release)

Set each missing variable to the existing service token value, not a new one:

  • seamless-iac/portal-auth/main.tf: sets only the service token today
  • seamless-terraform-service: sets only the service token today
  • seamless-iac/roxtarget/main.tf, seamless-iac/grand-cross/main.tf: missing OAUTH_STATE_SECRET and DECOY_SUBJECT_SECRET
  • seamless-cli local stack generator (src/generators/docker/docker.ts): missing DECOY_SUBJECT_SECRET
  • validateEnvs.sh, docs/configuration.md, docs/production-operations.md, the docs site environment reference and production checklist

Done when

No secret is derived from the service token, a deployment with a feature on and its secret unset cannot boot or be configured into that state, and every deployment Fells Code runs is updated before the release.

Activity

  1. added this to the v0.20 milestone on Oct 17, 2026
  2. added
    P1Security work outside the FIDO2 track
    secureServes the most-secure promise
    v0.20Targets the v0.20 release
    on Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Security work outside the FIDO2 tracksecureServes the most-secure promisev0.20Targets the v0.20 release

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions