Conversation
WalkthroughThis PR introduces an SSL verification bypass mechanism controlled by a Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/main/actions/getProxiedAxios.ts`:
- Around line 95-97: The request interceptor uses loose truthy checks on
requestConfig.sslVerificationDisabled (in instance.interceptors.request.use and
the similar branches at the other occurrences) which can accidentally disable
TLS verification; change those conditions to an explicit boolean comparison
(requestConfig.sslVerificationDisabled === true) and, where possible, narrow the
type of requestConfig (or cast to a known ApiRequest shape) before checking to
ensure type-safety for the properties used on lines referencing
sslVerificationDisabled (e.g., in the request interceptor and the blocks at the
other occurrences).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 722100dc-1c74-45cb-aae7-78e044d7ac92
📒 Files selected for processing (2)
src/main/actions/getProxiedAxios.tssrc/main/actions/makeApiClientRequest.js
| instance.interceptors.request.use((requestConfig: any) => { | ||
| if (requestConfig.sslVerificationDisabled) { | ||
| requestConfig.httpsAgent = new PatchedHttpsProxyAgent({ |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== All references to sslVerificationDisabled (with context) ==="
rg -n -C2 '\bsslVerificationDisabled\b' --type ts --type js
echo
echo "=== Potential non-boolean assignments in object literals ==="
rg -nP --type ts --type js 'sslVerificationDisabled\s*:\s*(["`\x27].*["`\x27]|[0-9]+|null|undefined)\b'
echo
echo "=== Type declarations mentioning sslVerificationDisabled ==="
rg -n --type ts 'sslVerificationDisabled\s*[:?]\s*boolean'Repository: requestly/requestly-desktop-app
Length of output: 2235
🏁 Script executed:
# Read the context around makeApiClientRequest.js where sslVerificationDisabled is assigned
cat -n src/main/actions/makeApiClientRequest.js | head -120 | tail -30Repository: requestly/requestly-desktop-app
Length of output: 1202
🏁 Script executed:
# Search for interface/type definitions of sslVerificationDisabled
rg -n --type ts 'sslVerificationDisabled' -B2 -A2 | grep -E '(interface|type|declare|:|\?)'Repository: requestly/requestly-desktop-app
Length of output: 859
🏁 Script executed:
# Look at the full context of getProxiedAxios.ts to understand the requestConfig type
head -200 src/main/actions/getProxiedAxios.ts | tail -100Repository: requestly/requestly-desktop-app
Length of output: 3082
🏁 Script executed:
# Search for where apiRequest parameter comes from in makeApiClientRequest.js
rg -n --type js 'export|function makeApiClientRequest|const makeApiClientRequest' src/main/actions/makeApiClientRequest.js -A 10Repository: requestly/requestly-desktop-app
Length of output: 565
🏁 Script executed:
# Find where makeApiClientRequest is called
rg -n 'makeApiClientRequest' --type ts --type js -B2 -A2Repository: requestly/requestly-desktop-app
Length of output: 1210
🏁 Script executed:
# Search for interface definitions for apiRequest or similar request structures
rg -n 'interface.*Request|type.*Request' --type ts | head -30Repository: requestly/requestly-desktop-app
Length of output: 259
🏁 Script executed:
# Check if sslVerificationDisabled comes from JSON parsing or external sources
rg -n 'JSON.parse|IPC|ipcMain|ipcRenderer|sslVerificationDisabled' --type ts --type js | grep -E '(JSON.parse|IPC|sslVerificationDisabled)' | head -20Repository: requestly/requestly-desktop-app
Length of output: 2150
🏁 Script executed:
# Look for where the request object structure is defined or used
rg -n 'sslVerificationDisabled.*:' --type ts --type js -B2 -A2Repository: requestly/requestly-desktop-app
Length of output: 508
🏁 Script executed:
# Find the ApiRequest type definition
fd -e ts -e tsx | xargs rg -l 'type ApiRequest|interface ApiRequest'Repository: requestly/requestly-desktop-app
Length of output: 59
🏁 Script executed:
# Read the type definition file
cat -n src/renderer/actions/local-sync/types.ts | grep -A 20 'ApiRequest'Repository: requestly/requestly-desktop-app
Length of output: 1394
🏁 Script executed:
# Check if there's validation before calling makeApiClientRequest in events.js
sed -n '190,210p' src/main/events.jsRepository: requestly/requestly-desktop-app
Length of output: 617
🏁 Script executed:
# Test actual JSON serialization behavior with boolean
node -e "console.log(JSON.stringify({a: true, b: false})); console.log(JSON.parse(JSON.stringify({a: true, b: false})))"Repository: requestly/requestly-desktop-app
Length of output: 117
🏁 Script executed:
# Find the schemas file
fd -name "schemas*" --type fRepository: requestly/requestly-desktop-app
Length of output: 305
🏁 Script executed:
# Search for sslVerificationDisabled in all files to find where it's defined
rg -n 'sslVerificationDisabled' --type ts --type js -B5 -A2 | grep -E '(type |interface |:.*boolean|: \{)' -A 3Repository: requestly/requestly-desktop-app
Length of output: 57
🏁 Script executed:
# Check if there's runtime validation/schema enforcement
rg -n 'zod|joi|ajv|schema.*validate|validate.*schema' --type ts --type js | head -20Repository: requestly/requestly-desktop-app
Length of output: 2284
🏁 Script executed:
# Find the schemas file with correct fd syntax
fd schemas --type fRepository: requestly/requestly-desktop-app
Length of output: 117
🏁 Script executed:
# Search for schemas.ts specifically
find . -name "schemas.ts" -o -name "schemas.js"Repository: requestly/requestly-desktop-app
Length of output: 119
🏁 Script executed:
# Look for where ApiRequest schema is defined
rg 'export.*ApiRequest' --type ts --type jsRepository: requestly/requestly-desktop-app
Length of output: 186
🏁 Script executed:
# Check if there's any type definition at all for sslVerificationDisabled
rg 'sslVerificationDisabled' --type ts -B 10 | head -50Repository: requestly/requestly-desktop-app
Length of output: 3319
🏁 Script executed:
# Read the full schemas.ts file to see HttpRequest and GraphQLRequest definitions
cat src/renderer/actions/local-sync/schemas.tsRepository: requestly/requestly-desktop-app
Length of output: 4839
🏁 Script executed:
# Check if sslVerificationDisabled is used anywhere else in the codebase
rg -n 'sslVerificationDisabled' --type ts --type jsRepository: requestly/requestly-desktop-app
Length of output: 569
🏁 Script executed:
# Look for any validation or enforcement of the ApiRequest schema
rg -n 'ApiRequest.*validate|validate.*ApiRequest' --type ts --type jsRepository: requestly/requestly-desktop-app
Length of output: 57
Use explicit boolean checks for sslVerificationDisabled in security-critical TLS decisions.
sslVerificationDisabled is not defined in the ApiRequest schema and is accessed without type safety on lines 96, 113, 136, and 149. The truthy/falsy checks on an any-typed requestConfig can mishandle non-boolean values or omitted properties, unintentionally disabling certificate validation. Use explicit === true comparison instead.
🔧 Proposed fix
instance.interceptors.request.use((requestConfig: any) => {
+ const disableSslVerification = requestConfig.sslVerificationDisabled === true;
- if (requestConfig.sslVerificationDisabled) {
+ if (disableSslVerification) {
requestConfig.httpsAgent = new PatchedHttpsProxyAgent({
host: config.ip,
port: config.port,
ca: readFileSync(config.rootCertPath),
rejectUnauthorized: false,
});
}
return requestConfig;
});
instance.interceptors.request.use(async (requestConfig: any) => {
- const { url: requestUrl, sslVerificationDisabled } = requestConfig;
+ const { url: requestUrl } = requestConfig;
+ const disableSslVerification = requestConfig.sslVerificationDisabled === true;
if (isLocalhost) {
const lookup = await createLocalhostLookup(port);
requestConfig.httpAgent = new http.Agent({ lookup });
requestConfig.httpsAgent = new https.Agent({
lookup,
- rejectUnauthorized: !sslVerificationDisabled
+ rejectUnauthorized: !disableSslVerification
});
- } else if (sslVerificationDisabled) {
+ } else if (disableSslVerification) {
requestConfig.httpsAgent = new https.Agent({ rejectUnauthorized: false });
}Also applies to: 136, 149
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/actions/getProxiedAxios.ts` around lines 95 - 97, The request
interceptor uses loose truthy checks on requestConfig.sslVerificationDisabled
(in instance.interceptors.request.use and the similar branches at the other
occurrences) which can accidentally disable TLS verification; change those
conditions to an explicit boolean comparison
(requestConfig.sslVerificationDisabled === true) and, where possible, narrow the
type of requestConfig (or cast to a known ApiRequest shape) before checking to
ensure type-safety for the properties used on lines referencing
sslVerificationDisabled (e.g., in the request interceptor and the blocks at the
other occurrences).
| // Preserve SSL bypass flag alongside localhost lookup logic | ||
| requestConfig.httpsAgent = new https.Agent({ | ||
| lookup, | ||
| rejectUnauthorized: !sslVerificationDisabled |
There was a problem hiding this comment.
please add the documentation of this config and the nuances of using it in the PR description
|
|
||
| // Interceptor to disable SSL securely when Proxy is enabled | ||
| instance.interceptors.request.use((requestConfig: any) => { | ||
| if (requestConfig.sslVerificationDisabled) { | ||
| requestConfig.httpsAgent = new PatchedHttpsProxyAgent({ | ||
| host: config.ip, | ||
| port: config.port, | ||
| ca: readFileSync(config.rootCertPath), | ||
| rejectUnauthorized: false, | ||
| }); | ||
| } | ||
| return requestConfig; | ||
| }); |
There was a problem hiding this comment.
this scope is currently not triggered, so are these changes necessary? could you please confirm?
| @@ -115,7 +129,12 @@ function createAxiosInstance( | |||
|
|
|||
| const lookup = await createLocalhostLookup(port); | |||
| requestConfig.httpAgent = new http.Agent({ lookup }); | |||
| requestConfig.httpsAgent = new https.Agent({ lookup }); | |||
|
|
|||
| // Preserve SSL bypass flag alongside localhost lookup logic | |||
| requestConfig.httpsAgent = new https.Agent({ | |||
| lookup, | |||
| rejectUnauthorized: !sslVerificationDisabled | |||
| }); | |||
|
|
|||
| // Node.js skips DNS lookup for raw IP literals, so the custom lookup | |||
| // above has no effect. Rewrite the URL to the concrete working IP. | |||
| @@ -127,6 +146,9 @@ function createAxiosInstance( | |||
| requestConfig.url = requestUrl.replace(hostname, targetIp); | |||
| } | |||
| } | |||
| } else if (sslVerificationDisabled) { | |||
| // Handle standard web requests where SSL is bypassed | |||
| requestConfig.httpsAgent = new https.Agent({ rejectUnauthorized: false }); | |||
There was a problem hiding this comment.
now that we have two things affecting the https agent config, can we structure this code better to be readable.
There was a problem hiding this comment.
discussed further on call
There was a problem hiding this comment.
needs a compatibility flag + a release plan
because even though the IPC call seems safe across version, we wouldn't want to show the feature on versions where the functionality isn't enforced
https://browserstack.atlassian.net/browse/RQ-737
Summary by CodeRabbit