Skip to content

fix(security): enforce TLS SNI allowlist - #8878

Merged
lpcox merged 1 commit into
mainfrom
enforce-tls-sni-allowlist
Sep 22, 2026
Merged

lpcox merged 1 commit into
mainfrom
enforce-tls-sni-allowlist

Conversation

@lpcox

@lpcox lpcox commented Sep 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • inspect the TLS ClientHello after an allowed CONNECT request and require the client-requested SNI to match the HTTPS allowlist
  • splice allowlisted TLS connections without decrypting application traffic, and terminate missing, blocked, or non-allowlisted SNI
  • preserve trusted AWF sidecar behavior and explicitly allowlisted IP destinations
  • generate an ephemeral listener certificate from the compose wrapper so the fix works with already-published Squid images
  • expose SNI enforcement in the policy manifest and document the corrected egress security model

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:

  1. authorize the CONNECT target through the existing HTTP access rules
  2. peek at the ClientHello without decrypting application data
  3. terminate blocked, missing, or non-allowlisted SNI
  4. splice allowed traffic unchanged

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 skipped
  • npm run type-check -- --pretty false
  • npm run lint -- --quiet
  • npx markdownlint-cli2 docs/egress-filtering.md docs/ssl-bump.md --no-globs
  • live Docker probe: normal https://nodejs.org succeeded; CONNECT to nodejs.org with TLS SNI example.com was terminated

A 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.sslBump content-inspection mode remains unchanged.

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>
Copilot AI balanced review requested due to automatic review settings September 22, 2026 11:36
@github-actions

Copy link
Copy Markdown
Contributor

Documentation Preview

Documentation has been built for this PR.

Download preview artifact

To view locally:

  1. Download the docs-preview-pr-8878 artifact from the workflow run
  2. Unzip and open index.html in your browser

Built from commit 71e4e24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Smoke Cloud Hypervisor completed. Cloud Hypervisor + Copilot passed.

Warning

Firewall blocked 2 domains

The following domains were blocked by the firewall during workflow execution:

  • example.com
  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "example.com"
    - "github.com"

See Network Configuration for more information.

Cloud Hypervisor + Copilot smoke test by Smoke Cloud Hypervisor

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Build Test Suite completed successfully!

Warning

Firewall blocked 8 domains

The following domains were blocked by the firewall during workflow execution:

  • api.nuget.org
  • bun.sh
  • dc.services.visualstudio.com
  • deno.land
  • dl.deno.land
  • github.com
  • releaseassets.githubusercontent.com
  • repo.maven.apache.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

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.

Generated by Build Test Suite for #8878

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Smoke Gemini reports failed. Facets need polishing...

💎 Faceted by Smoke Gemini

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

🔌 Smoke Services — All services reachable! ✅

🔌 Service connectivity validated by Smoke Services

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

📡 Smoke OTel Tracing completed. All tracing scenarios validated. ✅

Warning

Firewall blocked 2 domains

The following domains were blocked by the firewall during workflow execution:

  • o205451.ingest.us.sentry.io
  • registry.npmjs.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "o205451.ingest.us.sentry.io"
    - "registry.npmjs.org"

See Network Configuration for more information.

📡 OTel tracing validated by Smoke OTel Tracing

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Security Guard has started processing this pull request

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Smoke Copilot BYOK completed. Copilot BYOK mode operational. 🔓

🔑 BYOK report filed by Smoke Copilot BYOK

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟

Warning

Firewall blocked 12 domains

The following domains were blocked by the firewall during workflow execution:

  • 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

[!TIP]
api.github.com is blocked because GitHub API access uses the built-in GitHub tools by default. Instead of adding api.github.com to network.allowed, use tools.github.mode: gh-proxy for direct pre-authenticated GitHub CLI access without requiring network access to api.github.com:

tools:
  github:
    mode: gh-proxy

See GitHub Tools for more information on gh-proxy mode.

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

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.

🔮 The oracle has spoken through Smoke Codex

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Smoke Claude passed

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • api.anthropic.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "api.anthropic.com"

See Network Configuration for more information.

Generated by Smoke Claude for #8878

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Chroot tests passed! Smoke Chroot - All security and functionality tests succeeded.

Tested by Smoke Chroot

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Smoke Copilot BYOK AOAI (Entra) reports failed. AOAI BYOK (Entra) mode investigation needed...

🪪 BYOK (AOAI Entra) report filed by Smoke Copilot BYOK AOAI (Entra)

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Smoke Copilot BYOK AOAI (api-key) reports failed. AOAI BYOK (api-key) mode investigation needed...

🔑 BYOK (AOAI api-key) report filed by Smoke Copilot BYOK AOAI (api-key)

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

📰 BREAKING: Report filed by Smoke Copilot

@github-actions

github-actions Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

🛡️ Smoke Copilot Network Isolation confirmed the egress allowlist is enforced. ✅

Warning

Firewall blocked 2 domains

The following domains were blocked by the firewall during workflow execution:

  • api.github.com
  • example.com

[!TIP]
api.github.com is blocked because GitHub API access uses the built-in GitHub tools by default. Instead of adding api.github.com to network.allowed, use tools.github.mode: gh-proxy for direct pre-authenticated GitHub CLI access without requiring network access to api.github.com:

tools:
  github:
    mode: gh-proxy

See GitHub Tools for more information on gh-proxy mode.

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "api.github.com"
    - "example.com"

See Network Configuration for more information.

🛡️ Egress verdict from Smoke Copilot Network Isolation

@github-actions

Copy link
Copy Markdown
Contributor

Smoke Test: Cloud Hypervisor + Copilot

Check Result
1. List merged PRs (github MCP) PASS
2. curl https://github.com → 200 PASS
3. Write/read temp file PASS
4. curl (example.com/redacted) → blocked (000) PASS

Overall: PASS

Warning

Firewall blocked 2 domains

The following domains were blocked by the firewall during workflow execution:

  • example.com
  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "example.com"
    - "github.com"

See Network Configuration for more information.

Cloud Hypervisor + Copilot smoke test by Smoke Cloud Hypervisor
Add label ready-for-aw to run again

@github-actions

Copy link
Copy Markdown
Contributor

Smoke Test: Claude Engine Validation

Check Status
API ✅ PASS
GitHub CLI ✅ PASS
File ✅ PASS

Overall result: PASS

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • api.anthropic.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "api.anthropic.com"

See Network Configuration for more information.

Generated by Smoke Claude for #8878 · claude · haiku45 · 55.8 AIC · ⊞ 4.7K ·
Add label ready-for-aw to run again

@github-actions

Copy link
Copy Markdown
Contributor

Smoke Test: Copilot BYOK (Direct) Mode ✅

Test Results:

Status: PASS

Running in direct BYOK mode with api-proxy sidecar routing to api.githubcopilot.com.

🔑 BYOK report filed by Smoke Copilot BYOK
Add label ready-for-aw to run again

@lpcox
lpcox deployed to aoai-model September 22, 2026 14:23 — with GitHub Actions Active
@github-actions

Copy link
Copy Markdown
Contributor

📡 OTel Tracing Smoke Test Results

# Scenario Result
1 Module Loading (otel.js) ✅ Loaded successfully, isEnabled: true, exports: startRequestSpan, setTokenAttributes, setBudgetAttributes, endSpan, endSpanError, shutdown, isEnabled, ...
2 Test Suite (*otel* Jest) ✅ 3 suites / 68 tests passed, 0 failed
3 Env Var Forwarding GITHUB_AW_OTEL_TRACE_ID/GITHUB_AW_OTEL_PARENT_SPAN_ID found in env-passthrough.ts; GH_AW_OTLP_ENDPOINTS, OTEL_EXPORTER_OTLP_ENDPOINT, and trace context found in api-proxy-env-config.ts
4 Token Tracker Integration onUsage callback present in token-tracker-http.js
5 OTEL Diagnostics ⚠️ No otel.jsonl span file emitted this run (expected — no live OTLP export exercised in this smoke pass); token-usage.jsonl/token-tracker-audit.jsonl present

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 domains

The following domains were blocked by the firewall during workflow execution:

  • o205451.ingest.us.sentry.io
  • registry.npmjs.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "o205451.ingest.us.sentry.io"
    - "registry.npmjs.org"

See Network Configuration for more information.

📡 OTel tracing validated by Smoke OTel Tracing
Add label ready-for-aw to run again

@github-actions

Copy link
Copy Markdown
Contributor

Smoke test: services connectivity — PASS ✅

  • Redis PING: ✅ PONG
  • PostgreSQL pg_isready: ✅ accepting connections
  • PostgreSQL SELECT 1: ✅ 1

Overall: PASS

🔌 Service connectivity validated by Smoke Services
Add label ready-for-aw to run again

@github-actions

Copy link
Copy Markdown
Contributor

Smoke Test: Copilot Engine — PASS ✅

Overall: PASS

cc @lpcox

📰 BREAKING: Report filed by Smoke Copilot
Add label ready-for-aw to run again

@github-actions

Copy link
Copy Markdown
Contributor

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.14 Python 3.12.14 ✅ YES
Node.js v24.21.0 v22.23.2 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Overall: FAILED — Node.js version differs between host (v24.21.0) and chroot (v22.23.2). Python and Go match. smoke-chroot label not applied since not all tests passed.

Tested by Smoke Chroot
Add label ready-for-aw to run again

@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Build Test Suite Results

Ecosystem Project Build/Install Tests Status
Bun elysia 1/1 passed ✅ PASS
Bun hono 1/1 passed ✅ PASS
C++ fmt N/A ✅ PASS
C++ json N/A ✅ PASS
Deno oak N/A 1/1 passed ✅ PASS
Deno std N/A 1/1 passed ✅ PASS
.NET hello-world N/A (run OK) ✅ PASS
.NET json-parse N/A (run OK) ✅ PASS
Go color ok ✅ PASS
Go env ok ✅ PASS
Go uuid ok ✅ PASS
Java gson 1/1 passed ✅ PASS
Java caffeine 1/1 passed ✅ PASS
Node.js clsx passed ✅ PASS
Node.js execa passed ✅ PASS
Node.js p-limit passed ✅ PASS
Rust fd 1/1 passed ✅ PASS
Rust zoxide 1/1 passed ✅ PASS

Overall: 8/8 ecosystems passed — PASS

Note: The default Maven local repository at ~/.m2/repository could not be created because ~/.m2 was pre-existing and root-owned (permission denied), unrelated to firewall egress control. Worked around by passing -Dmaven.repo.local=/tmp/gh-aw/agent/m2repo to mvn compile/mvn test for both Java projects; all Squid proxy settings in ~/.m2/settings.xml applied correctly and all network access, compiles, and tests succeeded.

Warning

Firewall blocked 8 domains

The following domains were blocked by the firewall during workflow execution:

  • api.nuget.org
  • bun.sh
  • dc.services.visualstudio.com
  • deno.land
  • dl.deno.land
  • github.com
  • releaseassets.githubusercontent.com
  • repo.maven.apache.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

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.

Generated by Build Test Suite for #8878 · copilot · auto · 44.1 AIC · ⊞ 11.8K ·
Add label ready-for-aw to run again

@github-actions github-actions Bot added the smoke-copilot-network-isolation Copilot network-isolation egress smoke test label Sep 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

EGRESS_RESULT allow=pass deny=pass

✅ Allowed domain (github.com) reachable — allowed=200
✅ Blocked domain (example.com) denied — SSL/connection failure, denied=000

Overall: PASS

@lpcox

Warning

Firewall blocked 2 domains

The following domains were blocked by the firewall during workflow execution:

  • api.github.com
  • example.com

[!TIP]
api.github.com is blocked because GitHub API access uses the built-in GitHub tools by default. Instead of adding api.github.com to network.allowed, use tools.github.mode: gh-proxy for direct pre-authenticated GitHub CLI access without requiring network access to api.github.com:

tools:
  github:
    mode: gh-proxy

See GitHub Tools for more information on gh-proxy mode.

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "api.github.com"
    - "example.com"

See Network Configuration for more information.

🛡️ Egress verdict from Smoke Copilot Network Isolation
Add label ready-for-aw to run again

@github-actions

Copy link
Copy Markdown
Contributor
  • feat(nvx): add internal Phase 3c lifecycle manager
  • Correlate upstream 400s with request tool surface and negotiate MCP protocol version
  • Merged PR review: ✅
  • PR detail lookup: ✅
  • Playwright title check: ✅
  • File write/read: ✅
  • Latest discussion/comment: ✅
  • AWF build: ✅
  • Overall: PASS

Warning

Firewall blocked 12 domains

The following domains were blocked by the firewall during workflow execution:

  • 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

[!TIP]
api.github.com is blocked because GitHub API access uses the built-in GitHub tools by default. Instead of adding api.github.com to network.allowed, use tools.github.mode: gh-proxy for direct pre-authenticated GitHub CLI access without requiring network access to api.github.com:

tools:
  github:
    mode: gh-proxy

See GitHub Tools for more information on gh-proxy mode.

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

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.

🔮 The oracle has spoken through Smoke Codex
Add label ready-for-aw to run again

@lpcox
lpcox merged commit 7c56dd9 into main Sep 22, 2026
149 of 154 checks passed
@lpcox
lpcox deleted the enforce-tls-sni-allowlist branch September 22, 2026 14:50

This branch was successfully deployed

1 active deployment
aoai-model 1b3a2a9a Deployed Sep 22, 2026 by lpcox via conclusion #1731
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants