Skip to content

Scope secret references to prevent config-store writers exfiltrating unrelated secrets #1037

Description

@ChristianPavilonis

Problem

Secret references in the app-config blob currently become direct lookups in the default Trusted Server secret store. A principal that can write the config blob can choose any non-empty secret key name, recompute the blob checksum, and make Trusted Server resolve that secret at runtime.

This breaks the intended boundary between config-store write access and secret-store read access. In particular, a config writer can assign an unrelated secret key to ec.partners[*].ts_pull_token, configure a controlled pull-sync URL and allowlist, and cause the resolved value to be sent as an outbound Bearer token.

BlobEnvelope::verify() provides integrity checking, but is not an authorization boundary: a config-store writer can create a valid checksum for modified data.

Goal

Prevent a config-store writer from selecting or exporting a secret outside the secret scope explicitly assigned to the relevant configuration field, without adding a separate signature/authentication layer to config envelopes.

Proposed direction

  • Do not use an arbitrary string from the config blob as a physical secret-store key.
  • Define field-owned secret namespaces/slots, selected by schema metadata and resolved by the runtime/platform adapter. For example, proxy authentication, EC inbound tokens, EC pull-sync tokens, and handler passwords must be separate scopes.
  • Keep each field's resolver confined to its own scope; a value intended for publisher.proxy_secret must never be resolvable as a pull-sync token, and vice versa.
  • Use platform-native secret-store capabilities and deployment provisioning for the mapping. This follow-up should not require signing config envelopes.
  • Treat credentials sent to an external service (currently ts_pull_token) specially: its allowed destination and credential identity must not both be freely retargetable by a config-store writer. Namespacing prevents cross-scope theft, but alone does not prevent export of a pull-sync credential if the mutable blob can also redirect its endpoint.

Acceptance criteria

  • No app-config string is used directly as an unrestricted secret-store key.
  • Secret resolution is restricted to a field-owned namespace/slot and behaves consistently across Fastly, Axum, Cloudflare, and Spin.
  • A config-store writer cannot cause publisher.proxy_secret, EC inbound api_token, handler passwords, or another unrelated secret to be emitted in a pull-sync Authorization header.
  • Pull-sync credentials cannot be redirected to a config-writer-controlled destination solely by changing the mutable config blob.
  • Migration guidance documents the namespace/provisioning model and any required secret moves.
  • Tests model a config-store-only attacker attempting cross-field secret substitution and pull-sync exfiltration; the attempt must fail before any outbound request is made.

Relevant code

  • crates/trusted-server-core/src/config_payload.rs
  • crates/trusted-server-core/src/secret_resolution.rs
  • crates/trusted-server-core/src/ec/pull_sync.rs
  • crates/trusted-server-core/src/config.rs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions