Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 19, 2025

  • Add SSL Bump feature for HTTPS content inspection
    • Create src/ssl-bump.ts - CA generation utilities
    • Update src/types.ts - Add SSL Bump configuration types
    • Update src/squid-config.ts - Add SSL Bump configuration
    • Update src/docker-manager.ts - Handle CA certificate mounting
    • Update src/cli.ts - Add CLI flags --ssl-bump and --allow-urls
    • Update containers/squid/Dockerfile - Add OpenSSL tools
    • Update containers/agent/entrypoint.sh - Add CA certificate injection
    • Add tests for SSL Bump functionality
  • Fix SSL Bump issues (from PR review)
    • Call parseUrlPatterns() to transform user URLs to regex patterns
    • Fix SSL database initialization in Squid entrypoint
    • Fix port configuration (use http_port 3128 ssl-bump for explicit proxy)
    • Increase SSL certificate cache size from 4MB to 16MB
  • Update documentation with power-user warnings
  • Run code review
  • Run CodeQL security check
Original prompt

This section details on the original issue you should resolve

<issue_title>[Security] No TLS/HTTPS content inspection - only SNI visible</issue_title>
<issue_description>## Priority
P0 - Critical

Summary

AWF only inspects SNI (Server Name Indication) in the TLS ClientHello. It cannot see or filter based on URL paths, query parameters, or request methods for HTTPS traffic.

Current Behavior

When a client makes an HTTPS request, Squid only sees the CONNECT method with the domain:

CONNECT github.com:443 HTTP/1.1

Squid cannot distinguish between:

  • https://github.com/safe-org/repo
  • https://github.com/malicious-org/repo

Both requests are allowed if github.com is whitelisted.

Security Impact

  • Data exfiltration: Malicious code can exfiltrate data to any path on allowed domains
  • Access control bypass: Cannot restrict to specific repositories, API endpoints, or paths
  • Audit limitations: Logs only show domain, not actual resource accessed

Code Locations

  • src/squid-config.ts:108-120 - ACL rules only match dstdomain
  • Squid config uses http_access allow based on domain only

Proposed Solution

Enable Squid SSL Bump

  1. Generate per-session CA certificate (for security):
// Generate self-signed CA valid for 1 day only
openssl req -new -newkey rsa:2048 -days 1 -nodes -x509 \
  -subj "/CN=AWF Session CA" \
  -keyout ${workDir}/ca-key.pem -out ${workDir}/ca-cert.pem
  1. Configure Squid SSL Bump (src/squid-config.ts):
http_port 3128 ssl-bump \
  cert=/etc/squid/ca-cert.pem \
  key=/etc/squid/ca-key.pem \
  generate-host-certificates=on \
  dynamic_cert_mem_cache_size=4MB

acl step1 at_step SslBump1
ssl_bump peek step1
ssl_bump bump allowed_domains
ssl_bump terminate all
  1. Inject CA into agent container:
COPY ca-cert.pem /usr/local/share/ca-certificates/awf-ca.crt
RUN update-ca-certificates
  1. Add URL path ACLs:
acl allowed_urls url_regex ^https://github\.com/githubnext/
http_access allow allowed_urls
http_access deny all

Security Considerations

  • CA key stays in tmpfs only (never persisted)
  • Generated per-session, unique to each execution
  • Private key never written to logs
  • Certificate valid for 1 day maximum
  • Users should be informed that HTTPS traffic is inspected

Files to Modify

  • src/squid-config.ts - Add SSL Bump configuration
  • containers/squid/Dockerfile - Ensure OpenSSL tools available
  • containers/agent/Dockerfile - CA certificate injection
  • New: src/ssl-bump.ts - CA generation utilities

Testing

Add test cases:

  • URL path filtering for HTTPS works
  • CA injection successful
  • CA key not exposed in logs
  • Self-signed cert handling
  • Certificate chain validation</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Fix TLS content inspection for HTTPS traffic feat: add SSL Bump support for HTTPS content inspection Dec 19, 2025
Copilot AI requested a review from Mossaka December 19, 2025 09:51
@Mossaka Mossaka added the smoke label Dec 19, 2025
@github-actions
Copy link

📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing...

@github-actions
Copy link

💥 WHOOSH! Smoke Claude springs into action on this pull request! [Panel 1 begins...]

@Mossaka Mossaka marked this pull request as ready for review December 19, 2025 17:52
@github-actions
Copy link

Smoke Test Results (Run #20378121588)

PR #111: docs: streamline README for first-time visitors
PR #108: feat: add install script with sha256 validation

✅ GitHub MCP Test: PASS
✅ File Write Test: PASS
✅ Bash Tool Test: PASS

Overall: PASS

📰 BREAKING: Report filed by Smoke Copilot fer issue #131 🗺️

@github-actions
Copy link

Smoke Test Results (Claude Engine)

✅ GitHub MCP: Last 2 merged PRs retrieved

✅ File Writing: Created test file successfully

✅ Bash Tool: File verification passed

❌ Playwright MCP: Page loaded but assets blocked (tunnel connection failures)

Overall Status: PARTIAL PASS (3/4 tests passed; Playwright networking issues expected in firewall environment)

💥 [THE END] — Illustrated by Smoke Claude fer issue #131 🗺️

@github-actions
Copy link

github-actions bot commented Dec 19, 2025

Test Coverage Report

Metric Coverage Covered/Total
Lines 77.12% 1281/1661
Statements 77.17% 1312/1700
Functions 77.04% 141/183
Branches 69.29% 431/622
Coverage Thresholds

The project has the following coverage thresholds configured:

  • Lines: 38%
  • Statements: 38%
  • Functions: 35%
  • Branches: 30%

Coverage report generated by `npm run test:coverage`

@Mossaka Mossaka force-pushed the copilot/fix-tls-inspection-issue branch from cfd060b to 34b0ec9 Compare December 19, 2025 21:21
@Mossaka
Copy link
Collaborator

Mossaka commented Dec 19, 2025

@copilot, please address the following issues:

  1. parseUrlPatterns() is never called. User URL patterns aren't transformed to regex
  2. SSL database not initialized - Squid will crash on startup
  3. Port 3129 misconfigured - HTTPS traffic routing won't work

and then because this's a power-user feature, can you add documentation, and make it optional (should not come out of the box and affects perf under default mode)?

Copy link
Contributor Author

Copilot AI commented Dec 19, 2025

@copilot, please address the following issues:

  1. parseUrlPatterns() is never called. User URL patterns aren't transformed to regex
    ...

Fixed all three issues in commit af0bc2d:

  1. parseUrlPatterns() now called - User URL patterns are now properly transformed to regex patterns before being passed to Squid config.

  2. SSL database initialized - Squid entrypoint now initializes the SSL certificate database using security_file_certgen -c before starting. The database is mounted at /var/spool/squid_ssl_db.

  3. Port configuration fixed - Changed from https_port 3129 intercept ssl-bump to http_port 3128 ssl-bump for explicit proxy mode. This works correctly with the existing proxy configuration.

Also added power-user warnings to documentation and increased SSL certificate cache from 4MB to 16MB per code review feedback.

Copilot AI and others added 7 commits January 7, 2026 23:46
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
- Fix SSL database initialization: security_file_certgen requires the
  directory to NOT exist, but Docker volume mounts create it. Now
  initSslDb() creates the complete DB structure (certs/, index.txt,
  size) directly on the host.

- Simplify entrypoint.sh: Since DB is pre-initialized on host, the
  entrypoint only needs to fix permissions for the proxy user.

- Fix Squid config ordering: ACL definitions must appear before
  ssl_bump rules that reference them. Moved ${aclSection} before
  ${sslBumpSection} in the config template.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Two issues fixed:

1. URL pattern deny rule was blocking CONNECT requests:
   - The deny rule `http_access deny allowed_domains` was evaluated
     for CONNECT requests, blocking SSL bump before the URL check
   - Added `!CONNECT` to only deny actual HTTP requests after bump
   - CONNECT requests now pass through for domain-allowed hosts

2. URL pattern regex escaping was corrupting .* wildcards:
   - Input `https://api.github.com/users/.*` was becoming
     `^https://api\.github\.com/users/\..*` (incorrect)
   - Now preserves .* patterns using placeholder before escaping
   - Output is correctly `^https://api\.github\.com/users/.*`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@Mossaka Mossaka force-pushed the copilot/fix-tls-inspection-issue branch from 4d05eb4 to 6bcee3e Compare January 7, 2026 23:50
@github-actions
Copy link

github-actions bot commented Jan 7, 2026

📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing...

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

💥 WHOOSH! Smoke Claude springs into action on this pull request! [Panel 1 begins...]

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Smoke Test Results

Last 2 Merged PRs:

Tests:

  • ✅ GitHub MCP Testing
  • ✅ File Writing Testing
  • ✅ Bash Tool Testing

Status: PASS

📰 BREAKING: Report filed by Smoke Copilot fer issue #131 🗺️

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

🔐 Security Review: Critical Concerns Identified

This PR introduces SSL Bump (HTTPS interception), which fundamentally changes the security model. While the feature is well-implemented with reasonable safeguards, there are critical security concerns that must be addressed before merging:


🚨 Critical Issue #1: CA Private Key Mounted to Squid Container

File: src/docker-manager.ts, lines 185-186

squidVolumes.push(`${sslConfig.caFiles.certPath}:${sslConfig.caFiles.certPath}:ro`);
squidVolumes.push(`${sslConfig.caFiles.keyPath}:${sslConfig.caFiles.keyPath}:ro`);

Risk: The CA private key is mounted into the Squid container, which runs as the proxy user. If an attacker compromises the Squid process (e.g., via vulnerability in Squid itself), they gain access to the CA private key and can impersonate any HTTPS site for the duration of the key's validity (1 day).

Why this is critical:

  • Squid is exposed to all user-provided traffic and processes untrusted HTTP/HTTPS requests
  • The CA key grants complete MITM capability for any domain
  • Even though the key is session-specific, a 1-day window is significant for active exploitation

Suggested mitigation:

  1. Principle of least privilege: Only mount the CA certificate (not the private key) to the Squid container if possible
  2. If the key must be mounted, add additional container security hardening:
    • Drop all capabilities except those strictly required for SSL Bump
    • Apply seccomp profile to restrict system calls
    • Use read-only root filesystem for Squid container
  3. Consider reducing CA validity from 1 day to session duration (e.g., 1-2 hours)

⚠️ High Risk #2: No Input Validation for URL Patterns

File: src/ssl-bump.ts, lines 182-208 (function parseUrlPatterns)

The function does basic regex escaping but does not validate:

  • Protocol enforcement (should only allow https://, not http:// or other protocols)
  • Maximum pattern complexity (ReDoS protection)
  • Dangerous patterns like .* alone (matches everything)

Example attack:

# User provides overly broad pattern
awf --ssl-bump --allow-urls ".*" -- malicious-command
# This would allow ALL HTTPS traffic, bypassing domain restrictions

Current code:

export function parseUrlPatterns(patterns: string[]): string[] {
  return patterns.map(pattern => {
    let p = pattern.replace(/\/$/, '');
    // ... escaping logic ...
    if (p.endsWith('.*')) {
      return `^${p}`;
    }
    return `^${p}$`;
  });
}

Suggested action:

  1. Add validation in src/cli.ts (lines 552-560) to enforce:
    // Validate each URL pattern
    for (const url of allowedUrls) {
      if (!url.startsWith('https://')) {
        logger.error(`URL patterns must start with https:// (got: ${url})`);
        process.exit(1);
      }
      if (url === '(redacted)*' || url === 'https://*') {
        logger.error('Wildcard-only patterns are not allowed for security');
        process.exit(1);
      }
    }
  2. Add ReDoS protection by limiting pattern complexity or using a safe regex library

⚠️ Medium Risk #3: SSL Bump ACL Rule Ordering Vulnerability

File: src/squid-config.ts, lines 103-113

The denyNonMatching rule uses !CONNECT to prevent denying the initial CONNECT request, but this creates a potential bypass:

const denyNonMatching = hasPlainDomains
  ? 'http_access deny !CONNECT allowed_domains'
  : hasPatterns
    ? 'http_access deny !CONNECT allowed_domains_regex'
    : '';

Risk: The !CONNECT negation means:

  • CONNECT requests to allowed domains are always allowed (correct for SSL bump to work)
  • But if --allow-urls is specified, this could allow CONNECT to domains even when the actual URLs don't match patterns

Scenario:

  1. User specifies: --allow-domains github.com --ssl-bump --allow-urls "https://github.com/githubnext/*"
  2. Expected: Only URLs under /githubnext/ are allowed
  3. Actual: The CONNECT to github.com is allowed, then URL filtering applies
  4. But there's a window where if URL filtering fails, the connection might already be established

Suggested action:
Review the ACL rule ordering and ensure URL pattern matching happens before the ssl_bump decision, not after. The Squid config should ideally deny at the SSL Bump step based on domain, then filter by URL pattern after bumping.


📋 Low Risk #4: CA Certificate Validity Period

File: src/ssl-bump.ts, line 54

The CA certificate is valid for 1 day by default, which may be too long for session-specific security:

const { workDir, commonName = 'AWF Session CA', validityDays = 1 } = config;

Risk: If an attacker extracts the CA key from /tmp/awf-*/ssl/ before cleanup, they have 1 day to perform MITM attacks.

Suggested action:

  • Reduce default validity to match typical session duration (1-2 hours)
  • Or make it configurable: --ssl-bump-validity-hours 2

📋 Low Risk #5: Missing Documentation of Threat Model Change

Files: docs/ssl-bump.md, docs-site/src/content/docs/reference/ssl-bump.md

The documentation mentions that traffic is intercepted but doesn't clearly explain:

  • The CA key is stored unencrypted in /tmp (world-readable on multi-user systems)
  • Spawned containers inherit the CA trust (potential privilege escalation vector)
  • The feature should never be used in multi-tenant environments

Suggested action:
Add explicit warnings in documentation about:

  1. Multi-user system risks (other users can read /tmp)
  2. Multi-tenant risks (container escape = CA key compromise)
  3. When NOT to use SSL Bump (any untrusted workload)

Positive Security Aspects

The PR does implement several good security practices:

  • ✅ Per-session CA generation (not persistent)
  • ✅ Short CA validity (1 day, though could be shorter)
  • ✅ Restrictive file permissions on CA key (0o600)
  • ✅ SSL/TLS version restrictions (NO_SSLv3, NO_TLSv1, NO_TLSv1_1)
  • ✅ Opt-in feature (requires --ssl-bump flag)
  • ✅ Appropriate warnings in logs and documentation

📝 Recommended Actions Before Merge

Must fix (blocking):

  1. ⚠️ Address Critical Issue Improve links in readme to AW project #1 (CA key exposure in Squid container)
  2. ⚠️ Add URL pattern validation (Issue Secret proxying #2)

Should fix (recommended):
3. Review ACL rule ordering (Issue #3)
4. Consider reducing CA validity period (Issue #4)
5. Enhance documentation warnings (Issue #5)


Overall Assessment: This feature adds significant functionality but also increases the attack surface. With the suggested fixes, it can be safely merged for power-user scenarios with appropriate warnings. However, I recommend clearly documenting that SSL Bump is not recommended for production/untrusted workloads.

cc @Mossaka for review

Ahoy! This treasure was crafted by 🏴‍☠️ Security Guard fer issue #131 🗺️

@github-actions
Copy link

github-actions bot commented Jan 7, 2026

Smoke Test Results

Last 2 merged PRs:

✅ GitHub MCP - Retrieved PR data
✅ File Writing - Created test file successfully
✅ Bash Tool - Verified file contents
❌ Playwright MCP - Page loaded but tunnel errors (likely environment issue)

Overall: PARTIAL PASS - 3/4 tests successful, Playwright has environment issues unrelated to Claude engine

💥 [THE END] — Illustrated by Smoke Claude fer issue #131 🗺️

Security improvements based on review feedback:

1. URL Pattern Validation (cli.ts):
   - Reject patterns not starting with https://
   - Block overly broad patterns like https://* or .*
   - Require path component in URL patterns
   - Add helpful error messages guiding users to correct usage

2. Container Hardening (docker-manager.ts):
   - Drop unnecessary capabilities from Squid container:
     NET_RAW, SYS_ADMIN, SYS_PTRACE, SYS_MODULE, MKNOD,
     AUDIT_WRITE, SETFCAP
   - Reduces attack surface if Squid process is compromised

3. Enhanced Security Documentation (docs/ssl-bump.md):
   - Added prominent security warnings about threat model change
   - Documented when NOT to use SSL Bump:
     - Multi-tenant environments
     - Untrusted workloads
     - Multi-user systems
   - Detailed CA private key exposure risks
   - Listed all implemented mitigations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@github-actions
Copy link

github-actions bot commented Jan 8, 2026

📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing...

@github-actions
Copy link

github-actions bot commented Jan 8, 2026

💥 WHOOSH! Smoke Claude springs into action on this pull request! [Panel 1 begins...]

@github-actions
Copy link

github-actions bot commented Jan 8, 2026

Security Review: Critical Issues Found

I've completed a security review of this SSL Bump implementation and identified several critical security concerns that must be addressed:


🔴 CRITICAL: CA Private Key Stored in World-Readable /tmp

File: src/ssl-bump.ts, lines 57-60

Issue: The CA private key is stored in /tmp/awf-(timestamp)/ssl/ on the host filesystem. While the directory permissions are set to 0o700, /tmp is a world-readable directory and on multi-user systems, other users may be able to:

  1. List directory names in /tmp to discover session IDs
  2. Time-of-check-time-of-use (TOCTOU) race conditions during directory creation
  3. Access the key if permissions aren't set atomically

Code snippet:

const sslDir = path.join(workDir, 'ssl');
if (!fs.existsSync(sslDir)) {
  fs.mkdirSync(sslDir, { recursive: true, mode: 0o700 });
}

Risk: An attacker who obtains the CA private key can impersonate any HTTPS site for the certificate's validity period (1 day).

Recommendation:

  • Use a more secure temporary directory location (e.g., /run/user/(uid)/ or a dedicated AWF runtime directory)
  • Or use mkdtemp() with a secure umask to create the directory atomically
  • Add documentation warning about multi-user system risks

🔴 CRITICAL: Missing Access Control Between Domain and URL Patterns

File: src/squid-config.ts, lines 103-114

Issue: When URL patterns are used with SSL Bump, the access control logic has a flaw. The code generates:

http_access allow allowed_url_0
http_access allow allowed_url_1
http_access deny !CONNECT allowed_domains

However, this appears AFTER the SSL Bump section (line 154), and I don't see where the normal domain http_access allow allowed_domains rule is placed relative to these URL-specific rules. If the domain allowlist rule comes first, it would allow ALL traffic to those domains, bypassing the URL pattern restrictions entirely.

Location: The interaction between SSL Bump URL access rules and the main access rules section needs verification.

Risk: URL path filtering could be completely bypassed if domain-level rules take precedence.

Recommendation:

  • Verify the order of http_access rules in the final Squid config when both --allow-domains and --allow-urls are specified
  • Add integration tests that verify URL filtering actually blocks requests to allowed domains but wrong paths
  • Document the rule precedence clearly

⚠️ HIGH: Squid Container Retains Unnecessary Capabilities

File: src/docker-manager.ts, lines 208-218

Issue: While capabilities are being dropped from the Squid container, it still runs as the proxy user (uid 13) which has read access to the CA private key mounted at /etc/squid/ca-*.pem. If Squid is compromised through a vulnerability, the attacker can read the CA key.

Current mitigation: The key is mounted read-only, which prevents modification but not reading.

Risk: Squid vulnerabilities could lead to CA key exfiltration.

Recommendation:

  • Consider using a more restrictive approach where Squid doesn't have direct filesystem access to the key
  • Or implement key rotation on a shorter interval (hours instead of 1 day)
  • Add seccomp profile restrictions specific to Squid when SSL Bump is enabled

⚠️ MEDIUM: No Validation of URL Pattern Regex Safety

File: src/ssl-bump.ts, lines 182-208

Issue: The parseUrlPatterns() function converts user wildcards to regex but doesn't validate against ReDoS (Regular Expression Denial of Service) attacks. A malicious pattern like `(redacted) could create an expensive regex.

Code snippet:

// Convert * wildcards to .* regex
p = p.replace(/\*/g, '.*');

Risk: ReDoS could cause Squid to hang on regex matching, leading to DoS.

Recommendation:

  • Add validation to limit the number of wildcards per pattern
  • Consider using simpler string matching instead of full regex for common cases
  • Add timeout limits for regex matching in Squid config

⚠️ MEDIUM: SSL DB Directory Permissions Race Condition

File: src/ssl-bump.ts, lines 132-150

Issue: Similar to the CA key directory issue, the SSL database is created in the workDir with sequential permission setting that could be subject to TOCTOU attacks.

Recommendation: Create with secure permissions atomically using umask.


ℹ️ INFO: Missing Capability Drop in Agent Container

File: src/docker-manager.ts

Observation: The PR adds capability drops to the Squid container but doesn't update the agent container's capability configuration when SSL Bump is enabled. While the agent already drops NET_ADMIN after setup, consider adding the same security hardening to match Squid when SSL mode is active.


Required Actions

Before merging:

  1. ✅ Fix the CA private key storage to use a more secure location or document multi-user system restrictions clearly
  2. ✅ Verify and fix the http_access rule ordering to ensure URL patterns actually restrict access
  3. ✅ Add integration tests that verify URL filtering works as expected

Recommended before merging:
4. Add ReDoS protection to URL pattern parsing
5. Fix TOCTOU issues in directory creation
6. Add security warnings about when SSL Bump should NOT be used (already partially done in docs)

The feature is well-implemented overall with good documentation and security awareness, but these issues need to be addressed to maintain the firewall's security posture.

Ahoy! This treasure was crafted by 🏴‍☠️ Security Guard fer issue #131 🗺️

@github-actions
Copy link

github-actions bot commented Jan 8, 2026

🚀 Smoke Test Results

Last 2 Merged PRs:

Test Results:

  • ✅ GitHub MCP Testing (PR retrieval)
  • ✅ File Writing Testing (created /tmp/gh-aw/agent/smoke-test-copilot-20800952212.txt)
  • ✅ Bash Tool Testing (verified file content)

Overall Status: PASS

📰 BREAKING: Report filed by Smoke Copilot fer issue #131 🗺️

@github-actions
Copy link

github-actions bot commented Jan 8, 2026

Smoke Test Results

  1. GitHub MCP: ✅ (Last 2 PRs: Add YAML ruleset support for domain allowlists #141, feat: add no-new-privileges and ptrace syscall blocking #139)
  2. File Writing: ✅
  3. Bash Tool: ✅
  4. Playwright MCP: ❌ (ERR_TUNNEL_CONNECTION_FAILED)

Status: FAIL

💥 [THE END] — Illustrated by Smoke Claude fer issue #131 🗺️

@Mossaka Mossaka requested a review from Copilot January 8, 2026 00:28
@Mossaka Mossaka merged commit 110b633 into main Jan 8, 2026
45 checks passed
@Mossaka Mossaka deleted the copilot/fix-tls-inspection-issue branch January 8, 2026 00:30
Copy link

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

This pull request adds SSL Bump support to enable HTTPS content inspection and URL path filtering. The feature generates per-session CA certificates to intercept HTTPS traffic, allowing the firewall to filter based on URL paths rather than just domain names via SNI.

Key Changes:

  • Implements SSL Bump with per-session CA certificate generation (1-day validity)
  • Adds CLI flags --ssl-bump and --allow-urls for URL path filtering
  • Integrates SSL certificate management into Docker containers with automatic CA injection

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/ssl-bump.ts New module providing CA generation, SSL DB initialization, and URL pattern parsing utilities
src/ssl-bump.test.ts Unit tests for URL pattern parsing with wildcard and regex escaping
src/types.ts Adds SSL Bump configuration types for WrapperConfig and SquidConfig
src/squid-config.ts Generates SSL Bump configuration section with TLS interception settings
src/squid-config.test.ts Tests for SSL Bump configuration generation
src/docker-manager.ts Handles SSL certificate mounting, CA generation, and URL pattern transformation
src/cli.ts Adds --ssl-bump and --allow-urls flags with security validation
containers/squid/Dockerfile Installs OpenSSL and squid-openssl for SSL Bump support
containers/squid/entrypoint.sh Fixes SSL database permissions for Squid proxy user
containers/agent/entrypoint.sh Injects CA certificate into container trust store
docs/ssl-bump.md Comprehensive SSL Bump documentation with security warnings
docs/usage.md Usage documentation for SSL Bump feature
docs/troubleshooting.md SSL Bump troubleshooting section
docs-site/src/content/docs/reference/ssl-bump.md Website documentation for SSL Bump
docs-site/src/content/docs/reference/security-architecture.md Security architecture updates for SSL Bump
docs-site/src/content/docs/reference/cli-reference.md CLI reference updates
docs-site/src/content/docs/index.md Homepage update mentioning URL path filtering
README.md Adds link to SSL Bump documentation
Comments suppressed due to low confidence (1)

containers/squid/Dockerfile:22

  • The comment states port 3129 is for "HTTPS with SSL Bump", but this is incorrect. With SSL Bump, both HTTP and HTTPS are handled on port 3128 using the ssl-bump option. The configuration does not use or expose port 3129 anywhere.
# Expose Squid port (3128 for HTTP, 3129 for HTTPS with SSL Bump)

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

Comment on lines +22 to +24
# Expose Squid port (3128 for HTTP, 3129 for HTTPS with SSL Bump)
EXPOSE 3128
EXPOSE 3129
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

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

Port 3129 is exposed in the Dockerfile comment and EXPOSE directive but is never used or configured in the Squid configuration. The SSL Bump configuration uses port 3128 with the ssl-bump option, not a separate port 3129. This EXPOSE directive should be removed as it's misleading.

This issue also appears in the following locations of the same file:

  • line 22
Suggested change
# Expose Squid port (3128 for HTTP, 3129 for HTTPS with SSL Bump)
EXPOSE 3128
EXPOSE 3129
# Expose Squid port (3128 for HTTP and SSL Bump)
EXPOSE 3128

Copilot uses AI. Check for mistakes.
# Step 3 (SslBump3): Bump or splice based on policy
acl step1 at_step SslBump1
acl step2 at_step SslBump2
acl step3 at_step SslBump3
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

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

The ACL 'step3' is defined at line 141 but is never referenced in any ssl_bump directives. Squid ACL definitions that are not used can cause confusion and should be removed. The SSL Bump configuration only uses step1 and step2 in the peek and stare directives.

Suggested change
acl step3 at_step SslBump3

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +154
export async function generateSessionCa(config: SslBumpConfig): Promise<CaFiles> {
const { workDir, commonName = 'AWF Session CA', validityDays = 1 } = config;

// Create ssl directory in workDir
const sslDir = path.join(workDir, 'ssl');
if (!fs.existsSync(sslDir)) {
fs.mkdirSync(sslDir, { recursive: true, mode: 0o700 });
}

const certPath = path.join(sslDir, 'ca-cert.pem');
const keyPath = path.join(sslDir, 'ca-key.pem');
const derPath = path.join(sslDir, 'ca-cert.der');

logger.debug(`Generating SSL Bump CA certificate in ${sslDir}`);

try {
// Generate RSA private key and self-signed certificate in one command
// Using -batch to avoid interactive prompts
await execa('openssl', [
'req',
'-new',
'-newkey', 'rsa:2048',
'-days', validityDays.toString(),
'-nodes', // No password on private key
'-x509',
'-subj', `/CN=${commonName}`,
'-keyout', keyPath,
'-out', certPath,
'-batch',
]);

// Set restrictive permissions on private key
fs.chmodSync(keyPath, 0o600);
fs.chmodSync(certPath, 0o644);

logger.debug(`CA certificate generated: ${certPath}`);
logger.debug(`CA private key generated: ${keyPath}`);

// Generate DER format for easier import into trust stores
await execa('openssl', [
'x509',
'-in', certPath,
'-outform', 'DER',
'-out', derPath,
]);

fs.chmodSync(derPath, 0o644);
logger.debug(`CA certificate (DER) generated: ${derPath}`);

return { certPath, keyPath, derPath };
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(`Failed to generate SSL Bump CA: ${message}`);
}
}

/**
* Initializes Squid's SSL certificate database
*
* Squid requires a certificate database to store dynamically generated
* certificates for SSL Bump mode. The database structure expected by Squid is:
* - ssl_db/certs/ - Directory for storing generated certificates
* - ssl_db/index.txt - Index file for certificate lookups
* - ssl_db/size - File tracking current database size
*
* NOTE: We create this structure on the host because security_file_certgen
* (Squid's DB initialization tool) requires the directory to NOT exist when
* it runs. Since Docker volume mounts create the directory, we need to
* pre-populate the structure ourselves.
*
* @param workDir - Working directory
* @returns Path to the SSL database directory
*/
export async function initSslDb(workDir: string): Promise<string> {
const sslDbPath = path.join(workDir, 'ssl_db');
const certsPath = path.join(sslDbPath, 'certs');
const indexPath = path.join(sslDbPath, 'index.txt');
const sizePath = path.join(sslDbPath, 'size');

// Create the database structure
if (!fs.existsSync(sslDbPath)) {
fs.mkdirSync(sslDbPath, { recursive: true, mode: 0o700 });
}

// Create certs subdirectory
if (!fs.existsSync(certsPath)) {
fs.mkdirSync(certsPath, { mode: 0o700 });
}

// Create index.txt (empty file for certificate index)
if (!fs.existsSync(indexPath)) {
fs.writeFileSync(indexPath, '', { mode: 0o600 });
}

// Create size file (tracks current DB size, starts at 0)
if (!fs.existsSync(sizePath)) {
fs.writeFileSync(sizePath, '0\n', { mode: 0o600 });
}

logger.debug(`SSL certificate database initialized at: ${sslDbPath}`);
return sslDbPath;
}
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

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

The core SSL Bump functions generateSessionCa and initSslDb lack test coverage. These functions handle critical security functionality including CA certificate generation and SSL database initialization. Consider adding tests to verify certificate generation, file permissions, error handling, and database structure creation.

Copilot uses AI. Check for mistakes.
Comment on lines +157 to +170
* Validates that OpenSSL is available
*
* @returns true if OpenSSL is available, false otherwise
*/
export async function isOpenSslAvailable(): Promise<boolean> {
try {
await execa('openssl', ['version']);
return true;
} catch {
return false;
}
}

/**
Copy link

Copilot AI Jan 8, 2026

Choose a reason for hiding this comment

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

The function isOpenSslAvailable is exported but never used anywhere in the codebase. Consider either using it to validate OpenSSL availability before calling generateSessionCa, or removing it if it's not needed.

Suggested change
* Validates that OpenSSL is available
*
* @returns true if OpenSSL is available, false otherwise
*/
export async function isOpenSslAvailable(): Promise<boolean> {
try {
await execa('openssl', ['version']);
return true;
} catch {
return false;
}
}
/**

Copilot uses AI. Check for mistakes.
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.

[Security] No TLS/HTTPS content inspection - only SNI visible

2 participants