Skip to content

Fix weak and inconsistent secret default validation#467

Open
ChristianPavilonis wants to merge 4 commits intomainfrom
fix/secret-default-validation
Open

Fix weak and inconsistent secret default validation#467
ChristianPavilonis wants to merge 4 commits intomainfrom
fix/secret-default-validation

Conversation

@ChristianPavilonis
Copy link
Collaborator

Summary

  • Reject all known placeholder values for synthetic.secret_key ("secret-key", "secret_key", "trusted-server") and publisher.proxy_secret ("change-me-proxy-secret") at runtime startup so misconfigured deployments fail fast.
  • Consolidate validation into predicate methods (is_placeholder_secret_key, is_placeholder_proxy_secret) with explicit placeholder lists, replacing the inconsistent checks that missed the actual TOML defaults.
  • Improve error reporting by renaming InsecureSecretKey to InsecureDefault { field } so the error message identifies which secret triggered rejection.

Changes

File Change
crates/common/src/error.rs Renamed InsecureSecretKeyInsecureDefault { field: String } with a descriptive display message
crates/common/src/settings.rs Added PROXY_SECRET_PLACEHOLDERS const + is_placeholder_proxy_secret() on Publisher; replaced validate_secret_key() with SECRET_KEY_PLACEHOLDERS const + is_placeholder_secret_key() on Synthetic; added 4 unit tests
crates/common/src/settings_data.rs Replaced single == "secret-key" check with calls to both predicates; returns field-specific InsecureDefault errors; updated test to assert placeholder rejection
crates/common/build.rs Added comment explaining why placeholder rejection is intentionally skipped at build time

Closes

Closes #406

Test plan

  • cargo test --workspace
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo fmt --all -- --check

Checklist

  • Changes follow CLAUDE.md conventions
  • No unwrap() in production code — use expect("should ...")
  • Uses tracing macros (not println!)
  • New code has tests
  • No secrets or credentials committed

Reject all known placeholder values for synthetic.secret_key and
publisher.proxy_secret at runtime startup so deployments using
default secrets fail fast instead of running with predictable
cryptographic keys.
@ChristianPavilonis ChristianPavilonis self-assigned this Mar 10, 2026
Copy link
Collaborator

@aram356 aram356 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

# Severity File Finding
1 HIGH settings.rs proxy_secret has no validation — empty string passes and produces a deterministic crypto key
2 MEDIUM settings_data.rs Test is environment-dependent and can flap when CI overrides secrets
3 MEDIUM settings.rs Placeholder policy is scattered across two types and will drift
4 LOW settings_data.rs Only the first insecure field is reported; operator must fix-and-redeploy to find the second
5 NIT settings.rs Spurious #[allow(dead_code)] on public items that are actually used

…r checks

- Add #[validate(length(min = 1))] to proxy_secret to prevent empty
  strings from producing a deterministic crypto key
- Centralize placeholder validation into Settings::reject_placeholder_secrets()
  which collects all violations into a single error
- Rewrite tests to use explicit TOML input instead of build-time
  embedded config, making them deterministic across CI environments
- Remove spurious #[allow(dead_code)] from public items that are used
@ChristianPavilonis
Copy link
Collaborator Author

Review Feedback Addressed

All 5 items from @aram356's review have been addressed in cbef697:

# Severity Finding Resolution
1 HIGH proxy_secret has no validation — empty string produces deterministic crypto key Added #[validate(length(min = 1))] to proxy_secret field
2 MEDIUM Test is environment-dependent and can flap in CI Rewrote tests to use explicit TOML input with crate_test_settings_str() + string replacements — fully deterministic
3 MEDIUM Placeholder policy scattered across two types Centralized into Settings::reject_placeholder_secrets() — single source of truth for all secret placeholder checks
4 LOW Only first insecure field reported reject_placeholder_secrets() collects all violations and reports them in a single error
5 NIT Spurious #[allow(dead_code)] on public items Removed all 4 unnecessary annotations

All 480 tests pass, cargo fmt and cargo clippy clean.

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.

Weak/inconsistent secret default validation

2 participants