Add transparent proxy endpoint for RDI native API - #6503
Conversation
@rdi-ui/pipeline ships its own RDI SDK and calls the native RDI API directly from the browser. Route it through RedisInsight's own API instead of exposing RDI to the browser directly: this keeps instance credentials and self-signed-certificate handling server-side, and avoids CORS entirely since the browser only ever talks to RedisInsight. The proxy forwards method/path/query/body/headers to the RDI instance via the existing RdiClient, with the following hardening applied: - Strips hop-by-hop and auth-carrying headers (Authorization, cookies, CSRF token, window-id) in both directions so the proxy's own credentials and RedisInsight's session state never leak to or from RDI. - Rejects non-CRUD HTTP methods and any request path that resolves outside the configured RDI instance URL, including attempts to escape it via encoded dot-segments or smuggled query/fragment delimiters. - Does not follow upstream redirects server-side (which could let an attacker point our backend at an arbitrary host); instead rewrites in-scope 3xx Location headers to the externally reachable proxy URL so the browser's follow-up request stays within the proxy, and strips out-of-scope ones. - Forwards/returns bodies as raw bytes (arraybuffer) to avoid axios parsing and re-serializing non-JSON, binary, or already-encoded payloads. - Forces a sandboxed Content-Security-Policy and nosniff on proxied responses so a compromised RDI instance can't get arbitrary HTML/JS executed under RedisInsight's own origin. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5c2a7e885f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| method: req.method, | ||
| path: RdiProxyController.getUpstreamPath(req, rdiClientMetadata.id), | ||
| query: RdiProxyController.getQueryString(req), | ||
| body: req.body, |
There was a problem hiding this comment.
Preserve non-JSON request bodies
For requests such as text/plain, application/octet-stream, or multipart/form-data, req.body is undefined because the application only installs JSON and URL-encoded parsers in main.ts:65-71. The proxy consequently forwards an empty body while retaining the caller's content type, so native RDI endpoints accepting YAML, binary, or multipart payloads cannot work through this otherwise transparent proxy; capture raw bytes or stream the request for content types the existing parsers do not handle.
Useful? React with 👍 / 👎.
|
|
||
| let resolved: URL; | ||
| try { | ||
| resolved = new URL(location, baseUrl); |
There was a problem hiding this comment.
Resolve relative redirects against the requested upstream URL
When RDI returns a path-relative or query-relative Location, resolving it against the configured base URL changes its meaning. For example, while proxying http://host/rdi/api/v1/pipelines/old, Location: new should resolve to /rdi/api/v1/pipelines/new, but this code resolves it against http://host/rdi and produces /new, which is then stripped as out of scope (or rewritten to the wrong endpoint when there is no subpath). Pass the actual upstream request URL into this method and use it as the resolution base.
Useful? React with 👍 / 👎.
Code Coverage - Backend unit tests
Test suite run success3851 tests passing in 330 suites. Report generated by 🧪jest coverage report action from 5c2a7e8 |
Code Coverage - Integration Tests
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5c2a7e8. Configure here.
| 'proxy', | ||
| ); | ||
|
|
||
| return `${posix.join(proxyPrefix, relativePath)}${resolved.search}${resolved.hash}`; |
There was a problem hiding this comment.
Redirect Location uses the wrong base
Medium Severity
rewriteLocationThroughProxy resolves a redirect Location against rdi.url rather than the request URL that returned the 3xx. Path-relative and query-only values therefore lose the original path, get rewritten to the wrong proxy URL, or are stripped, so the browser cannot follow in-scope redirects through the proxy.
Reviewed by Cursor Bugbot for commit 5c2a7e8. Configure here.
| // overridden below with FORCED_RESPONSE_HEADERS, not just stripped | ||
| 'content-security-policy', | ||
| 'x-content-type-options', | ||
| ]); |
There was a problem hiding this comment.
Origin-wide response headers still forwarded
Medium Severity
STRIPPED_RESPONSE_HEADERS drops clear-site-data because browsers honor it on any same-origin response, but it still forwards other origin-scoped headers such as strict-transport-security, content-security-policy-report-only, report-to, and nel. A compromised RDI instance can therefore set HSTS or leak request URLs via reporting on RedisInsight's origin.
Reviewed by Cursor Bugbot for commit 5c2a7e8. Configure here.


Summary
@rdi-ui/pipelineships its own RDI SDK and calls the native RDI API directly from the browser. This routes it through RedisInsight's own API instead, so instance credentials and self-signed-certificate handling stay server-side and CORS is avoided entirely (the browser only ever talks to RedisInsight).RdiClient, with hardening applied:Authorization, cookies, CSRF token, window-id) in both directions.Locationheaders to the externally reachable proxy URL so the browser's follow-up request stays within the proxy, and strips out-of-scope ones.arraybuffer) to avoid axios parsing/re-serializing non-JSON, binary, or already-encoded payloads.nosniffon proxied responses so a compromised RDI instance can't get arbitrary HTML/JS executed under RedisInsight's own origin.This replaces #6468, which is closed - this branch was recreated with squashed history off latest
main(which already includes the mergedpipeline-management-v2standalone-page work) for a clean review.Test plan
npx jest rdi-proxy api.rdi.client- 64/64 tests passingeslint --fixon all touched files - 0 errorstsc --noEmit- no new errors introduced (only pre-existing, unrelated integration-test typing issues)🤖 Generated with Claude Code
Note
High Risk
Introduces a caller-influenced HTTP proxy to configured RDI instances; overall safety depends on path validation, redirect rewriting, and header filtering holding under edge cases.
Overview
Adds
/rdi/:id/proxy/*so the@rdi-ui/pipelineSDK can call the native RDI API through RedisInsight instead of the browser hitting RDI directly—keeping credentials, TLS, and auth on the server and avoiding CORS.RdiProxyControllerandRdiProxyServiceforward method, path (from the raw URL to preserve encoding), query, body, and filtered headers via the existingRdiClient, which gainsproxyRequestonApiRdiClient. Upstream calls usearraybuffer,validateStatus: null,allowAbsoluteUrls: false, andmaxRedirects: 0; paths are constrained to the configured RDI base (including subpath escapes via../ encoded segments), and in-scope 3xxLocationvalues are rewritten to the proxy URL (out-of-scope locations are stripped). The service strips hop-by-hop, auth, cookie, and CORS-related headers and forcesContent-Security-Policy: sandboxandX-Content-Type-Options: nosniffon responses. TRACE and CONNECT are rejected at the controller.New
RdiProxyRequest/RdiProxyResponsetypes and broad unit tests cover the client, controller, and service;RdiModuleregisters the new controller and provider.Reviewed by Cursor Bugbot for commit 5c2a7e8. Bugbot is set up for automated code reviews on this repo. Configure here.