Skip to content

Validate synthetic ID format on inbound header and cookie values#508

Open
prk-Jr wants to merge 1 commit intomainfrom
validate-synthetic-id-format
Open

Validate synthetic ID format on inbound header and cookie values#508
prk-Jr wants to merge 1 commit intomainfrom
validate-synthetic-id-format

Conversation

@prk-Jr
Copy link
Collaborator

@prk-Jr prk-Jr commented Mar 16, 2026

Summary

  • Inbound synthetic IDs from the x-synthetic-id header and synthetic_id cookie were accepted without validation, allowing injection of arbitrary strings into response headers, cookies, and third-party API calls
  • Adds a private is_valid_synthetic_id() validator (64 lowercase hex + . + 6 alphanumeric) with an O(1) length check first to bound all downstream work; invalid values are silently discarded and a fresh ID is generated in their place
  • Hardens logging by ensuring the raw ID value never appears in warn logs and demoting synthetic ID values from INFO to DEBUG to avoid recording pseudonymous identifiers in production log pipelines

Changes

File Change
crates/common/src/synthetic.rs Add is_valid_synthetic_id() production validator; validate in get_synthetic_id(); add debug_assert! in generator; demote ID values to debug!; new rejection + fallthrough tests
crates/common/src/test_support.rs Add shared VALID_SYNTHETIC_ID constant
crates/common/src/proxy.rs Update test fixture to use VALID_SYNTHETIC_ID
crates/common/src/integrations/registry.rs Update test fixture to use valid-format cookie value
docs/guide/synthetic-ids.md Document inbound validation behaviour and clarify HMAC determinism
CHANGELOG.md Add ### Security entry under [Unreleased]

Closes

Closes #412

Test plan

  • cargo test --workspace
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo fmt --all -- --check
  • JS format: cd crates/js/lib && npm run format
  • Docs format: cd docs && npm run format

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

Inbound synthetic IDs from the x-synthetic-id header and synthetic_id
cookie were accepted without validation. An attacker could inject
arbitrary strings — including very long values, special characters, or
newlines — which were then set as response headers, cookies, and
forwarded to third-party APIs.

Adds a private is_valid_synthetic_id() validator enforcing the canonical
format (64 lowercase hex chars + '.' + 6 alphanumeric chars). The length
check is O(1) and runs first to bound all downstream work. Invalid values
are silently discarded and a fresh ID is generated in their place; the
raw value is never written to logs.

Also adds a debug_assert! in generate_synthetic_id() to catch any future
regression in the generator, moves VALID_SYNTHETIC_ID to test_support so
it is shared across all test modules, and demotes synthetic ID values from
INFO to DEBUG in log output to avoid recording pseudonymous identifiers in
production log pipelines.

Closes #412
@prk-Jr prk-Jr self-assigned this Mar 16, 2026
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.

No synthetic ID format validation on inbound values

1 participant