From 12c25f9c77f7b44e65ab9855ada9f3a8ab834604 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 03:33:21 +0900 Subject: [PATCH 1/6] test(core): reject non-digit origin port prefixes --- .../tests/origin_port_syntax.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 crates/originweave-core/tests/origin_port_syntax.rs diff --git a/crates/originweave-core/tests/origin_port_syntax.rs b/crates/originweave-core/tests/origin_port_syntax.rs new file mode 100644 index 000000000..ce58e523e --- /dev/null +++ b/crates/originweave-core/tests/origin_port_syntax.rs @@ -0,0 +1,18 @@ +use originweave_core::{Origin, OriginError}; + +#[test] +fn origin_rejects_non_digit_port_prefixes() { + for input in [ + "https://example.com:+443", + "https://example.com:+8443", + "http://localhost:+80", + "http://127.0.0.1:+8080", + "https://[2001:db8::1]:+443", + ] { + assert_eq!( + Origin::parse(input), + Err(OriginError::InvalidPort), + "input={input}" + ); + } +} From 222d52f2a9bbee4ee8eebb17e79bab0a61d247f7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 03:41:00 +0900 Subject: [PATCH 2/6] fix(core): enforce digit-only origin ports --- crates/originweave-core/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/originweave-core/src/lib.rs b/crates/originweave-core/src/lib.rs index 88dd2e586..b7ab20379 100644 --- a/crates/originweave-core/src/lib.rs +++ b/crates/originweave-core/src/lib.rs @@ -165,6 +165,9 @@ fn parse_bracketed_ipv6(authority: &str) -> Result<(String, Option, bool), } fn parse_port(port_text: &str) -> Result { + if port_text.is_empty() || !port_text.bytes().all(|byte| byte.is_ascii_digit()) { + return Err(OriginError::InvalidPort); + } let port = port_text .parse::() .map_err(|_error| OriginError::InvalidPort)?; @@ -1062,4 +1065,4 @@ pub fn evaluate_extension_access( return ExtensionAccessDecision::DenyCapabilityNotGranted; } ExtensionAccessDecision::Allow -} +} \ No newline at end of file From 1232edad8d50fb56c4f028309945b3cee0c310fa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 04:11:14 +0900 Subject: [PATCH 3/6] fix(core): restore canonical rustfmt newline --- crates/originweave-core/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/originweave-core/src/lib.rs b/crates/originweave-core/src/lib.rs index b7ab20379..632ca9490 100644 --- a/crates/originweave-core/src/lib.rs +++ b/crates/originweave-core/src/lib.rs @@ -422,7 +422,7 @@ pub enum NodeHandleError { StaleDocumentEpoch { /// Epoch that originally produced the node handle. observed: DocumentEpoch, - /// Epoch currently active in the browser context. + /// Epoch currently active for the requested action. current: DocumentEpoch, }, } @@ -1065,4 +1065,4 @@ pub fn evaluate_extension_access( return ExtensionAccessDecision::DenyCapabilityNotGranted; } ExtensionAccessDecision::Allow -} \ No newline at end of file +} From a6ad10cfaace873f600db85305a1a743d444e124 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 04:17:09 +0900 Subject: [PATCH 4/6] docs(changelog): record strict origin port syntax --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e4bd39ca..a70b658cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ All notable changes to OriginWeave are documented in this file. The format follo - State-changing actions are same-origin by default. - R3 and R4 approvals are bound to the exact action, target origin, and immutable digest of the complete canonical action intent; R5 legal consent is non-delegable. - Shortened, integer, hexadecimal, and legacy octal-looking IPv4 host spellings are rejected so the policy origin cannot diverge from Chromium host interpretation. +- Explicit origin ports must contain ASCII decimal digits before numeric parsing, preventing Rust-only signed spellings such as a leading `+` from diverging from browser URL port syntax. - IPv4-mapped IPv6 is canonicalized before destination classification and pin comparison so mapped private or loopback addresses cannot bypass IPv4 policy. - The default destination policy permits only public addresses and denies unspecified, loopback, private, shared, link-local, metadata, documentation, benchmarking, multicast, broadcast, transition, and protocol-reserved destinations. - Azure platform IP `168.63.129.16` and Amazon EKS Pod Identity endpoints `169.254.170.23` and `fd00:ec2::23` are classified as metadata or platform services before broader public, link-local, or unique-local rules. From a119190918999858c66f43bc3f613f05e072b544 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 16:56:59 +0900 Subject: [PATCH 5/6] chore(core): remove unrelated node-handle doc drift --- crates/originweave-core/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/originweave-core/src/lib.rs b/crates/originweave-core/src/lib.rs index 632ca9490..36bada998 100644 --- a/crates/originweave-core/src/lib.rs +++ b/crates/originweave-core/src/lib.rs @@ -422,7 +422,7 @@ pub enum NodeHandleError { StaleDocumentEpoch { /// Epoch that originally produced the node handle. observed: DocumentEpoch, - /// Epoch currently active for the requested action. + /// Epoch currently active in the browser context. current: DocumentEpoch, }, } From 240a66d991ba2d68c2ba6a900dd06951b25c68e6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 17:09:54 +0900 Subject: [PATCH 6/6] docs(core): cite browser port syntax authority --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a70b658cc..f705f96fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,7 +50,7 @@ All notable changes to OriginWeave are documented in this file. The format follo - State-changing actions are same-origin by default. - R3 and R4 approvals are bound to the exact action, target origin, and immutable digest of the complete canonical action intent; R5 legal consent is non-delegable. - Shortened, integer, hexadecimal, and legacy octal-looking IPv4 host spellings are rejected so the policy origin cannot diverge from Chromium host interpretation. -- Explicit origin ports must contain ASCII decimal digits before numeric parsing, preventing Rust-only signed spellings such as a leading `+` from diverging from browser URL port syntax. +- Explicit origin ports must contain ASCII decimal digits before numeric parsing, matching the WHATWG URL Standard port-state syntax and preventing Rust-only signed spellings such as a leading `+` from creating a browser/parser authority mismatch. - IPv4-mapped IPv6 is canonicalized before destination classification and pin comparison so mapped private or loopback addresses cannot bypass IPv4 policy. - The default destination policy permits only public addresses and denies unspecified, loopback, private, shared, link-local, metadata, documentation, benchmarking, multicast, broadcast, transition, and protocol-reserved destinations. - Azure platform IP `168.63.129.16` and Amazon EKS Pod Identity endpoints `169.254.170.23` and `fd00:ec2::23` are classified as metadata or platform services before broader public, link-local, or unique-local rules. @@ -74,4 +74,8 @@ All notable changes to OriginWeave are documented in this file. The format follo - The hourly product agent has no Git metadata or repository authority. A separate post-verification publisher opens one PR and cannot approve or merge it. - The unprivileged OpenCode user is restricted to loopback egress during model execution, preventing runner-wide allow-listed endpoints from becoming direct source-exfiltration channels. +### References + +Web Hypertext Application Technology Working Group. (2026). *URL standard*. https://url.spec.whatwg.org/ + [Unreleased]: https://github.com/ContextualWisdomLab/OriginWeave/compare/main...HEAD