Skip to content

Refactor squid config generation into focused modules#3028

Merged
lpcox merged 5 commits into
mainfrom
copilot/refactor-squid-config-module
May 12, 2026
Merged

Refactor squid config generation into focused modules#3028
lpcox merged 5 commits into
mainfrom
copilot/refactor-squid-config-module

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 12, 2026

✨ Enhancement

src/squid-config.ts had grown into a single 945-line module mixing domain ACL parsing, SSL bump generation, upstream proxy chaining, and policy-manifest construction. This refactor decomposes those concerns into focused modules while preserving the existing generateSquidConfig / generatePolicyManifest public surface.

What does this improve?

  • Reduces review complexity in a security-critical path by isolating config-generation concerns.
  • Makes domain ACL, SSL bump, upstream proxy, and manifest logic independently maintainable.

Why is this valuable?

  • Smaller, concern-specific modules make policy behavior easier to reason about and safer to modify.
  • Keeps callers stable (src/container-lifecycle.ts continues importing from src/squid-config.ts).

Implementation approach:

  • Module extraction
    • src/squid/domain-acl.ts: extracted domain parsing/grouping and Squid interpolation safety helpers.
    • src/squid/ssl-bump.ts: extracted SSL bump section assembly.
    • src/squid/upstream-proxy.ts: extracted upstream proxy cache_peer / bypass section generation.
    • src/squid/policy-manifest.ts: extracted policy-manifest generation and DANGEROUS_PORTS.
  • Facade retention
    • src/squid-config.ts now focuses on generateSquidConfig orchestration and imports extracted helpers.
    • generatePolicyManifest remains available via src/squid-config.ts through re-export for compatibility.
// src/squid-config.ts (facade)
import { DANGEROUS_PORTS } from './squid/policy-manifest';
import { parseDomainConfig, formatDomainForSquid } from './squid/domain-acl';
import { generateSslBumpSection } from './squid/ssl-bump';
import { generateUpstreamProxySection } from './squid/upstream-proxy';

export { generatePolicyManifest } from './squid/policy-manifest';

Copilot AI changed the title [WIP] Refactor squid-config.ts into focused config-generation modules Refactor squid config generation into focused modules May 12, 2026
Copilot finished work on behalf of lpcox May 12, 2026 16:33
Copilot AI requested a review from lpcox May 12, 2026 16:33
@lpcox lpcox marked this pull request as ready for review May 12, 2026 16:48
@lpcox lpcox requested a review from Mossaka as a code owner May 12, 2026 16:48
Copilot AI review requested due to automatic review settings May 12, 2026 16:48
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 12, 2026

⚠️ Coverage Regression Detected

This PR decreases test coverage. Please add tests to maintain coverage levels.

Overall Coverage

Metric Base PR Delta
Lines 87.63% 89.86% 📈 +2.23%
Statements 87.60% 89.77% 📈 +2.17%
Functions 92.16% 92.02% 📉 -0.14%
Branches 79.65% 81.76% 📈 +2.11%
📁 Per-file Coverage Changes (4 files)
File Lines (Before → After) Statements (Before → After)
src/commands/main-action.ts 5.7% → 7.2% (+1.49%) 5.7% → 7.1% (+1.45%)
src/host-iptables.ts 97.7% → 100.0% (+2.34%) 97.3% → 100.0% (+2.70%)
src/squid-config.ts 97.1% → 100.0% (+2.90%) 97.2% → 100.0% (+2.85%)
src/container-lifecycle.ts 87.4% → 93.9% (+6.57%) 87.7% → 94.2% (+6.50%)
✨ New Files (12 files)
  • src/config-writer.ts: 81.0% lines
  • src/host-iptables-cleanup.ts: 100.0% lines
  • src/host-iptables-network.ts: 100.0% lines
  • src/host-iptables-rules.ts: 97.3% lines
  • src/host-iptables-shared.ts: 96.5% lines
  • src/commands/network-setup.ts: 100.0% lines
  • src/commands/preflight.ts: 100.0% lines
  • src/commands/signal-handler.ts: 89.5% lines
  • src/squid/domain-acl.ts: 100.0% lines
  • src/squid/policy-manifest.ts: 87.0% lines
  • src/squid/ssl-bump.ts: 93.8% lines
  • src/squid/upstream-proxy.ts: 100.0% lines

Coverage comparison generated by scripts/ci/compare-coverage.ts

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors Squid config generation by extracting domain ACL parsing, SSL bump section generation, upstream-proxy chaining, and policy-manifest generation into focused modules, while keeping generateSquidConfig/generatePolicyManifest available via the src/squid-config.ts facade.

Changes:

  • Extracted domain parsing/formatting + Squid interpolation safety helpers into src/squid/domain-acl.ts.
  • Extracted SSL bump config assembly into src/squid/ssl-bump.ts and upstream proxy chaining into src/squid/upstream-proxy.ts.
  • Moved policy manifest generation (and DANGEROUS_PORTS) into src/squid/policy-manifest.ts, re-exported from src/squid-config.ts.
Show a summary per file
File Description
src/squid-config.ts Converts to a facade/orchestrator importing extracted helpers and re-exporting generatePolicyManifest.
src/squid/domain-acl.ts New shared domain parsing/grouping + Squid-safe interpolation utilities.
src/squid/ssl-bump.ts New module generating the SSL bump section (including optional URL-pattern ACL/rules).
src/squid/upstream-proxy.ts New module generating cache_peer + bypass rules for upstream proxy chaining.
src/squid/policy-manifest.ts New module generating the structured policy manifest and exporting DANGEROUS_PORTS.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 5/5 changed files
  • Comments generated: 3

Comment thread src/squid/ssl-bump.ts Outdated
Comment on lines +42 to +60
// Build access rules for URL patterns
// When URL patterns are specified, we:
// 1. Allow requests matching the URL patterns
// 2. Deny all other requests to allowed_domains (they didn't match URL patterns)
const urlAccessLines = urlPatterns
.map((_, i) => `http_access allow allowed_url_${i}`)
.join('\n');

// Deny requests to allowed domains that don't match URL patterns
// This ensures URL-level filtering is enforced
// IMPORTANT: Use !CONNECT to only deny actual HTTP requests after bump,
// not the CONNECT request itself (which must be allowed for SSL bump to work)
const denyNonMatching = hasPlainDomains
? 'http_access deny !CONNECT allowed_domains'
: hasPatterns
? 'http_access deny !CONNECT allowed_domains_regex'
: '';

urlAccessRules = `\n# Allow HTTPS requests matching URL patterns\n${urlAccessLines}\n\n# Deny requests that don't match URL patterns\n${denyNonMatching}\n`;
Comment thread src/squid/domain-acl.ts
Comment on lines +27 to +37
/**
* Defense-in-depth: assert a domain/regex/URL-pattern string is safe for Squid config interpolation.
* Rejects whitespace, null bytes, quotes, semicolons, backticks, hash characters, and backslashes —
* all of which can inject directives, tokens, or comments into Squid config.
*/
export function assertSafeForSquidConfig(value: string): string {
if (SQUID_DANGEROUS_CHARS.test(value)) {
throw new Error(
`SECURITY: Domain or pattern contains characters unsafe for Squid config and cannot be ` +
`interpolated into squid.conf: ${JSON.stringify(value)}`
);
Comment on lines +10 to +31
export function generateUpstreamProxySection(upstream: UpstreamProxyConfig): string {
const lines: string[] = [
'# Upstream corporate proxy — route outbound traffic through parent proxy',
'# Required for self-hosted runners where direct egress is blocked',
`cache_peer ${upstream.host} parent ${upstream.port} 0 no-query default`,
];

// Generate always_direct ACL for no_proxy bypass domains
if (upstream.noProxy && upstream.noProxy.length > 0) {
lines.push('');
lines.push('# Bypass upstream proxy for these domains (from host no_proxy)');
for (const domain of upstream.noProxy) {
// All entries are treated as suffix matches (domain + subdomains),
// matching standard no_proxy semantics:
// .corp.com → *.corp.com
// internal.corp.com → internal.corp.com AND *.internal.corp.com
const squidDomain = domain.startsWith('.') ? domain : `.${domain}`;
lines.push(`acl upstream_bypass dstdomain ${squidDomain}`);
// For non-dot entries, also add the exact domain for Squid dstdomain matching
if (!domain.startsWith('.')) {
lines.push(`acl upstream_bypass dstdomain ${domain}`);
}
@lpcox
Copy link
Copy Markdown
Collaborator

lpcox commented May 12, 2026

@copilot address the review feedback

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 12, 2026

@copilot address the review feedback

Addressed in commit 821cfac.

  • Moved URL-pattern http_access rules out of generateSslBumpSection and now emit them in generateSquidConfig after Safe_ports deny rules.
  • Updated assertSafeForSquidConfig JSDoc to match actual validator behavior (no backslash rejection claim).
  • Added defense-in-depth sanitization in generateUpstreamProxySection for upstream.host and each upstream.noProxy entry.
  • Added/updated tests for URL-rule ordering and unsafe upstream values.

Copilot finished work on behalf of lpcox May 12, 2026 17:14
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@lpcox
Copy link
Copy Markdown
Collaborator

lpcox commented May 12, 2026

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 12, 2026

@copilot fix this failing ci check https://github.com/github/gh-aw-firewall/actions/runs/25750190383/job/75625642186?pr=3028

Fixed in e09c8ce (with the core CI fix in 82ee56b). I updated the failing integration tests to use pre-built local images via --skip-pull instead of per-test --build-local rebuilds, and re-ran the affected integration tests (skip-pull and no-docker) successfully.

Copilot finished work on behalf of lpcox May 12, 2026 18:36
@github-actions
Copy link
Copy Markdown
Contributor

🔬 Smoke Test Results

Test Result
GitHub MCP connectivity ❌ 401 Bad credentials
GitHub.com HTTP connectivity ⚠️ Template vars not expanded
File write/read ⚠️ Template vars not expanded

Overall: FAIL — Workflow template variables (${{ steps.smoke-data.outputs.* }}) were not substituted at runtime, and GitHub MCP returned 401 errors. The smoke test infrastructure needs review.

📰 BREAKING: Report filed by Smoke Copilot

@github-actions
Copy link
Copy Markdown
Contributor

Smoke Test: Copilot BYOK (Offline) Mode

Test Result
GitHub MCP connectivity ❌ 401 Bad credentials
GitHub.com HTTP ❌ Pre-step data not resolved (template vars unexpanded)
File write/read ❌ Pre-step data not resolved
BYOK inference (api-proxy → api.githubcopilot.com)

Running in BYOK offline mode (COPILOT_OFFLINE=true) via api-proxy → api.githubcopilot.com.

Overall: FAIL — pre-step smoke data was not injected into the prompt (template variables unresolved) and GitHub MCP returned 401.

🔑 BYOK report filed by Smoke Copilot BYOK

@github-actions
Copy link
Copy Markdown
Contributor

Smoke Codex: FAIL
PRs: ✅ #3030 Refactor host iptables into focused modules with a stable public facade; #3029 refactor: split main-action.ts into preflight, network-setup, and signal-handler modules
safeinputs-gh: ❌ missing tool
Playwright: ✅ title contains GitHub
Tavily: ❌ no exposed search tool
File/bash: ✅ readback ok
Discussion: ❌ query tool missing; oracle comment posted to #3042
Build: ✅ npm ci && npm run build
Overall status: FAIL

Warning

Firewall blocked 1 domain

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

  • registry.npmjs.org

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

network:
  allowed:
    - defaults
    - "registry.npmjs.org"

See Network Configuration for more information.

🔮 The oracle has spoken through Smoke Codex

@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 ✅ PASS
.NET json-parse N/A ✅ PASS
Go color 1/1 passed ✅ PASS
Go env 1/1 passed ✅ PASS
Go uuid 1/1 passed ✅ 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

Generated by Build Test Suite for issue #3028 · ● 528.7K ·

@github-actions
Copy link
Copy Markdown
Contributor

Chroot Smoke Test Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.13 Python 3.12.3
Node.js v24.14.1 v20.20.2
Go go1.22.12 go1.22.12

Overall: ❌ Not all tests passed — Python and Node.js versions differ between host and chroot.

Tested by Smoke Chroot

@github-actions
Copy link
Copy Markdown
Contributor

Smoke Test Results

  • Redis PING: ❌ (timeout — no response on host.docker.internal:6379)
  • PostgreSQL pg_isready: ❌ (host.docker.internal:5432 - no response)
  • PostgreSQL SELECT 1: ❌ (skipped — pg unreachable)

Overall: FAIL — service containers are not reachable from this environment.

🔌 Service connectivity validated by Smoke Services

@lpcox lpcox merged commit 549ce80 into main May 12, 2026
60 of 66 checks passed
@lpcox lpcox deleted the copilot/refactor-squid-config-module branch May 12, 2026 18:51
@github-actions
Copy link
Copy Markdown
Contributor

Smoke Test Results

✅ GitHub commits verification
✅ Playwright navigation test
✅ File creation test
✅ Bash verification test

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude

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.

[Refactoring] Split squid-config.ts into focused config-generation modules

3 participants