fix: reject devnet fallback RPC on mainnet (C2)#81
fix: reject devnet fallback RPC on mainnet (C2)#810x-SquidSol wants to merge 1 commit intodcccrypto:mainfrom
Conversation
The @percolator/shared config defaults FALLBACK_RPC_URL to https://api.devnet.solana.com when the env var is unset. On mainnet this silently routes fallback RPCs (market discovery, liquidation retry, 429 read-only retry) to the wrong network. Add a startup guard in env-guards that: - requires FALLBACK_RPC_URL to be explicitly set when NETWORK=mainnet - rejects URLs containing devnet indicators (api.devnet.solana.com, devnet.helius-rpc.com, etc.) The guard is skipped for non-mainnet networks so devnet usage is unaffected. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdded mainnet-specific validation to environment guards that requires Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 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 unit tests (beta)
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/env-guards.ts`:
- Around line 4-7: The function looksLikeDevnet currently scans the whole URL
string (using DEVNET_INDICATORS) which can misclassify mainnet URLs; update
looksLikeDevnet to parse the URL with the URL constructor, inspect only the
hostname for any DEVNET_INDICATORS, and also check the explicit query/search
param named "cluster" (or similar param your app uses) for the value "devnet";
if URL parsing fails, fall back to a conservative check but prefer the
parsed-hostname+cluster approach; update references to DEVNET_INDICATORS and
ensure the function returns true only when hostname contains a devnet indicator
or the cluster param equals "devnet".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d290e02c-396b-49cf-b2bd-11fe42ee4293
📒 Files selected for processing (2)
src/env-guards.tstests/env-guards.test.ts
| function looksLikeDevnet(url: string): boolean { | ||
| const lower = url.toLowerCase(); | ||
| return DEVNET_INDICATORS.some((indicator) => lower.includes(indicator)); | ||
| } |
There was a problem hiding this comment.
Avoid full-string devnet matching; it can reject valid mainnet URLs.
Line 6 checks the entire URL, so a mainnet endpoint can be falsely blocked if devnet appears in query/path text (e.g., API key value). Parse and validate hostname (and explicit cluster param) instead.
Proposed fix
-/** Known devnet RPC hostnames / URL substrings — used to detect network mismatch */
-const DEVNET_INDICATORS = ["devnet", "api.devnet.solana.com"];
+/** Known devnet RPC hostname indicators */
+const DEVNET_HOST_INDICATORS = ["devnet", "api.devnet.solana.com"];
function looksLikeDevnet(url: string): boolean {
- const lower = url.toLowerCase();
- return DEVNET_INDICATORS.some((indicator) => lower.includes(indicator));
+ try {
+ const parsed = new URL(url);
+ const hostname = parsed.hostname.toLowerCase();
+ const cluster = parsed.searchParams.get("cluster")?.toLowerCase();
+
+ return (
+ DEVNET_HOST_INDICATORS.some((indicator) => hostname.includes(indicator)) ||
+ cluster === "devnet"
+ );
+ } catch {
+ return false;
+ }
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/env-guards.ts` around lines 4 - 7, The function looksLikeDevnet currently
scans the whole URL string (using DEVNET_INDICATORS) which can misclassify
mainnet URLs; update looksLikeDevnet to parse the URL with the URL constructor,
inspect only the hostname for any DEVNET_INDICATORS, and also check the explicit
query/search param named "cluster" (or similar param your app uses) for the
value "devnet"; if URL parsing fails, fall back to a conservative check but
prefer the parsed-hostname+cluster approach; update references to
DEVNET_INDICATORS and ensure the function returns true only when hostname
contains a devnet indicator or the cluster param equals "devnet".
Summary
@percolator/sharedconfig defaultsFALLBACK_RPC_URLtohttps://api.devnet.solana.comwhen the env var is unsetenv-guards.tsthat requiresFALLBACK_RPC_URLto be explicitly set on mainnet and rejects devnet-pointing URLsAffected codepaths
crank.ts:212liquidation.ts:49shared/rpc-client.ts:130Test plan
throws when NETWORK=mainnet and FALLBACK_RPC_URL is not setthrows when NETWORK=mainnet and FALLBACK_RPC_URL points to devnetthrows when NETWORK=mainnet and FALLBACK_RPC_URL contains devnet in Helius URLdoes not throw when NETWORK=mainnet and FALLBACK_RPC_URL is a mainnet endpointdoes not throw when NETWORK=devnet and FALLBACK_RPC_URL is not set🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Tests