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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions