Skip to content

fix(security): block SSRF in data resolver route - #1655

Merged
olexii4 merged 3 commits into
mainfrom
CRW-11948
Aug 31, 2026
Merged

fix(security): block SSRF in data resolver route#1655
olexii4 merged 3 commits into
mainfrom
CRW-11948

Conversation

@olexii4

@olexii4 olexii4 commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes an SSRF vulnerability in POST /dashboard/api/data/resolver that let any authenticated user proxy requests to internal addresses.

Root Cause

The route passed the caller-supplied URL directly to axios.get() with no host filtering. The operator allowlist (spec.devEnvironments.allowedSources.urls) existed in serverConfigApi but was never checked here, so loopback addresses, RFC-1918 ranges, and the cloud IMDS endpoint (169.254.169.254) were all reachable.

Fix

Two guards added to dataResolver.ts:

  1. Private IP block — rejects requests to 127.x, localhost, ::1, 169.254.x, 10.x, 172.16–31.x, 192.168.x with 403 before making any outbound call.
  2. Operator allowlist — when spec.devEnvironments.allowedSources.urls is set, the URL must match an entry (exact or wildcard). Empty list keeps the existing open behavior.

maxRedirects: 0 prevents bypass via redirect from an allowed host.

Also updated the Swagger example URL, which pointed to a private address and would now always return 403.

What issues does this PR fix or reference?

fixes https://redhat.atlassian.net/browse/CRW-11948

Is it tested? How?

Manual via Swagger:

  1. Deploy Eclipse Che with the dashboard image from this PR.
  2. Navigate to https://<che-host>/dashboard/swaggerData ResolverPOST /dashboard/api/data/resolverTry it out.
  3. Submit — verify 403:
    { "url": "http://127.0.0.1:8080/dashboard/devfile-registry/devfiles/index.json" }
  4. Submit — verify 200:
    { "url": "https://raw.githubusercontent.com/devfile-samples/devfile-sample-python-basic/main/devfile.yaml" }

Release Notes

Fixed an SSRF vulnerability in the data resolver endpoint that allowed authenticated users to reach internal network addresses.

Docs PR

N/A

The /dashboard/api/data/resolver route accepted any HTTP URL and
proxied the response verbatim. Any authenticated user could reach
IMDS credential endpoints, loopback addresses, and in-cluster services.

Private/loopback IP ranges are now always rejected (127.x, 10.x,
172.16-31.x, 192.168.x, 169.254.x, localhost). When the operator
configures spec.devEnvironments.allowedSources.urls, the request URL
must also match the allowlist. Redirects are disabled to prevent
bypass via 302.

Fixes: https://redhat.atlassian.net/browse/CRW-11948

Assisted-by: Claude Sonnet 4.6
Signed-off-by: Oleksii Orel <oorel@redhat.com>
Replace the private-IP example URL with a public devfile URL so
Swagger UI does not advertise a request pattern that is now blocked
by the SSRF fix.

Assisted-by: Claude Sonnet 4.6
Signed-off-by: Oleksii Orel <oorel@redhat.com>
@che-bot

che-bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Click here to review and test in web IDE: Contribute

IPv4-mapped IPv6 addresses like [::ffff:169.254.169.254] resolve to
their embedded IPv4 address at the OS level but were not caught by the
hostname check introduced in the previous commit.

Adds isPrivateOctets() helper and a [::ffff:XXXX:YYYY] pattern match
in isPrivateHostname() to decode the embedded first two octets and
apply the same private-range check.

Also adds a test for the 400 path (malformed URL) and a comment in
isUrlAllowed() acknowledging that non-wildcard URL chars are not
regex-escaped, matching the existing frontend isSourceAllowed() behavior.

Assisted-by: Claude Sonnet 4.6
Signed-off-by: Oleksii Orel <oorel@redhat.com>
@github-actions

Copy link
Copy Markdown

Docker image build succeeded: quay.io/eclipse/che-dashboard:pr-1655 (linux/amd64, linux/arm64, linux/s390x)

kubectl patch command
kubectl patch -n eclipse-che "checluster/eclipse-che" --type=json -p="[{"op": "replace", "path": "/spec/components/dashboard/deployment", "value": {containers: [{image: "quay.io/eclipse/che-dashboard:pr-1655", name: che-dashboard}]}}]"

1 similar comment
@github-actions

Copy link
Copy Markdown

Docker image build succeeded: quay.io/eclipse/che-dashboard:pr-1655 (linux/amd64, linux/arm64, linux/s390x)

kubectl patch command
kubectl patch -n eclipse-che "checluster/eclipse-che" --type=json -p="[{"op": "replace", "path": "/spec/components/dashboard/deployment", "value": {containers: [{image: "quay.io/eclipse/che-dashboard:pr-1655", name: che-dashboard}]}}]"

@olexii4
olexii4 requested a review from svor August 31, 2026 14:15
@openshift-ci

openshift-ci Bot commented Aug 31, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: olexii4, svor

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.90909% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.56%. Comparing base (8d59ae9) to head (0ace377).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...s/dashboard-backend/src/routes/api/dataResolver.ts 90.80% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1655      +/-   ##
==========================================
- Coverage   92.56%   92.56%   -0.01%     
==========================================
  Files         596      596              
  Lines       61908    61995      +87     
  Branches     4874     4898      +24     
==========================================
+ Hits        57305    57384      +79     
- Misses       4541     4549       +8     
  Partials       62       62              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@olexii4
olexii4 merged commit 1f4db8b into main Aug 31, 2026
18 of 20 checks passed
@olexii4
olexii4 deleted the CRW-11948 branch August 31, 2026 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants