mirror of
https://github.com/openai/codex.git
synced 2026-09-20 12:47:38 +00:00
Document and test ? wildcards in network proxy domain patterns (#46027)
## What changed Document the existing `?` wildcard behavior: it matches exactly one character, including a dot, in allow and deny patterns. For example, `api?.example.com` matches `api1.example.com`, but not `api.example.com` or `api12.example.com`. ## Testing Add table-driven tests for both allowlist and denylist compilation, covering single and repeated `?` wildcards, combinations with `*`, `*.`, and `**.`, dot matching, and host and pattern normalization. GitOrigin-RevId: dd5cd1817c6ea0b701335a38a57fbb5e8039c284
This commit is contained in:
@@ -214,6 +214,9 @@ what it can reasonably guarantee.
|
||||
|
||||
- Allowlist-first policy: if `domains` has no `allow` entries, requests are blocked until an allowlist is configured.
|
||||
- Domain patterns: exact hosts are supported, `*.example.com` matches subdomains only, and `**.example.com` matches the apex plus subdomains; the global `*` wildcard is only accepted when explicitly enabled for allowlist compilation and is otherwise rejected.
|
||||
- Within a domain pattern, `?` matches exactly one character, including a dot. For example,
|
||||
`api?.example.com` matches `api1.example.com`, but not `api.example.com` or `api12.example.com`.
|
||||
It can be combined with `*`, `*.`, and `**.` in both allow and deny entries.
|
||||
- Deny wins: `domains` entries marked `deny` always override the allowlist.
|
||||
- Local/private network protection: when `allow_local_binding = false`, the proxy blocks loopback
|
||||
and common private/link-local ranges. Explicit allowlisting of local IP literals (or `localhost`)
|
||||
|
||||
@@ -200,6 +200,9 @@ pub(crate) fn compile_denylist_globset(patterns: &[String]) -> Result<GlobSet> {
|
||||
compile_globset_with_policy(patterns, GlobalWildcard::Reject)
|
||||
}
|
||||
|
||||
// Browser network-policy matchers implement a subset of this hostname grammar.
|
||||
// Keep changes to shared grammar and normalization in sync with their contract
|
||||
// cases and the Rust tests below, including compile_globset_supports_question_mark_wildcards.
|
||||
fn compile_globset_with_policy(
|
||||
patterns: &[String],
|
||||
global_wildcard: GlobalWildcard,
|
||||
@@ -217,6 +220,7 @@ fn compile_globset_with_policy(
|
||||
// - "example.com": match the exact host
|
||||
// - "*.example.com": match any subdomain (not the apex)
|
||||
// - "**.example.com": match the apex and any subdomain
|
||||
// - "api?.example.com": match exactly one character after "api"
|
||||
// - "*": match every host when explicitly enabled for allowlist compilation
|
||||
for candidate in expand_domain_pattern(&pattern) {
|
||||
if !seen.insert(candidate.clone()) {
|
||||
@@ -411,6 +415,46 @@ mod tests {
|
||||
assert_eq!(false, set.is_match("foo.region1.v2.argotunnel.com"));
|
||||
}
|
||||
|
||||
// Keep this table one-for-one with the browser network-policy matchers'
|
||||
// question-mark contract cases so grammar changes are checked on both sides.
|
||||
#[test]
|
||||
fn compile_globset_supports_question_mark_wildcards() -> Result<()> {
|
||||
for (pattern, host, expected) in [
|
||||
("api?.example.com", "api1.example.com", true),
|
||||
("api?.example.com", "api.example.com", false),
|
||||
("api?.example.com", "api12.example.com", false),
|
||||
("api??.example.com", "api12.example.com", true),
|
||||
("api??.example.com", "api1.example.com", false),
|
||||
("api*?.example.com", "api.example.com", false),
|
||||
("api*?.example.com", "api1.example.com", true),
|
||||
("api*?.example.com", "api123.example.com", true),
|
||||
("api?example.com", "api.example.com", true),
|
||||
("*.api?.example.com", "api1.example.com", false),
|
||||
("*.api?.example.com", "www.api1.example.com", true),
|
||||
("*.api?.example.com", "nested.www.api1.example.com", true),
|
||||
("*.api?.example.com", "www.api12.example.com", false),
|
||||
("**.api?.example.com", "api1.example.com", true),
|
||||
("**.api?.example.com", "www.api1.example.com", true),
|
||||
("**.api?.example.com", "nested.www.api1.example.com", true),
|
||||
("**.api?.example.com", "api12.example.com", false),
|
||||
("**.api?.example.com", "www.api12.example.com", false),
|
||||
(" API?.EXAMPLE.COM. ", "API1.EXAMPLE.COM.", true),
|
||||
] {
|
||||
let patterns = [pattern.to_string()];
|
||||
for set in [
|
||||
compile_allowlist_globset(&patterns)?,
|
||||
compile_denylist_globset(&patterns)?,
|
||||
] {
|
||||
assert_eq!(
|
||||
set.is_match(normalize_host(host)),
|
||||
expected,
|
||||
"pattern {pattern}, host {host}"
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_globset_normalizes_apex_and_subdomains() {
|
||||
let set = compile_denylist_globset(&["**.Example.COM.".to_string()]).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user