Skip to content

fix(security): apply full non-routable IP-class filter on WebClient (GHSA-v49v-673j-g4vj, GHSA-m23h-pvf3-2m7p)#41849

Merged
wyattwalter merged 2 commits into
releasefrom
ww-ghsa-loopback-bypass
May 27, 2026
Merged

fix(security): apply full non-routable IP-class filter on WebClient (GHSA-v49v-673j-g4vj, GHSA-m23h-pvf3-2m7p)#41849
wyattwalter merged 2 commits into
releasefrom
ww-ghsa-loopback-bypass

Conversation

@wyattwalter
Copy link
Copy Markdown
Contributor

@wyattwalter wyattwalter commented May 26, 2026

Summary

Extend the WebClientUtils host filter (REST API / GraphQL / OAuth2 plugin paths) to reject the same set of non-routable IP address classes that the SMTP code path already rejects via resolveIfAllowed: loopback (127.0.0.0/8, ::1), any-local (0.0.0.0, ::), link-local (169.254.0.0/16, fe80::/10), multicast, and IPv6 Unique Local Addresses (fc00::/7). RFC 1918 site-local ranges remain allowed (same intentional exception as resolveIfAllowed).

Addresses:

Approach

requestFilterFn and isDisallowedAndFail now OR an additional check against the existing exact-match DISALLOWED_HOSTS lookup: an IP-literal helper that returns true when InetAddress.isLoopbackAddress(), isAnyLocalAddress(), isLinkLocalAddress(), or isMulticastAddress() is true, or when the address is IPv6 in the fc00::/7 ULA range. The existing canonicalization (IPv4-mapped IPv6 literals normalized to IPv4) handles literal variants.

Test plan

  • mvn -pl appsmith-interfaces test -Dtest=WebClientUtilsTest (48/48, +24 parameterized cases over isBlockedIpAddressClass).
  • mvn -pl appsmith-interfaces spotless:check clean.
  • Validated end-to-end on a deploy preview: REST API requests to literals in the blocked classes return Host not allowed rather than attempting the outbound connection. RFC 1918 and external hosts continue to work.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Strengthened outbound request validation for Docker deployments: expanded blocking to additional non-routable and special IP classes (loopback, any-local, link-local, multicast and IPv6 unique local ranges) to prevent connections to disallowed addresses.
  • Tests

    • Added parameterized tests covering the expanded IP blocking logic, validating recognition of blocked address classes and ensuring other hosts remain allowed.

Review Change Stack

Tip

🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/26515121230
Commit: 7c75fba
Cypress dashboard.
Tags: @tag.All
Spec:


Wed, 27 May 2026 15:22:15 UTC

Automation

/ok-to-test tags="@tag.All"

…GHSA-v49v-673j-g4vj, GHSA-m23h-pvf3-2m7p)

Extends the WebClient/Netty filter check to the full non-routable set already
enforced by resolveIfAllowed: full loopback range (127.0.0.0/8, ::1), any-local
(0.0.0.0, ::), link-local (169.254/16, fe80::/10), multicast, and IPv6 Unique
Local Addresses (fc00::/7). RFC 1918 site-local ranges remain allowed for
legitimate REST API access to internal infrastructure.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

Walkthrough

WebClientUtils extends its DNS resolver and request filtering guards to block non-routable IP address classes (loopback, any-local, link-local, multicast, IPv6 ULA ranges) when running inside Docker, alongside the existing denylist. New parameterized tests validate both blocked and allowed host patterns.

Changes

Docker IP Address Class Blocking

Layer / File(s) Summary
Docker IP address blocking logic
app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java
isDisallowedAndFail, requestFilterFn, and resolveIfAllowed now use centralized checks to classify and block loopback, any-local, link-local, multicast, and IPv6 ULA (fc00::/7) address classes when IN_DOCKER=1; new helpers isBlockedIpAddressClass, matchesBlockedAddressClass, and isBlockedAddressClassInDocker were added.
IP blocking test coverage
app/server/appsmith-interfaces/src/test/java/com/appsmith/util/WebClientUtilsTest.java
Adds assertFalse import and two parameterized tests: one asserting isBlockedIpAddressClass returns true for non-routable IPv4/IPv6 literals, the other asserting it returns false for public IPs and non-IP hostnames.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • subrata71

Poem

🔐 Docker's gates close tight and fast,
Loopback, link-local, and ULA cast;
Resolve and filter both align,
Denylist plus classes now combine,
Tests sing that the blockade lasts.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the security fix: extending non-routable IP-class filtering on WebClient, with explicit references to the addressed vulnerabilities.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The pull request description includes all required template sections with comprehensive details: summary of changes, security advisory links, approach explanation, test plan with verification steps, and communication flag.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ww-ghsa-loopback-bypass

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java (1)

288-313: 💤 Low value

Implementation looks solid.

The bitmask check (firstByte & 0xFE) == 0xFC correctly identifies the fc00::/7 range (ULA). Package-private visibility is appropriate for testing.

Minor observation: the address classification logic (loopback, link-local, any-local, multicast, ULA checks) is duplicated between this method and resolveIfAllowed (lines 236-247). Consider extracting a shared helper if these paths continue to evolve together.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java`
around lines 288 - 313, Duplicate address-classification logic exists in
isBlockedIpAddressClass and resolveIfAllowed; extract the shared checks
(loopback, any-local, link-local, multicast, IPv6 ULA fc00::/7) into a single
helper (e.g., isBlockedAddressClass or isAddressInBlockedClass) and replace the
duplicated blocks in both isBlockedIpAddressClass and resolveIfAllowed to call
that helper; ensure the helper is static and package-private (or private static
if only used in this class) and keep existing behavior for
isBlockedAddressClassInDocker by calling the refactored isBlockedIpAddressClass
which delegates to the new helper.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java`:
- Around line 288-313: Duplicate address-classification logic exists in
isBlockedIpAddressClass and resolveIfAllowed; extract the shared checks
(loopback, any-local, link-local, multicast, IPv6 ULA fc00::/7) into a single
helper (e.g., isBlockedAddressClass or isAddressInBlockedClass) and replace the
duplicated blocks in both isBlockedIpAddressClass and resolveIfAllowed to call
that helper; ensure the helper is static and package-private (or private static
if only used in this class) and keep existing behavior for
isBlockedAddressClassInDocker by calling the refactored isBlockedIpAddressClass
which delegates to the new helper.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 85af20a9-5972-4816-afa8-824074abd0f2

📥 Commits

Reviewing files that changed from the base of the PR and between b36830e and 9de0e61.

📒 Files selected for processing (2)
  • app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java
  • app/server/appsmith-interfaces/src/test/java/com/appsmith/util/WebClientUtilsTest.java

Both resolveIfAllowed (SMTP path) and isBlockedIpAddressClass (REST path) had
the same 4-way isXxxAddress check plus IPv6 ULA byte-mask inlined. Consolidate
into one private helper so the two paths can't drift.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@wyattwalter
Copy link
Copy Markdown
Contributor Author

/build-deploy-preview skip-tests=true

@github-actions
Copy link
Copy Markdown

Deploying Your Preview: https://github.com/appsmithorg/appsmith/actions/runs/26477545224.
Workflow: On demand build Docker image and deploy preview.
skip-tests: true.
env: ``.
PR: 41849.
recreate: .
base-image-tag: .

@github-actions
Copy link
Copy Markdown

Deploy-Preview-URL: https://ce-41849.dp.appsmith.com

@subrata71 subrata71 added the ok-to-test Required label for CI label May 27, 2026
@wyattwalter wyattwalter merged commit ea45488 into release May 27, 2026
159 of 161 checks passed
@wyattwalter wyattwalter deleted the ww-ghsa-loopback-bypass branch May 27, 2026 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test Required label for CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants