Skip to content

fix(#6844): support wildcard hostnames in SSRF hook egress allowlist - #6845

Open
fullsend-ai-coder[bot] wants to merge 2 commits into
mainfrom
agent/6844-ssrf-wildcard-allowlist
Open

fix(#6844): support wildcard hostnames in SSRF hook egress allowlist#6845
fullsend-ai-coder[bot] wants to merge 2 commits into
mainfrom
agent/6844-ssrf-wildcard-allowlist

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Summary

Adds wildcard hostname support to the SSRF pre-tool hook's egress allowlist, aligning it with the network policy layer that already supports wildcards. Previously, wildcard entries like *.atlassian.net:443 in FULLSEND_EGRESS_ALLOWLIST were silently dropped, causing DNS-failure fail-closed blocks for Jira integration users whose sandbox policies use wildcards.

Changes

  • internal/security/hooks/ssrf_pretool.py:

    • _parse_egress_allowlist(): Accept leading *.domain wildcard entries (stored as ("*.domain", port) tuples). Bare * and mid-string globs remain rejected with a warning.
    • _is_host_allowlisted(): After exact matching, iterate wildcard entries and perform domain-anchored suffix matching — *.atlassian.net matches redhat.atlassian.net but not atlassian.net itself (requires at least one subdomain label) and not atlassian.net.evil.com (suffix-spoof prevention).
  • internal/security/hooks/ssrf_pretool_test.py:

    • Updated test_wildcard_entries_ignoredtest_leading_wildcard_entries_accepted
    • Added parsing tests: bare wildcard rejected, mid-string glob rejected, leading wildcard without port
    • Added TestWildcardAllowlistMatching class (10 tests): subdomain match, multi-level subdomain, base domain rejection, suffix-spoof rejection, port matching, case insensitivity, trailing dot handling
    • Added validate_url integration tests: wildcard allows subdomain on DNS failure, blocks base domain, blocks wrong port

Testing

  • All 156 tests pass (up from 143)
  • ruff check and ruff format pass
  • Secret scan passes

Closes #6844

Post-script verification

  • Branch is not main/master (agent/6844-ssrf-wildcard-allowlist)
  • Secret scan passed (gitleaks — 6439d79a40fa67505cdc916384b2a278a31a1942..HEAD)
  • PR body secret scan passed (gitleaks — no-git)

The SSRF pre-tool hook silently dropped wildcard entries (e.g.
*.atlassian.net:443) from FULLSEND_EGRESS_ALLOWLIST with a warning,
causing DNS-failure fail-closed blocks for hosts that the network
policy intended to allow. This broke Jira integration for orgs
using wildcard policies like *.atlassian.net.

Add leading-wildcard suffix matching to _parse_egress_allowlist()
and _is_host_allowlisted(). Only the *.domain form is accepted —
bare * and mid-string globs remain rejected. Matching requires at
least one subdomain label (*.example.com matches sub.example.com
but not example.com itself) and uses domain-anchored suffix
comparison to prevent spoofing (atlassian.net.evil.com does not
match *.atlassian.net).

Closes #6844
@fullsend-ai-coder
fullsend-ai-coder Bot requested a review from a team as a code owner September 1, 2026 12:13
@fullsend-ai-coder fullsend-ai-coder Bot added the ready-for-review Agent PR ready for human review label Sep 1, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Sep 1, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 12:16 PM UTC · Completed 12:35 PM UTC

Commit: fdf4ffd · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $6.97

@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@fullsend-ai-review fullsend-ai-review Bot added the risk/moderate PR risk: moderate label Sep 1, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Sep 1, 2026

Copy link
Copy Markdown

Risk Assessment: moderate (2/5)

Details

Moderate risk preserved from prior assessment. Tier 1 remains low (small 3-file change, 0.33 test ratio, bot-authored, no protected paths); Tier 2 still elevated due to high churn (13 commits/30d), multi-author contention (5 authors/90d), and heavy regression activity (14 fix/revert commits/90d) on ssrf_pretool.py; Tier 3 adds caution from security-labeled issue modifying SSRF allowlist parsing.

Previous run

Risk Assessment: moderate (2/5)

Details

Moderate risk. Tier 1 is low (small 2-file change, 0.50 test ratio, bot-authored, no protected paths), but Tier 2 elevates due to high churn (13 commits/30d), multi-author contention (5 authors/90d), and heavy recent regression activity (14 fix/revert commits/90d) on ssrf_pretool.py. Tier 3 adds caution from security-labeled issue and the fact that modifying SSRF allowlist parsing changes runtime security behavior.

@fullsend-ai-review

fullsend-ai-review Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review

Findings

Low

  • [authorization/allowlist-scope] internal/security/hooks/ssrf_pretool.py:155 — The wildcard parser accepts broad TLD-level patterns like *.com:443 or *.net:443, which would allowlist egress to every subdomain under that TLD during DNS failures. While FULLSEND_EGRESS_ALLOWLIST is operator-controlled infrastructure (not user-facing), there is no minimum label-depth validation to prevent accidentally over-broad entries. A misconfigured *.com entry would effectively disable SSRF fail-closed behavior for the entire .com namespace.
    Remediation: Consider requiring at least two labels after the wildcard (e.g., reject *.com but accept *.example.com) by checking wc_host_clean.count('.') >= 2 before accepting the entry, or by emitting a loud warning for single-dot patterns.

Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run

Review

Findings

Medium

  • [stale-documentation] docs/contributing/runtime-implementation.md:228 — The FULLSEND_EGRESS_ALLOWLIST environment variable documentation states "exact hostnames only — wildcards are skipped with a warning on stderr." This PR adds leading-wildcard hostname support (e.g., *.atlassian.net:443), making the documented behavior incorrect.
    Remediation: Update the Behaviour column to reflect that leading-wildcard entries (e.g., *.example.com:443) are now accepted and matched by domain-anchored suffix comparison against the request hostname.

Low

  • [edge-case] internal/security/hooks/ssrf_pretool.py:157 — An entry like *..:443 passes validation (startswith("*.") is true, len("*..") > 2 is true, no extra * in wc_host[2:]) but after rstrip(".") the stored tuple becomes ("*", 443). This entry is inert — it cannot match via the wildcard path ("*".startswith("*.") is false) and cannot match via the exact path — so it is not a security concern. However, it silently accepts a malformed entry without warning, inconsistent with the explicit rejection of other malformed wildcards.
    Remediation: Move the rstrip(".") call before the validation check, or validate after stripping: wc_host_clean = wc_host.lower().rstrip(".") then check wc_host_clean.startswith("*.") and len(wc_host_clean) > 2.

Labels: PR modifies SSRF security hook in internal/security/hooks/


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added component/sandbox OpenShell sandbox environment security Security threat model and related concerns labels Sep 1, 2026
@fullsend-ai-coder

fullsend-ai-coder Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Finished Fix · ✅ Success · Started 12:37 PM UTC · Completed 12:43 PM UTC

Commit: fdf4ffd · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $1.69

Move rstrip(".") before the wildcard-shape check in _parse_egress_allowlist
so entries like "*..:443" are correctly rejected instead of silently collapsing
to ("*", 443). Update FULLSEND_EGRESS_ALLOWLIST docs in runtime-implementation
to reflect leading-wildcard support.

Addresses #6845
@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

🔧 Fix agent — iteration 1 (bot-triggered)

Addressed both review findings: (1) updated FULLSEND_EGRESS_ALLOWLIST documentation to reflect leading-wildcard support, (2) fixed edge case where trailing-dot wildcards like ..:443 silently collapsed to ('', 443) by moving rstrip(".") before validation. Added regression test for the edge case. All 157 tests pass.

Fixed (2):

  1. stale-documentation: FULLSEND_EGRESS_ALLOWLIST docs say wildcards are skipped (docs/contributing/runtime-implementation.md): Updated Behaviour column to reflect that leading-wildcard entries (e.g. *.example.com:443) are now accepted and matched by domain-anchored suffix comparison, while bare * and mid-string globs are rejected.
  2. *edge-case: ..:443 silently accepted as malformed entry after rstrip (internal/security/hooks/ssrf_pretool.py): Moved rstrip(".") before the wildcard validation check so entries like *..:443 are correctly rejected. After stripping, .. becomes * which fails the startswith(".") check and emits a warning. Added test_trailing_dot_wildcard_collapses_rejected to cover this case.

Tests: passed

Next steps:

  • /fs-review — request a re-review of the changes
  • /fs-fix <your instruction> — run another fix pass with specific guidance
  • Push commits directly — review re-runs automatically on push
    Updated by fullsend fix agent

@fullsend-ai-review

fullsend-ai-review Bot commented Sep 1, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 12:45 PM UTC · Completed 1:05 PM UTC

Commit: a68d5ce · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $6.15

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

See the review comment for full details.

else:
wc_host = entry
wc_port = 0
wc_host_clean = wc_host.lower().rstrip(".")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] authorization/allowlist-scope

The wildcard parser accepts broad TLD-level patterns like *.com:443 or *.net:443, which would allowlist egress to every subdomain under that TLD during DNS failures. While FULLSEND_EGRESS_ALLOWLIST is operator-controlled infrastructure (not user-facing), there is no minimum label-depth validation to prevent accidentally over-broad entries. A misconfigured *.com entry would effectively disable SSRF fail-closed behavior for the entire .com namespace.

Suggested fix: Consider requiring at least two labels after the wildcard (e.g., reject *.com but accept *.example.com) by checking wc_host_clean.count('.') >= 2 before accepting the entry, or by emitting a loud warning for single-dot patterns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/sandbox OpenShell sandbox environment ready-for-review Agent PR ready for human review risk/moderate PR risk: moderate security Security threat model and related concerns

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SSRF pre-tool hook silently drops wildcard hostnames from FULLSEND_EGRESS_ALLOWLIST

1 participant