Add transparent proxy endpoint for RDI native API - #6468
ArtemHoruzhenko wants to merge 3 commits into
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 482705a |
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".
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".
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 👍 / 👎.
| ) { | ||
| 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.
65753f2 to
52d1587
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 52d1587d92
ℹ️ 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".
Code Coverage - Frontend unit tests
Test suite run success8099 tests passing in 874 suites. Report generated by 🧪jest coverage report action from 74361b6 |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ 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 52d1587. Configure here.
52d1587 to
74361b6
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 74361b6298
ℹ️ 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".
| Object.entries(headers).filter(([name]) => { | ||
| const lowerName = name.toLowerCase(); | ||
| return ( | ||
| !STRIPPED_RESPONSE_HEADERS.has(lowerName) && |
There was a problem hiding this comment.
Strip upstream HSTS before replaying responses
In an HTTPS hosted deployment, an RDI response containing Strict-Transport-Security passes this filter and is emitted as policy for the RedisInsight API origin. Browsers process HSTS on secure subresource responses, so max-age=0 can remove an existing RedisInsight HSTS policy and weaken transport protection for later requests. Treat HSTS as origin-level policy and strip it rather than forwarding it from RDI.
Useful? React with 👍 / 👎.
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).
…, 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.
74361b6 to
482705a
Compare


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 to configured RDI instances using stored credentials; mitigations are substantial but any proxy/SSRF surface warrants careful review.
Overview
Adds
rdi/:id/proxy/*, a server-side passthrough so the upcoming@rdi-ui/pipelineSDK can call the RDI native API without browser CORS or exposing instance credentials. Requests go throughRdiProxyController→RdiProxyService(header filtering, forcedContent-Security-Policy: sandbox/nosniff) →RdiClient.proxyRequestonApiRdiClient, reusing the existing authenticated axios client.proxyRequestforwards method/path/query/body withvalidateStatus: null(4xx/5xx returned to the client),maxRedirects: 0,allowAbsoluteUrls: false, andarraybufferbodies. It blocks path traversal outside the configured RDI URL subpath (including encoded..) and strips unsafeLocationheaders on 3xx. The controller allows only GET/POST/PUT/PATCH/DELETE, slices the upstream path from the raw URL to preserve percent-encoding, and rejects TRACE/CONNECT.New
RdiProxyRequest/RdiProxyResponsetypes and module wiring; specs cover the client, service, and controller.Reviewed by Cursor Bugbot for commit 482705a. Bugbot is set up for automated code reviews on this repo. Configure here.