Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Security

- Validate synthetic ID format on inbound values from the `x-synthetic-id` header and `synthetic_id` cookie; values that do not match the expected format (`64-hex-hmac.6-alphanumeric-suffix`) are discarded and a fresh ID is generated rather than forwarded to response headers, cookies, or third-party APIs

### Added

- Implemented basic authentication for configurable endpoint paths (#73)
Expand Down
11 changes: 9 additions & 2 deletions crates/trusted-server-core/src/integrations/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1369,8 +1369,15 @@ mod tests {
let registry = IntegrationRegistry::from_routes(routes);

let mut req = Request::get("https://test.example.com/integrations/test/synthetic");
// Pre-existing cookie
req.set_header(header::COOKIE, "synthetic_id=existing_id_12345");
// Pre-existing cookie with a valid-format synthetic ID
req.set_header(
header::COOKIE,
format!(
"{}={}",
crate::constants::COOKIE_SYNTHETIC_ID,
crate::test_support::tests::VALID_SYNTHETIC_ID
),
);

let result = futures::executor::block_on(registry.handle_proxy(
&Method::GET,
Expand Down
5 changes: 3 additions & 2 deletions crates/trusted-server-core/src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1328,7 +1328,8 @@ mod tests {
sig
),
);
req.set_header(crate::constants::HEADER_X_SYNTHETIC_ID, "synthetic-123");
let valid_synthetic_id = crate::test_support::tests::VALID_SYNTHETIC_ID;
req.set_header(crate::constants::HEADER_X_SYNTHETIC_ID, valid_synthetic_id);

let resp = handle_first_party_click(&settings, req)
.await
Expand All @@ -1346,7 +1347,7 @@ mod tests {
assert_eq!(pairs.remove("foo").as_deref(), Some("1"));
assert_eq!(
pairs.remove("synthetic_id").as_deref(),
Some("synthetic-123")
Some(valid_synthetic_id)
);
assert!(pairs.is_empty());
}
Expand Down
15 changes: 10 additions & 5 deletions crates/trusted-server-core/src/publisher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ pub fn handle_publisher_request(
mod tests {
use super::*;
use crate::integrations::IntegrationRegistry;
use crate::test_support::tests::create_test_settings;
use crate::test_support::tests::{create_test_settings, VALID_SYNTHETIC_ID};
use fastly::http::{Method, StatusCode};

#[test]
Expand Down Expand Up @@ -518,9 +518,14 @@ mod tests {
#[test]
fn revocation_targets_cookie_synthetic_id_not_header() {
let settings = create_test_settings();
let cookie_synthetic_id =
"b2a1c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0b1a2.Zx98y7";
let mut req = Request::new(Method::GET, "https://test.example.com/page");
req.set_header("x-synthetic-id", "header_id");
req.set_header("cookie", "synthetic_id=cookie_id; other=value");
req.set_header(HEADER_X_SYNTHETIC_ID, VALID_SYNTHETIC_ID);
req.set_header(
header::COOKIE,
format!("synthetic_id={cookie_synthetic_id}; other=value"),
);

let cookie_jar = handle_request_cookies(&req).expect("should parse cookies");
let existing_ssc_cookie = cookie_jar
Expand All @@ -533,11 +538,11 @@ mod tests {

assert_eq!(
existing_ssc_cookie.as_deref(),
Some("cookie_id"),
Some(cookie_synthetic_id),
"should read revocation target from cookie value"
);
assert_eq!(
resolved_synthetic_id, "header_id",
resolved_synthetic_id, VALID_SYNTHETIC_ID,
"should still resolve request synthetic ID from header precedence"
);
}
Expand Down
Loading
Loading