Skip to content

fix(ssrf): block loopback addresses for trusted hostname origins#100835

Merged
steipete merged 6 commits into
openclaw:mainfrom
machine3at:fix/4.2-ssrf-trusted-hostname-loopback-check
Jul 7, 2026
Merged

fix(ssrf): block loopback addresses for trusted hostname origins#100835
steipete merged 6 commits into
openclaw:mainfrom
machine3at:fix/4.2-ssrf-trusted-hostname-loopback-check

Conversation

@machine3at

@machine3at machine3at commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Note

AI-Assisted Contribution: This PR was prepared and validated with the assistance of an AI coding assistant (Antigravity/Gemini).

What Problem This Solves

This PR resolves a security boundary bypass where hostnames configured as trusted/allowed origins (and promoted to allowedHostnames during a request) bypass loopback DNS checks. Because assertAllowedTrustedHostnameResolvedAddressesOrThrow did not block loopback addresses, a trusted non-localhost hostname (e.g. lan-llm.corp.internal) resolving/rebinding to a loopback IP (127.0.0.1 or ::1) would be allowed. This exposes the gateway to DNS rebinding attacks targeting localhost services.

Faulty code snippet in ssrf.ts:

function assertAllowedTrustedHostnameResolvedAddressesOrThrow(
  results: readonly LookupAddress[],
): void {
  for (const entry of results) {
    if (isLinkLocalIpAddress(entry.address) || isCloudMetadataIpAddress(entry.address)) {
      throw new SsrFBlockedError(BLOCKED_RESOLVED_IP_MESSAGE);
    }
  }
}

Why This Change Was Made

The change blocks loopback resolutions for trusted hostnames unless the hostname itself is explicitly a localhost origin (e.g. localhost, 127.0.0.1, ::1, or matching *.localhost), which is required for legitimate local-dev provider configurations.

Fixed code snippet in ssrf.ts:

function assertAllowedTrustedHostnameResolvedAddressesOrThrow(
  results: readonly LookupAddress[],
  hostname: string,
): void {
  const isLoopbackAllowed =
    hostname === "localhost" ||
    hostname === "127.0.0.1" ||
    hostname === "::1" ||
    hostname.endsWith(".localhost") ||
    isLoopbackIpAddress(hostname);

  for (const entry of results) {
    if (
      (!isLoopbackAllowed && isLoopbackIpAddress(entry.address)) ||
      isLinkLocalIpAddress(entry.address) ||
      isCloudMetadataIpAddress(entry.address)
    ) {
      throw new SsrFBlockedError(BLOCKED_RESOLVED_IP_MESSAGE);
    }
  }
}

User Impact

Tightens the gateway's SSRF boundary to protect against malicious DNS rebinding to local-host services while keeping support for explicit local development configurations.

Important

Upgrade compatibility note:
Non-localhost custom or private local provider aliases (e.g., pointing to custom local DNS names resolving to 127.0.0.1) will now be blocked unless users explicitly opt in by enabling allowPrivateNetwork in their configuration policy or use a localhost hostname.


Evidence

Unit Tests / Verification Suite

  • Unit tests in src/plugin-sdk/ssrf-policy.test.ts fully cover all cases.
  • Total test count: 49 tests in the isolated run.

Real Behavior Proof

Scenario A — [Attack/Bad Input]: Blocked ✅

Rebinding a trusted private origin to loopback IPv4/IPv6 is successfully blocked.
Test cases:

  • rebinding a trusted private origin to a loopback IP is rejected
  • rebinding a trusted private origin to IPv6 loopback is rejected
  it("rebinding a trusted private origin to a loopback IP is rejected", async () => {
    const baseUrl = "http://lan-llm.corp.internal:11434/v1";
    const policy = ssrfPolicyFromHttpBaseUrlAllowedOrigin(baseUrl);
    const policyForUrl = resolveSsrFPolicyForUrl(new URL(baseUrl), policy);

    await expect(
      resolvePinnedHostnameWithPolicy("lan-llm.corp.internal", {
        policy: policyForUrl,
        lookupFn: createLookupFn([{ address: "127.0.0.1", family: 4 }]),
      }),
    ).rejects.toThrow(SsrFBlockedError);
  });

Scenario B — [Legitimate Input]: Still Allowed ✅

Explicit localhost/127.0.0.1 origins resolving to loopback are still permitted.
Test cases:

  • explicit localhost origin resolving to 127.0.0.1 is still allowed
  • explicit 127.0.0.1 origin resolving to loopback is still allowed
  it("explicit localhost origin resolving to 127.0.0.1 is still allowed", async () => {
    const baseUrl = "http://localhost:11434/v1";
    const policy = ssrfPolicyFromHttpBaseUrlAllowedOrigin(baseUrl);
    const policyForUrl = resolveSsrFPolicyForUrl(new URL(baseUrl), policy);

    await expect(
      resolvePinnedHostnameWithPolicy("localhost", {
        policy: policyForUrl,
        lookupFn: createLookupFn([{ address: "127.0.0.1", family: 4 }]),
      }),
    ).resolves.toBeDefined();
  });

Scenario C — [Pre-existing Rejections]: Unaffected ✅

Pre-existing rejections to cloud metadata or link-local IPs remain blocked.
Test cases:

  • rebinding a trusted private origin to a metadata IP is still rejected
  • rejects plugin-supplied allowedOrigins entry: AWS/EC2 IMDS IPv4 literal
  • rejects plugin-supplied allowedOrigins entry: GCP metadata canonical hostname
  it("rebinding a trusted private origin to a metadata IP is still rejected", async () => {
    const baseUrl = "http://lan-llm.corp.internal:11434/v1";
    const policy = ssrfPolicyFromHttpBaseUrlAllowedOrigin(baseUrl);
    const policyForUrl = resolveSsrFPolicyForUrl(new URL(baseUrl), policy);

    await expect(
      resolvePinnedHostnameWithPolicy("lan-llm.corp.internal", {
        policy: policyForUrl,
        lookupFn: createLookupFn([{ address: "169.254.169.254", family: 4 }]),
      }),
    ).rejects.toThrow(SsrFBlockedError);
  });

Full Test Run (Real OpenClaw Runner Output)

Run command: OPENCLAW_VITEST_INCLUDE_FILE=/tmp/ssrf-test.json node scripts/run-vitest.mjs run --config test/vitest/vitest.unit-fast.config.ts
Branch name: fix/4.2-ssrf-trusted-hostname-loopback-check
Commit SHA: afcffd44432d08a98d678220741e49e24e772a6e
Timestamp: 2026-07-07T15:07:15+05:30

The `envFile` option is deprecated, please use `envDir: false` instead.

 RUN  v4.1.9 /home/dietpi/Developer/openclaw

 ✓ |unit-fast| src/plugin-sdk/ssrf-policy.test.ts (49 tests) 18ms

 Test Files  1 passed (1)
      Tests  49 passed (49)
   Start at  15:07:15
   Duration  280ms (transform 73ms, setup 33ms, import 83ms, tests 18ms, environment 0ms)

Real Gateway Runtime Proof

Run command: node --import tsx scripts/proof/proof-ssrf-loopback.mts
Timestamp: 2026-07-07T15:06:56+05:30

=== Proof: SSRF Guarded Fetch Loopback / localhost Checks ===

Scenario: Block non-localhost loopback DNS rebinding (IPv4)
  Allowed Base URL: http://lan-llm.corp.internal:11434/v1
  Target Request URL: http://lan-llm.corp.internal:11434/v1/chat
  Simulated Resolved IP: 127.0.0.1
15:06:56 [security] blocked URL fetch (url-fetch) targetOrigin=http://lan-llm.corp.internal:11434 reason=Blocked: resolves to private/internal/special-use IP address
  [BLOCKED] SSRF Guard successfully blocked request. Error: Blocked: resolves to private/internal/special-use IP address

Scenario: Block non-localhost loopback DNS rebinding (IPv6)
  Allowed Base URL: http://lan-llm.corp.internal:11434/v1
  Target Request URL: http://lan-llm.corp.internal:11434/v1/chat
  Simulated Resolved IP: ::1
15:06:56 [security] blocked URL fetch (url-fetch) targetOrigin=http://lan-llm.corp.internal:11434 reason=Blocked: resolves to private/internal/special-use IP address
  [BLOCKED] SSRF Guard successfully blocked request. Error: Blocked: resolves to private/internal/special-use IP address

Scenario: Allow explicit localhost origin (IPv4)
  Allowed Base URL: http://localhost:11434/v1
  Target Request URL: http://localhost:11434/v1/chat
  Simulated Resolved IP: 127.0.0.1
  [ALLOWED] Request successfully completed! Response: OK

Scenario: Allow explicit 127.0.0.1 origin (IPv4)
  Allowed Base URL: http://127.0.0.1:11434/v1
  Target Request URL: http://127.0.0.1:11434/v1/chat
  Simulated Resolved IP: 127.0.0.1
  [ALLOWED] Request successfully completed! Response: OK

@openclaw-barnacle openclaw-barnacle Bot added size: XS triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. cli CLI command changes size: S and removed size: XS triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. labels Jul 6, 2026
@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 7, 2026, 6:06 AM ET / 10:06 UTC.

Summary
The PR tightens src/infra/net/ssrf.ts so exact trusted hostnames cannot resolve or rebind to loopback unless the requested hostname is explicitly loopback/localhost, and adds SSRF policy plus dispatcher regression tests.

PR surface: Source +31, Tests +89. Total +120 across 3 files.

Reproducibility: yes. at source level. Current main promotes matching allowedOrigins into allowedHostnames, and the trusted-host DNS-answer check blocks metadata/link-local answers but not loopback answers.

Review metrics: 1 noteworthy metric.

  • Loopback trust cases: 5 rebound classes blocked, 6 explicit loopback classes allowed. The table-driven tests define the compatibility boundary maintainers should accept before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Get explicit maintainer acceptance for the fail-closed behavior on non-localhost aliases resolving to loopback.
  • Wait for the remaining exact-head CI jobs to finish.

Risk before merge

  • [P1] Existing non-localhost custom aliases that intentionally resolve to loopback can now fail closed unless users switch to an explicit localhost/loopback hostname or an accepted private-network policy.
  • [P1] The PR changes an SSRF trust boundary: exact-host trust still allows ordinary private answers but now treats loopback rebinding as forbidden unless the hostname itself is explicit loopback.

Maintainer options:

  1. Accept the tightened trusted-host boundary (recommended)
    Merge after owner review if maintainers accept that non-localhost aliases resolving to loopback should fail closed.
  2. Add compatibility guidance or exception
    Require docs, tests, or a narrow exception for any custom loopback alias class that must remain supported.
  3. Pause for shared SSRF policy
    Defer this PR if exact-host trust should be decided together with adjacent guarded-fetch work.

Next step before merge

  • [P2] The remaining action is maintainer security and compatibility acceptance of the trusted-host loopback boundary, not a narrow automated repair.

Maintainer decision needed

  • Question: Should exact trusted-host SSRF policy reject loopback DNS answers for non-loopback hostnames while continuing to allow explicit localhost, localhost.localdomain, *.localhost, and loopback IP literals?
  • Rationale: The patch is coherent, but it intentionally changes a security and upgrade boundary for operator-configured provider origins that may currently use custom DNS aliases to loopback.
  • Likely owner: steipete — He has the strongest current-main and current-PR ownership signal for this exact SSRF boundary.
  • Options:
    • Accept tightened loopback boundary (recommended): Proceed with this shape, treating non-localhost loopback rebinding as unsafe while preserving explicit loopback development origins.
    • Broaden compatibility first: Ask for a narrower compatibility exception or migration guidance for custom loopback aliases before merge.
    • Pause for wider SSRF model: Hold this PR until related guarded-fetch and exact-host trust work share one maintainer-approved policy.

Security
Cleared: The diff is security-sensitive and tightens SSRF behavior; I found no concrete supply-chain, credential, permission, or authorization regression in the changed files.

Review details

Best possible solution:

Land the tightened trusted-host loopback guard after the owning maintainer accepts the fail-closed compatibility behavior and exact-head CI finishes green.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level. Current main promotes matching allowedOrigins into allowedHostnames, and the trusted-host DNS-answer check blocks metadata/link-local answers but not loopback answers.

Is this the best way to solve the issue?

Yes, mostly. The PR fixes the central helper used by both DNS resolution and dispatcher override paths with existing net-policy parsing; the remaining question is maintainer acceptance of the fail-closed compatibility boundary.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 395fbb8eb631.

Label changes

Label changes:

  • add merge-risk: 🚨 compatibility: Merging can break existing custom non-localhost aliases that currently resolve to loopback and rely on exact-origin trust.
  • add merge-risk: 🚨 security-boundary: The diff changes the exact-host SSRF trust boundary for loopback DNS answers.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes terminal output for a focused test run and a guarded-fetch runtime proof of the central block/allow behavior; the final maintainer commit strengthens embedded-IPv4 handling with added tests.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes terminal output for a focused test run and a guarded-fetch runtime proof of the central block/allow behavior; the final maintainer commit strengthens embedded-IPv4 handling with added tests.

Label justifications:

  • P0: The PR addresses an SSRF security-boundary bypass where trusted hostnames could rebind to localhost services.
  • merge-risk: 🚨 compatibility: Merging can break existing custom non-localhost aliases that currently resolve to loopback and rely on exact-origin trust.
  • merge-risk: 🚨 security-boundary: The diff changes the exact-host SSRF trust boundary for loopback DNS answers.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes terminal output for a focused test run and a guarded-fetch runtime proof of the central block/allow behavior; the final maintainer commit strengthens embedded-IPv4 handling with added tests.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes terminal output for a focused test run and a guarded-fetch runtime proof of the central block/allow behavior; the final maintainer commit strengthens embedded-IPv4 handling with added tests.
Evidence reviewed

PR surface:

Source +31, Tests +89. Total +120 across 3 files.

View PR surface stats
Area Files Added Removed Net
Source 1 34 3 +31
Tests 2 89 0 +89
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 3 123 3 +120

What I checked:

  • Repository policy applied: Root AGENTS.md was read fully, and the scoped src/plugin-sdk/AGENTS.md was read because the PR changes SDK boundary tests; the guidance requires deep source, proof, compatibility, and security-boundary review. (AGENTS.md:1, 395fbb8eb631)
  • Current-main vulnerable path: Current main promotes a matching allowedOrigins request into allowedHostnames, which makes shouldSkipPrivateNetworkChecks true for the current hostname. (src/infra/net/ssrf.ts:236, 395fbb8eb631)
  • Current-main trusted-host post-DNS check: The trusted-host DNS-answer check on current main blocks link-local and cloud metadata answers but does not block loopback answers, matching the reported bypass. (src/infra/net/ssrf.ts:413, 59bc7b0e166c)
  • PR head implementation: PR head adds a local loopback classifier that includes embedded IPv4 forms, permits loopback only for explicit loopback hostnames, and passes the normalized hostname into the trusted-host check from both DNS resolution and dispatcher override paths. (src/infra/net/ssrf.ts:414, f4331d175a6a)
  • PR head regression coverage: PR head adds table tests for loopback rebinding rejection, explicit loopback allowance, and dispatcher override handling for trusted private hostnames. (src/plugin-sdk/ssrf-policy.test.ts:462, f4331d175a6a)
  • Dependency contract checked: The existing net-policy helper parses canonical and embedded IPv4-in-IPv6 forms, exposes isLoopbackIpAddress, and extracts embedded IPv4 addresses for transition prefixes used by the PR helper. (packages/net-policy/src/ip.ts:180, 395fbb8eb631)

Likely related people:

  • steipete: Blame for current exact-origin/trusted-host SSRF code points to Peter Steinberger’s recent main commit, and the current PR head was force-pushed with a hardening commit authored by the same handle. (role: introduced behavior and recent area contributor; confidence: high; commits: 59bc7b0e166c, f4331d175a6a, 53aa5232bc00; files: src/infra/net/ssrf.ts, src/infra/net/fetch-guard.ts, src/infra/net/ssrf.dispatcher.test.ts)
  • Kaspre: The exact-origin SSRF trust model and metadata/link-local blocking work that this PR tightens were introduced in the merged origin-scoped SSRF trust commit. (role: SSRF policy feature-history contributor; confidence: high; commits: 44840007d42d; files: src/infra/net/ssrf.ts, src/plugin-sdk/ssrf-policy.ts, src/agents/provider-transport-fetch.ts)
  • Vincent Koc: Recent history on the same SSRF/fetch-guard files includes trusted explicit proxy DNS and lookup normalization work relevant to this boundary. (role: recent adjacent network contributor; confidence: medium; commits: e58d50b7a8, 24eef3d6e3, 47f0dc3adb; files: src/infra/net/ssrf.ts, src/infra/net/fetch-guard.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (7 earlier review cycles)
  • reviewed 2026-07-06T11:30:45.101Z sha 970feaa :: needs real behavior proof before merge. :: [P3] Remove the unrelated cron parser change
  • reviewed 2026-07-06T12:28:15.226Z sha 970feaa :: needs real behavior proof before merge. :: [P3] Remove the unrelated cron parser change
  • reviewed 2026-07-06T16:42:31.930Z sha 970feaa :: needs real behavior proof before merge. :: [P3] Remove the unrelated cron parser change
  • reviewed 2026-07-07T06:18:20.313Z sha 013c1fc :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-07T06:29:26.592Z sha 013c1fc :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-07T07:28:57.106Z sha 013c1fc :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-07T09:25:12.135Z sha 213bd55 :: needs real behavior proof before merge. :: none

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. labels Jul 6, 2026
@machine3at

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. label Jul 6, 2026
@openclaw-barnacle openclaw-barnacle Bot added size: XS and removed cli CLI command changes size: S labels Jul 7, 2026
@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. label Jul 7, 2026
@machine3at

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jul 7, 2026
@machine3at

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@openclaw-barnacle openclaw-barnacle Bot added size: S and removed triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. size: XS labels Jul 7, 2026
@machine3at

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@steipete steipete self-assigned this Jul 7, 2026
@machine3at

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@openclaw-barnacle openclaw-barnacle Bot added the scripts Repository scripts label Jul 7, 2026
@steipete
steipete force-pushed the fix/4.2-ssrf-trusted-hostname-loopback-check branch from afcffd4 to f4331d1 Compare July 7, 2026 09:57
@openclaw-barnacle openclaw-barnacle Bot removed the scripts Repository scripts label Jul 7, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 7, 2026
@steipete

steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Land-ready maintainer repair complete on exact head f4331d175a6a1e962e411f1750e76cea6b2fc7e6.

What changed:

  • kept loopback-rebinding enforcement at the trusted-host SSRF owner boundary;
  • covered direct, mapped, NAT64, and ISATAP IPv4 loopback encodings without broadening the shared locality/auth classifier;
  • preserved explicit localhost, localhost.localdomain, *.localhost, and loopback-IP provider origins;
  • added negative and compatibility proof for the pinned-dispatcher override path;
  • removed the non-asserting mocked proof script in favor of executable regressions.

Proof:

  • Sanitized AWS Crabbox: provider=aws, lease cbx_b1a775f1892a, run run_75139df382ae; public network, no Tailscale, no instance role, trusted bootstrap, exact PR SHA. pnpm test src/plugin-sdk/ssrf-policy.test.ts src/infra/net/ssrf.dispatcher.test.ts passed 2 shards / 69 tests.
  • Structured autoreview: autoreview --mode branch --base origin/main --engine codex --model gpt-5.5 --thinking high; clean, no accepted/actionable findings, confidence 0.84.
  • Exact-head CI: https://github.com/openclaw/openclaw/actions/runs/28857644791 succeeded.
  • Native prepare wrapper: hosted exact-head gates passed; prepared and remote trees match.

Known proof gaps: none for this bounded resolver/dispatcher policy change.

@steipete
steipete merged commit a00e9fc into openclaw:main Jul 7, 2026
146 of 157 checks passed
@steipete

steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

ruel225 added a commit to ruel225/openclaw that referenced this pull request Jul 8, 2026
The SSRF loopback tightening in openclaw#100835 blocked loopback addresses for
trusted hostnames, but the browser navigation guard's explicit allowlist
(allowedHostnames) should permit loopback for explicitly allowed hosts.

Pass the SSRF policy to assertAllowedTrustedHostnameResolvedAddressesOrThrow
so it can check the allowedHostnames list in addition to explicit loopback
hostnames.

Fixes openclaw#101965
ruel225 added a commit to ruel225/openclaw that referenced this pull request Jul 8, 2026
The SSRF loopback tightening in openclaw#100835 blocked loopback addresses for
trusted hostnames, but the browser navigation guard's explicit allowlist
(allowedHostnames) should permit loopback for explicitly allowed hosts.

Pass the SSRF policy to assertAllowedTrustedHostnameResolvedAddressesOrThrow
so it can check the allowedHostnames list in addition to explicit loopback
hostnames.

Fixes openclaw#101965
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 8, 2026
…nclaw#100835)

* fix(ssrf): block loopback addresses for trusted hostname origins

* fix(ssrf): allow loopback resolution for explicitly trusted loopback/localhost hostnames

* refactor(cron): remove unrelated cron session option changes from ssrf branch

* test(ssrf): add explicit loopback-origin allow tests to close ClawSweeper proof gap

* test(ssrf): add real gateway runtime proof script for loopback rebinding

* fix(ssrf): harden trusted-host loopback checks

---------

Co-authored-by: Peter Steinberger <[email protected]>
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
…nclaw#100835)

* fix(ssrf): block loopback addresses for trusted hostname origins

* fix(ssrf): allow loopback resolution for explicitly trusted loopback/localhost hostnames

* refactor(cron): remove unrelated cron session option changes from ssrf branch

* test(ssrf): add explicit loopback-origin allow tests to close ClawSweeper proof gap

* test(ssrf): add real gateway runtime proof script for loopback rebinding

* fix(ssrf): harden trusted-host loopback checks

---------

Co-authored-by: Peter Steinberger <[email protected]>
wheakerd pushed a commit to wheakerd/clawdbot that referenced this pull request Jul 15, 2026
…nclaw#100835)

* fix(ssrf): block loopback addresses for trusted hostname origins

* fix(ssrf): allow loopback resolution for explicitly trusted loopback/localhost hostnames

* refactor(cron): remove unrelated cron session option changes from ssrf branch

* test(ssrf): add explicit loopback-origin allow tests to close ClawSweeper proof gap

* test(ssrf): add real gateway runtime proof script for loopback rebinding

* fix(ssrf): harden trusted-host loopback checks

---------

Co-authored-by: Peter Steinberger <[email protected]>
(cherry picked from commit a00e9fc)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants