fix(security): enforce TLS SNI allowlist - #8878
Conversation
Validate TLS ClientHello SNI before splicing HTTPS connections. Preserve trusted sidecar and explicit IP behavior. Add regression coverage and document the default peek-and-splice enforcement model. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Documentation PreviewDocumentation has been built for this PR. To view locally:
Built from commit 71e4e24 |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The security fix is consistently integrated across configuration, startup, policy reporting, tests, and documentation with no unresolved defects found.
Review effort: Balanced
Findings: None
What changed in this PR
This PR hardens HTTPS egress filtering by validating TLS ClientHello SNI after CONNECT authorization, preventing domain-fronting bypasses while preserving trusted sidecar and allowlisted-IP behavior.
Changes:
- Adds default Squid peek-and-splice SNI enforcement and ephemeral certificate generation.
- Exposes enforcement in policy manifests and adds unit/integration coverage.
- Updates egress and SSL Bump security documentation.
| File | Description |
|---|---|
tests/integration/network-security.test.ts |
Adds a raw CONNECT/SNI domain-fronting regression test. |
src/types/policy.ts |
Adds the SNI guard manifest capability. |
src/squid/ssl-bump.ts |
Generates guard-only peek/splice/terminate rules. |
src/squid/ssl-bump.test.ts |
Tests SNI ACL and rule generation. |
src/squid/policy-manifest.ts |
Reports SNI enforcement as enabled. |
src/squid/config-sections.ts |
Enables the guard by default and supplies policy inputs. |
src/squid/config-sections.test.ts |
Tests default listeners, allow/block precedence, sidecars, and IPs. |
src/squid/config-generator.ts |
Propagates blocked domains into section generation. |
src/squid-config-ssl-bump.test.ts |
Updates generated-config expectations. |
src/services/squid-service.ts |
Generates the listener’s ephemeral certificate at startup. |
src/services/squid-service.test.ts |
Verifies certificate bootstrap command generation. |
src/logs/audit-enricher.test-utils.ts |
Updates manifest test fixtures. |
docs/ssl-bump.md |
Documents default SNI validation and splicing. |
docs/egress-filtering.md |
Documents the corrected domain-fronting threat model. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Smoke Cloud Hypervisor completed. Cloud Hypervisor + Copilot passed. Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "example.com"
- "github.com"See Network Configuration for more information.
|
|
✅ Build Test Suite completed successfully! Warning Firewall blocked 8 domainsThe following domains were blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "api.nuget.org"
- "bun.sh"
- "dc.services.visualstudio.com"
- "deno.land"
- "dl.deno.land"
- "github.com"
- "releaseassets.githubusercontent.com"
- "repo.maven.apache.org"See Network Configuration for more information.
|
|
❌ Smoke Gemini reports failed. Facets need polishing...
|
|
🔌 Smoke Services — All services reachable! ✅
|
|
📡 Smoke OTel Tracing completed. All tracing scenarios validated. ✅ Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "o205451.ingest.us.sentry.io"
- "registry.npmjs.org"See Network Configuration for more information.
|
|
🚀 Security Guard has started processing this pull request |
|
✅ Smoke Copilot BYOK completed. Copilot BYOK mode operational. 🔓
|
|
✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟 Warning Firewall blocked 12 domainsThe following domains were blocked by the firewall during workflow execution:
[!TIP] tools:
github:
mode: gh-proxySee GitHub Tools for more information on To allow these domains, add them to the network:
allowed:
- defaults
- "ab.chatgpt.com"
- "accounts.google.com"
- "api.github.com"
- "clients2.google.com"
- "collector.github.com"
- "contentautofill.googleapis.com"
- "github.com"
- "github.githubassets.com"
- "msfeed25.pkgs.visualstudio.com"
- "update.googleapis.com"
- "www.google.com"
- "www.gstatic.com"See Network Configuration for more information.
|
|
✅ Smoke Claude passed Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "api.anthropic.com"See Network Configuration for more information.
|
|
Chroot tests passed! Smoke Chroot - All security and functionality tests succeeded.
|
|
❌ Smoke Copilot BYOK AOAI (Entra) reports failed. AOAI BYOK (Entra) mode investigation needed...
|
|
❌ Smoke Copilot BYOK AOAI (api-key) reports failed. AOAI BYOK (api-key) mode investigation needed...
|
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤
|
|
🛡️ Smoke Copilot Network Isolation confirmed the egress allowlist is enforced. ✅ Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
[!TIP] tools:
github:
mode: gh-proxySee GitHub Tools for more information on To allow these domains, add them to the network:
allowed:
- defaults
- "api.github.com"
- "example.com"See Network Configuration for more information.
|
Smoke Test: Cloud Hypervisor + Copilot
Overall: PASS ✅ Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "example.com"
- "github.com"See Network Configuration for more information.
|
Smoke Test: Claude Engine Validation
Overall result: PASS Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "api.anthropic.com"See Network Configuration for more information.
|
Smoke Test: Copilot BYOK (Direct) Mode ✅Test Results:
Status: PASS Running in direct BYOK mode with api-proxy sidecar routing to api.githubcopilot.com.
|
📡 OTel Tracing Smoke Test Results
Summary: All functional/unit checks (1–4) pass cleanly. Scenario 5 shows no spans exported in this run, which is expected since no proxied LLM traffic occurred during validation — not a regression. Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "o205451.ingest.us.sentry.io"
- "registry.npmjs.org"See Network Configuration for more information.
|
|
Smoke test: services connectivity — PASS ✅
Overall: PASS
|
|
Smoke Test: Copilot Engine — PASS ✅
Overall: PASS cc @lpcox
|
Chroot Version Comparison Results
Overall: FAILED — Node.js version differs between host (v24.21.0) and chroot (v22.23.2). Python and Go match.
|
🏗️ Build Test Suite Results
Overall: 8/8 ecosystems passed — PASS Note: The default Maven local repository at Warning Firewall blocked 8 domainsThe following domains were blocked by the firewall during workflow execution:
To allow these domains, add them to the network:
allowed:
- defaults
- "api.nuget.org"
- "bun.sh"
- "dc.services.visualstudio.com"
- "deno.land"
- "dl.deno.land"
- "github.com"
- "releaseassets.githubusercontent.com"
- "repo.maven.apache.org"See Network Configuration for more information.
|
|
EGRESS_RESULT allow=pass deny=pass ✅ Allowed domain (github.com) reachable — Overall: PASS Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
[!TIP] tools:
github:
mode: gh-proxySee GitHub Tools for more information on To allow these domains, add them to the network:
allowed:
- defaults
- "api.github.com"
- "example.com"See Network Configuration for more information.
|
Warning Firewall blocked 12 domainsThe following domains were blocked by the firewall during workflow execution:
[!TIP] tools:
github:
mode: gh-proxySee GitHub Tools for more information on To allow these domains, add them to the network:
allowed:
- defaults
- "ab.chatgpt.com"
- "accounts.google.com"
- "api.github.com"
- "clients2.google.com"
- "collector.github.com"
- "contentautofill.googleapis.com"
- "github.com"
- "github.githubassets.com"
- "msfeed25.pkgs.visualstudio.com"
- "update.googleapis.com"
- "www.google.com"
- "www.gstatic.com"See Network Configuration for more information.
|
Summary
Security context
This fixes the domain-fronting bypass reported in github/gh-aw#62547. Previously, Squid authorized an HTTPS tunnel solely from the plaintext CONNECT target. On shared CDN infrastructure, a client could CONNECT to an allowlisted hostname and then send a different TLS SNI inside the tunnel.
The default listener now uses Squid peek-and-splice:
Blocked-domain rules take precedence over parent-domain allow rules. Trusted API/CLI proxy sources and explicitly allowlisted IP destinations retain their existing behavior.
Validation
npm test -- --runInBand— 379 suites, 6,088 passed, 4 skippednpm run type-check -- --pretty falsenpm run lint -- --quietnpx markdownlint-cli2 docs/egress-filtering.md docs/ssl-bump.md --no-globshttps://nodejs.orgsucceeded; CONNECT tonodejs.orgwith TLS SNIexample.comwas terminatedA real integration regression reproducing the raw CONNECT/SNI attack is included. The local integration harness itself requires interactive sudo on this machine, so that test is intended to run in CI.
Compatibility
TLS clients connecting to normal hostname destinations must send SNI. This is intentional fail-closed behavior. Full
security.sslBumpcontent-inspection mode remains unchanged.