Skip to content

refactor: consolidate shell port-spec parsing into shared parse_port_specs()#6037

Merged
lpcox merged 3 commits into
mainfrom
copilot/duplicate-code-host-access-validation
Jul 9, 2026
Merged

refactor: consolidate shell port-spec parsing into shared parse_port_specs()#6037
lpcox merged 3 commits into
mainfrom
copilot/duplicate-code-host-access-validation

Conversation

Copilot AI commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Port validation logic (is_valid_port_spec semantics + IFS=',' read parse loop) was duplicated three times in setup-iptables.sh, diverging from each other and from the TypeScript parseValidPortSpecs() in src/host-iptables-validation.ts. The inline validator in allow_service_ports_to_ip() used a different regex that didn't support ranges; configure_http_dnat() had a dead if/else on *"-"* where both branches executed identical iptables commands.

Changes

containers/agent/setup-iptables.sh

  • Add parse_port_specs <result_array_name> <input> <label> — a bash 4.3+ nameref function that directly mirrors TypeScript parseValidPortSpecs(): trims whitespace, validates each entry via is_valid_port_spec(), warns-and-skips invalid specs, populates the caller's array with valid results
  • allow_service_ports_to_ip(): drop duplicated inline regex — HSP_PORTS is now pre-validated at parse time
  • allow_host_access_to_gateway() / configure_http_dnat(): replace identical IFS=',' read + trim + validate loops with a single parse_port_specs call; remove dead range/single-port if/else in the DNAT path
  • configure_host_access_rules(): replace bare IFS=',' read for AWF_HOST_SERVICE_PORTS with parse_port_specs so both port-env-var consumers validate at the same layer
# Before — duplicated in two functions:
IFS=',' read -ra PORTS <<< "$AWF_ALLOW_HOST_PORTS"
for port_spec in "${PORTS[@]}"; do
  port_spec=$(echo "$port_spec" | xargs)
  if ! is_valid_port_spec "$port_spec"; then
    echo "[iptables] WARNING: Skipping invalid port spec: $port_spec"
    continue
  fi
  iptables -t nat -A OUTPUT -p tcp --dport "$port_spec" -j DNAT ...
done

# After — one call, shared parser:
local -a dnat_ports=()
parse_port_specs dnat_ports "$AWF_ALLOW_HOST_PORTS" "port spec"
for port_spec in "${dnat_ports[@]}"; do
  iptables -t nat -A OUTPUT -p tcp --dport "$port_spec" -j DNAT ...
done

tests/setup-iptables-port-spec.test.sh

  • Add run_parse_port_specs / run_parse_port_specs_warnings test helpers using function extraction (same isolation pattern as the existing is_valid_port_spec tests)
  • Add 9 new cases covering: empty input, single port, multi-port CSV, whitespace trimming, port ranges, invalid-spec filtering with warning emission, all-invalid → empty result, mixed valid/range input

…) shell function

- Add parse_port_specs() to setup-iptables.sh mirroring TypeScript
  parseValidPortSpecs() in src/host-iptables-validation.ts: takes a
  comma-separated input + label, validates each entry via is_valid_port_spec(),
  warns and skips invalid ones, populates a caller nameref array (bash 4.3+).

- Refactor allow_service_ports_to_ip(): remove the duplicated inline regex
  validator since HSP_PORTS is now pre-validated by parse_port_specs().

- Refactor allow_host_access_to_gateway(): replace the inline
  IFS=',' read + trim + is_valid_port_spec loop with parse_port_specs.

- Refactor configure_http_dnat(): replace the inline IFS=',' read +
  trim + is_valid_port_spec loop and the dead range/single-port if/else
  with parse_port_specs.

- Refactor configure_host_access_rules(): replace the bare IFS=',' read
  for AWF_HOST_SERVICE_PORTS with parse_port_specs so validation happens
  at parse time.

- Extend tests/setup-iptables-port-spec.test.sh: add 9 new test cases
  for parse_port_specs (empty input, single port, multiple ports,
  whitespace trimming, port ranges, invalid-spec filtering, warning
  emission, all-invalid input), 62 total.

Closes #6015
Copilot AI changed the title [WIP] Refactor host-access port validation to eliminate duplication refactor: consolidate shell port-spec parsing into shared parse_port_specs() Jul 9, 2026
Copilot finished work on behalf of lpcox July 9, 2026 02:49
Copilot AI requested a review from lpcox July 9, 2026 02:49
@lpcox lpcox marked this pull request as ready for review July 9, 2026 02:56
Copilot AI review requested due to automatic review settings July 9, 2026 02:56

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.

Pull request overview

This PR refactors containers/agent/setup-iptables.sh to consolidate duplicated comma-separated port-spec parsing/validation into a single shared parse_port_specs() helper, keeping the shell behavior aligned with the TypeScript port-spec validator and reducing divergence risk across iptables rule paths.

Changes:

  • Introduces parse_port_specs() (bash nameref-based) to trim, validate, and filter port specs with consistent warning behavior.
  • Replaces multiple bespoke IFS=',' read + trim + validate loops with parse_port_specs() in host access and DNAT configuration paths.
  • Expands shell unit tests to cover parse_port_specs() behavior (empty input, whitespace trimming, ranges, mixed validity, and warning emission).
Show a summary per file
File Description
containers/agent/setup-iptables.sh Adds shared parse_port_specs() and refactors multiple iptables configuration paths to reuse it.
tests/setup-iptables-port-spec.test.sh Adds extraction and functional tests for parse_port_specs() alongside existing port-spec fixtures.

Review details

Tip

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

  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Low

Comment on lines +61 to +64
for _pps_trimmed in "${_pps_entries[@]}"; do
_pps_trimmed=$(echo "$_pps_trimmed" | xargs)
if [ -z "$_pps_trimmed" ]; then
continue
@lpcox

lpcox commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

@copilot address review feedback

Copilot AI commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address review feedback

Fixed in the latest commit. Replaced xargs with pure-bash parameter expansion:

_pps_trimmed="${_pps_trimmed#"${_pps_trimmed%%[! ]*}"}"
_pps_trimmed="${_pps_trimmed%"${_pps_trimmed##*[! ]}"}"

This strips leading and trailing spaces without spawning a subprocess or risk of --prefixed inputs being treated as echo flags. All 62 shell tests continue to pass.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Smoke Copilot BYOK completed. Copilot BYOK mode operational. 🔓

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Smoke Copilot BYOK AOAI (api-key) completed. Copilot AOAI BYOK (api-key) mode operational. 🔓

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Smoke Copilot BYOK AOAI (Entra) completed. Copilot AOAI BYOK (Entra) mode operational. 🔓

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Contribution Check completed successfully!

PR follows the applicable CONTRIBUTING.md guidelines; no contribution-check comment needed.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Security Guard failed. Please review the logs for details.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Build Test Suite completed successfully!

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Smoke Gemini completed. All facets verified. 💎

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🔌 Smoke Services — All services reachable! ✅

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🔑 Smoke Copilot PAT PAT auth validated. All systems operational. ✅

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Smoke Claude passed

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

⚠️ Coverage Regression Detected

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

Overall Coverage

Metric Base PR Delta
Lines 98.98% 98.98% ➡️ +0.00%
Statements 98.94% 98.94% ➡️ +0.00%
Functions 99.44% 99.44% ➡️ +0.00%
Branches 95.64% 95.60% 📉 -0.04%

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Smoke Test: Copilot BYOK (Direct) Mode ✅ PASS

  • ✅ MCP connectivity
  • ✅ GitHub.com HTTP (200)
  • ✅ File I/O ops
  • ✅ BYOK inference (api-proxy → api.githubcopilot.com)

Running in direct BYOK mode via COPILOT_PROVIDER_API_KEY with api-proxy sidecar.

Warning

Firewall blocked 1 domain

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

  • awmgmcpg

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

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Smoke Test: Services Connectivity

  • Redis PING: ❌ Network is unreachable
  • PostgreSQL pg_isready: ❌ No response
  • PostgreSQL SELECT 1: ❌ Network is unreachable

Result: FAILhost.docker.internal (172.17.0.1) is not reachable from this environment. Service containers may not be running or the network route is blocked.

Warning

Firewall blocked 1 domain

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

  • awmgmcpg

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

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🔍 Smoke Test Results

Test Status
GitHub MCP Connectivity
GitHub.com HTTP (200)
File Write/Read

PR: refactor: consolidate shell port-spec parsing into shared parse_port_specs()
Author: @Copilot | Assignees: @lpcox @Copilot

Overall: PASS 🎉

Warning

Firewall blocked 1 domain

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

  • awmgmcpg

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

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🔬 Smoke Test: Copilot PAT Auth

Test Result
GitHub MCP connectivity ✅ MCP bridge reachable
GitHub.com HTTP ⚠️ pre-step data not injected
File write/read ⚠️ pre-step data not injected

Overall: PARTIAL — Template vars unresolved; pre-computed outputs unavailable. Auth mode: PAT (COPILOT_GITHUB_TOKEN)

Warning

Firewall blocked 1 domain

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

  • awmgmcpg

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

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

✅ fix: use tag-only image ref in rootless permission repair
✅ chore: upgrade gh-aw extension to v0.82.5 pre-release
✅ GitHub title check
✅ file write/read
✅ build
Overall: PASS

Warning

Firewall blocked 2 domains

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

  • awmgmcpg
  • registry.npmjs.org

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

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

See Network Configuration for more information.

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Smoke Test: Claude Engine Validation

Check Result
API Status ✅ PASS
GH Check ✅ PASS
File Status ✅ PASS

Overall Result: PASS

Warning

Firewall blocked 1 domain

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

  • awmgmcpg

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

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

Generated by Smoke Claude for #6037 · 35.1 AIC · ⊞ 3.3K ·
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Smoke Test Results (Gemini)

  • GitHub MCP Testing: ❌ (No tools available)
  • GitHub.com Connectivity: ❌ (HTTP 000)
  • File Writing Testing: ✅
  • Bash Tool Testing: ✅

Overall Status: FAIL

Warning

Firewall blocked 1 domain

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

  • localhost

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

network:
  allowed:
    - defaults
    - "localhost"

See Network Configuration for more information.

💎 Faceted by Smoke Gemini
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Chroot Version Comparison

Runtime Host Version Chroot Version Match?
Python 3.12.13 3.12.3 ❌ NO
Node.js v24.18.0 v22.23.1 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Overall: FAILED — Python and Node.js versions differ between host and chroot.

Warning

Firewall blocked 1 domain

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

  • awmgmcpg

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

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

@lpcox

  • GitHub MCP connectivity: ✅
  • GitHub.com HTTP: ✅
  • File write/read: ✅
  • BYOK inference (Azure OpenAI via Entra): ✅

Running in direct BYOK mode (AWF_AUTH_TYPE=github-oidc + AWF_AUTH_AZURE_* + COPILOT_PROVIDER_BASE_URL) via api-proxy → Azure OpenAI (Foundry, o4-mini-aw) authenticated via Microsoft Entra

Overall: PASS

Warning

Firewall blocked 1 domain

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

  • awmgmcpg

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

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

🪪 BYOK (AOAI Entra) report filed by Smoke Copilot BYOK AOAI (Entra)
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Jul 9, 2026

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 passed ✅ PASS
Go env passed ✅ PASS
Go uuid 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

Note: Java Maven tests required a writable local repository (-Dmaven.repo.local) as the default ~/.m2/repository was owned by root in this environment. All tests passed after this workaround.

Warning

Firewall blocked 1 domain

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

  • awmgmcpg

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

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

Generated by Build Test Suite for #6037 · 63.2 AIC · ⊞ 6.9K ·
Add label ready-for-aw to run again

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🔬 OTEL Tracing Smoke Test Results

Scenario Status Detail
1. Module Loading otel.js loads cleanly; exports: startRequestSpan, setTokenAttributes, setBudgetAttributes, endSpan, endSpanError, shutdown, isEnabled
2. Test Suite 59 tests passed, 0 failed across otel.test.js and otel-fanout.test.js
3. Env Var Forwarding src/services/api-proxy-env-config.ts forwards GH_AW_OTLP_ENDPOINTS, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS, GITHUB_AW_OTEL_TRACE_ID, GITHUB_AW_OTEL_PARENT_SPAN_ID, OTEL_SERVICE_NAME
4. Token Tracker Integration onUsage callback present in token-tracker-http.js (lines 285/343) as the OTEL hook point
5. OTEL Diagnostics Graceful degradation confirmed — falls back to FileSpanExporter at /var/log/api-proxy/otel.jsonl when no OTEL env vars set

All 5 scenarios pass. OTEL tracing integration is functional.

Warning

Firewall blocked 1 domain

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

  • awmgmcpg

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

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

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

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Running in direct BYOK mode (COPILOT_PROVIDER_API_KEY + COPILOT_PROVIDER_BASE_URL) via api-proxy → Azure OpenAI (Foundry, o4-mini-aw)

Merged PRs: ${{ steps.smoke-data.outputs.SMOKE_PR_DATA }}

  1. GitHub MCP Testing ✅
  2. github.com connectivity ✅
  3. File I/O ✅
  4. BYOK inference ✅

Overall: PASS

cc @lpcox

Warning

Firewall blocked 1 domain

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

  • awmgmcpg

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

network:
  allowed:
    - defaults
    - "awmgmcpg"

See Network Configuration for more information.

🔑 BYOK (AOAI api-key) report filed by Smoke Copilot BYOK AOAI (api-key)
Add label ready-for-aw to run again

@lpcox lpcox merged commit bd98cef into main Jul 9, 2026
86 of 88 checks passed
@lpcox lpcox deleted the copilot/duplicate-code-host-access-validation branch July 9, 2026 03:39
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.

[Duplicate Code] Host-access port validation still repeats across firewall layers

3 participants