Security (EVM-01): oracle-service uses sequential RPC fallback, not multi-provider cross-check #7
Labels
No labels
enhancement
governance
QA
testing
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
code/ust1-window#7
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
@PlasticDigits finding from security review on #5.
Severity
Medium. Single point of trust in the rate pipeline.
Description
oracle-service/src/evm_rpc.rsrun_with_evm_rpc_url_fallbackiteratesBSC_RPC_URLSsequentially and returns the first successful result. It does not cross-check the rate against other providers before accepting it.Combined with
bsc.rsread_exchange_rate_stored, which takes a singlerpc_url, this means: whatever the first-responding RPC returns is what gets proposed on-chain.Why this matters
BSC_RPC_URLSis user-configured. If one URL is compromised (or an attacker controls its DNS), and it appears first in the list, the attacker can forgeexchangeRateStoredand the service will dutifully broadcast that forged rate to Terra. On-chain caps (4h throttle, 2% daily, monotonic) bound the blast radius per tick, but over many ticks an attacker can steadily push the rate in a harmful direction within caps.A single responsive-and-wrong RPC is enough — the other URLs are only consulted if the first one errors, not when it returns an anomalous value.
Recommendation
Related
mentioned in issue #5
mentioned in commit
8c9fafbe69Fix implemented (merged to
main)Behavior
BSC_RPC_URLSmust now list at least two comma-separated endpoints (validated inconfig::Config::from_env).run_with_evm_rpc_rate_consensus: the first two URLs are queried in parallel viatokio::join!.|a-b| / max(a,b) ≤ 1/10 000(integer check:(hi-lo) * 10_000 ≤ hi).Code
oracle-service/src/evm_rpc.rs: consensus + unit tests for the tolerance helper.oracle-service/src/main.rs: uses the new consensus path instead of first-success fallback.scripts/deploy_local.py: example env shows two Binance dataseed URLs.Commit on
main: merge offix/issue-7-evm-rpc-consensus(pushed toorigin/main).Residual risk / follow-ups: still no reorg handling (EVM-02) or weighted median for ≥3 providers; can extend later if desired.
@PlasticDigits verified fix on
8c9fafb.Code review:
parse_comma_separated_rpc_urls+ startup check: ≥2 URLs now required, startup errors if fewerrun_with_evm_rpc_rate_consensus: queries first two endpoints in parallel, accepts rate only when they agree within 0.01% relative (|a−b|/max ≤ 1e-4)rates_agree_within_point_zero_one_percent)identical_rates_agree,zero_pair,within_point_zero_one_percent,symmetricTolerance choice of 0.01% is a good balance — tight enough to catch malicious forgery, loose enough for cross-provider fixed-point rounding noise.
Workspace test count confirms: 40/40 pass (includes new oracle-service unit tests).
mentioned in issue #19