Skip to content

Harden deploy validation: reject fail-open publisher hosts, APS pub_id, and request-signing store ids #871

Description

@aram356

Summary

Follow-up from #869 / PR #870. Several config fields fail open at ts config validate / deploy validation: template placeholder values (or trivially-fake values) pass validation and only fail later at runtime / key-rotation time. The secret placeholders (EC passphrase, proxy_secret, admin handler password, partner API tokens) are already rejected; these are the remaining gaps.

None of these are security holes on their own — a wrong domain or fake pub_id simply won't work at runtime — but rejecting them at config-push time gives operators a much faster, clearer failure.

Gaps

  1. Reserved example publisher hosts pass validation (High).
    [publisher] domain = "example.com", cookie_domain = ".example.com", origin_url = "https://origin.example.com" validate OK. An operator who changes the three secret placeholders but forgets the publisher block deploys against example.com.

    • Tension to resolve: CLAUDE.md mandates example.com in all examples, and the test suite uses example.com pervasively. Any rejection must distinguish "unedited template default" from legitimate test/example usage (e.g. only reject in validate_settings_for_deploy, and/or a dedicated reserved-host list mirroring the secret-placeholder approach). Needs its own tests.
  2. ApsConfig.pub_id has no non-empty/placeholder validation (Medium).
    With [integrations.aps] enabled = true, pub_id = "your-aps-publisher-id" validates (only custom deserialization runs, no #[validate]). Add a non-empty + placeholder check.

  3. RequestSigning has no Validate derive / placeholder rejection (Low).
    config_store_id / secret_store_id accept any string (e.g. <management-config-store-id>), so a misconfigured request-signing block validates and fails later at key rotation instead of at push.

Acceptance

  • ts config validate / deploy validation rejects each of the above with a clear message, without breaking the many example.com-based tests or the example config embedded in the Cloudflare/Spin adapters.
  • Once rejection lands, update trusted-server.example.toml comments accordingly (the template currently notes these as fail-open).

Context

  • Placeholder-secret rejection lives in Settings::reject_placeholder_secrets / validate_settings_for_deploy (config.rs) and the per-type *_PLACEHOLDERS lists (settings.rs).
  • Handler password rejection: Handler::PASSWORD_PLACEHOLDERS.
  • GTM already validates its container id via GTM_CONTAINER_ID_PATTERN — a good model for pub_id.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions