Add transparent proxy endpoint for RDI native API - #6468
Conversation
26b2880 to
fae4cd3
Compare
Code Coverage - Backend unit tests
Test suite run success3851 tests passing in 330 suites. Report generated by 🧪jest coverage report action from 65753f2 |
Code Coverage - Integration Tests
|
fae4cd3 to
4657769
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 465776968b
ℹ️ 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".
4657769 to
7bd0022
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7bd0022392
ℹ️ 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".
7bd0022 to
1b9497b
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1b9497b61b
ℹ️ 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".
1b9497b to
c5f6525
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c5f65250d3
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 21d95de22c
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dbc7444db8
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: da9c332a52
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 58ae63d5db
ℹ️ 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".
58ae63d to
41f2a1b
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 41f2a1bc8f
ℹ️ 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".
41f2a1b to
3ef1d83
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3ef1d83654
ℹ️ 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".
3ef1d83 to
25b3b2a
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 25b3b2a9cc
ℹ️ 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".
25b3b2a to
c0ff70a
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c0ff70a2db
ℹ️ 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".
Adds an HTTP passthrough (rdi/:id/proxy/*) so the @rdi-ui/pipeline SDK's bundled client can talk to the RDI instance's native API without exposing credentials to the browser or hitting CORS, reusing the same authenticated RdiClient connection every other RDI endpoint already uses. Hop-by-hop, auth, and transport headers (including RDI's own CORS headers and Clear-Site-Data, either of which could interfere with RedisInsight's own origin) are stripped in both directions; the upstream response is forwarded as raw bytes rather than letting axios parse/re-serialize it, which corrupted non-JSON, binary, or already-encoded responses. Closes an SSRF vector where an absolute/scheme-relative path could override the RDI base URL and send the Authorization header to an arbitrary host, and returns 3xx responses to the caller as-is instead of following them server-side, which could otherwise point this backend (not just the browser) at an arbitrary host via a redirect Location. RDI hosted under a subpath (e.g. https://host/rdi) is supported, but a request path is rejected if it would normalize past that subpath. RdiClient gains an abstract proxyRequest() method, implemented once on ApiRdiClient (ApiV2RdiClient inherits it).
c0ff70a to
9c14acf
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9c14acfa92
ℹ️ 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".
…, and encoded traversal Three gaps in the RDI proxy endpoint: - assertPathWithinRdiBase only collapsed literal ".." segments, so an encoded traversal (..%2f, %2e%2e%2f) passed the guard here but could still be decoded and collapsed by RDI itself server-side. - A 3xx response's Location header was forwarded unfiltered, letting a compromised RDI redirect the browser cross-origin while it still carries RedisInsight-only headers. - Proxied responses kept whatever content-type RDI sent, so a compromised RDI returning text/html would execute under the RedisInsight origin if the proxy URL were opened as a document. Decode paths and redirect Locations before validating them, strip Location headers that resolve outside the configured RDI origin/ subpath, and force Content-Security-Policy: sandbox + nosniff on every proxied response.
The proxy's @ALL('*path') forwarded any method verbatim, including TRACE - which, if the upstream RDI server implements it, echoes the request (with the RDI client's bearer token, attached as an axios default header) back in the response body, leaking the server-side credential to the caller. Restrict the proxy to the methods the pipeline SDK actually needs.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 65753f26d8
ℹ️ 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".
| if ( | ||
| locationKey && | ||
| !this.isLocationWithinRdiBase(responseHeaders[locationKey]) | ||
| ) { | ||
| delete responseHeaders[locationKey]; |
There was a problem hiding this comment.
Rewrite allowed redirects back through the proxy
When RDI returns a same-origin redirect, this retains its Location unchanged even though the browser is communicating with the RedisInsight origin. A root-relative value such as /rdi/api/v1/pipelines/new is therefore requested from RedisInsight without the configured API prefix or :id/proxy route, while an absolute RDI URL is followed directly without the proxy-injected bearer token and may fail CORS. Fresh evidence in this revision is that maxRedirects is again set to 0 and locations within the RDI base are explicitly retained; rewrite those locations to the externally reachable proxy URL or follow only validated redirects server-side.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ 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 65753f2. Configure here.
| ) { | ||
| delete responseHeaders[locationKey]; | ||
| } | ||
| } |
There was a problem hiding this comment.
Redirect Location hits RedisInsight origin
High Severity
isLocationWithinRdiBase keeps a 3xx Location when it resolves against rdi.url, then the proxy relays that header unchanged. The browser resolves it against RedisInsight’s origin instead, so a relative in-scope Location becomes a same-origin hop onto RedisInsight routes. A 307/308 can replay the original method, body, and session headers onto /api/*. Absolute RDI Locations also leave the proxy, so the SDK hits RDI directly without the server-side bearer token and without RedisInsight CORS.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 65753f2. Configure here.


What
Fourth PR in the rdi-ui integration chain (stacked on #6467, which is stacked on #6465/#6464).
Adds
rdi/:id/proxy/*, a transparent passthrough to an RDI instance's native API. The upcoming@rdi-ui/pipelinepackage ships its own SDK (@rdi-ui/sdk) that speaks the native RDI API directly rather than RedisInsight's curated/rdi/:id/pipelineendpoints. This proxy gives it something real to call while keeping credentials and TLS handling entirely server-side.Key points:
RdiClientneeds a new method (proxyRequest, declared on the abstractRdiClient, implemented once onApiRdiClient, inherited byApiV2RdiClient): the authenticated connection (bearer token, self-signed-cert TLS bypass) only exists inside that class;RdiClientProvider.getOrCreate()returns the abstractRdiClienttype, so every other RDI capability is already exposed this same way. Reusing it avoids re-implementing login/token-refresh in the proxy layer.authorization/cookiewould override the RDI client's own bearer token or leak RedisInsight's session; forwarding originalcontent-length/content-encodingon the response would corrupt it in the browser once axios has already decompressed the body. Hop-by-hop headers (connection,te,trailer, etc.) are never proxy-safe per RFC 7230.Testing
npm run lint:apiandnpm run type-check --prefix redisinsight/api(0 new errors) pass.RdiProxyService,RdiProxyController, andApiRdiClient.proxyRequest(incl. non-2xx passthrough).rdimodule test suite (293 tests) still passes.No ticket yet.
Note
High Risk
Introduces a generic HTTP proxy that forwards authenticated server requests to user-configured RDI hosts; mitigations exist but SSRF, header smuggling, and open-redirect edge cases remain security-sensitive.
Overview
Adds
rdi/:id/proxy/*, a server-side passthrough so the upcoming@rdi-ui/pipelineSDK can call an RDI instance’s native API through RedisInsight (credentials/TLS stay on the server; browser avoids CORS).RdiProxyControllermaps the raw URL suffix after/proxy(keeping percent-encoding), allows only GET/POST/PUT/PATCH/DELETE, and streams status/headers/body back.RdiProxyServicestrips unsafe hop-by-hop, auth, cookie, and CORS headers on the way in/out, and forcesContent-Security-Policy: sandboxandX-Content-Type-Options: nosniffon responses.ApiRdiClient.proxyRequest(new abstract onRdiClient) forwards via the existing authenticated axios client withvalidateStatus: null(non-2xx pass through),allowAbsoluteUrls: false,maxRedirects: 0, andarraybufferbodies. It blocks path traversal outside the configured RDI base URL (including encoded..) and stripsLocationon 3xx when it would leave the RDI origin/subpath.New
RdiProxyRequest/RdiProxyResponsetypes and unit tests for controller, service, and client;RdiModuleregisters the new controller/service.Reviewed by Cursor Bugbot for commit 65753f2. Bugbot is set up for automated code reviews on this repo. Configure here.