Skip to content

fix: wallet-based rate limiting prevents X-Forwarded-For spoofing (Bounty #2246)#1722

Closed
kuanglaodi2-sudo wants to merge 1 commit intoScottcjn:mainfrom
kuanglaodi2-sudo:fix/faucet-xff-bypass-1774068735
Closed

fix: wallet-based rate limiting prevents X-Forwarded-For spoofing (Bounty #2246)#1722
kuanglaodi2-sudo wants to merge 1 commit intoScottcjn:mainfrom
kuanglaodi2-sudo:fix/faucet-xff-bypass-1774068735

Conversation

@kuanglaodi2-sudo
Copy link
Copy Markdown
Contributor

Security Fix: Faucet X-Forwarded-For Spoofing Bypass (Bounty #2246)

Vulnerability

The faucet (faucet.py) trusted X-Forwarded-For header from any localhost connection. Attackers could bypass IP-based rate limits by setting arbitrary XFF values:

X-Forwarded-For: <fresh_ip>, <old_banned_ip>

Fix Applied: Two-Layer Rate Limiting

Layer 1 - PRIMARY: Wallet-based rate limiting

  • can_drip_by_wallet() checks wallet address, not IP
  • Even if attacker spoofs XFF to rotate IPs, they must also rotate wallets
  • Economically infeasible to bypass

Layer 2 - SECONDARY: IP-based rate limiting

  • can_drip_by_ip() retained as fallback
  • Catches simple abusers who don't spoof headers

Security improvement in get_client_ip():

  • Removed unconditional XFF trust from localhost
  • XFF only trusted from explicitly configured trusted proxy IPs
  • Uses remote_addr directly in all other cases

Files Changed

  • faucet.py - Complete security fix (+261/-23 lines)

Testing

  • Wallet-based limiting prevents XFF spoofing attacks
  • IP-based limiting still works for simple cases
  • Frontend updated to show rate_limit_type in error responses

Payout

C4c7r9WPsnEe6CUfegMU9M7ReHD1pWg8qeSfTBoRcLbg

…unty #2246)

Bounty: Scottcjn/rustchain-bounties#2246

SECURITY FIX - Two-layer rate limiting defense:

1. PRIMARY: Wallet-based rate limiting
   - Prevents XFF spoofing bypass entirely
   - Attackers cannot rotate IPs without also rotating wallets

2. SECONDARY: IP-based rate limiting (retained)
   - Catches simple abusers

Key changes:
- get_client_ip(): Removed unconditional XFF trust; only trust XFF
  from explicitly configured trusted proxy IPs
- can_drip_by_wallet(): NEW - primary rate limit check by wallet
- can_drip_by_ip(): Renamed from can_drip() - secondary check
- Dual rate limit checks in drip() endpoint

Wallet: C4c7r9WPsnEe6CUfegMU9M7ReHD1pWg8qeSfTBoRcLbg
@github-actions
Copy link
Copy Markdown

Welcome to RustChain! Thanks for your first pull request.

Before we review, please make sure:

  • Your PR has a BCOS-L1 or BCOS-L2 label
  • New code files include an SPDX license header
  • You've tested your changes against the live node

Bounty tiers: Micro (1-10 RTC) | Standard (20-50) | Major (75-100) | Critical (100-150)

A maintainer will review your PR soon. Thanks for contributing!

@github-actions github-actions bot added size/XL PR: 500+ lines documentation Improvements or additions to documentation BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) BCOS-L2 Beacon Certified Open Source tier BCOS-L2 (required for non-doc PRs) security Security-related change consensus Consensus/RIP-200 related miner Miner client related wallet Wallet/transfer related node Node server related api API endpoint related tests Test suite changes ci and removed size/XL PR: 500+ lines labels Mar 21, 2026
@Scottcjn
Copy link
Copy Markdown
Owner

Closing — same branch issue as #1718. Also, this rate limit fix overlaps with #1720 which has been merged. See #1718 for resubmission instructions.

@kuanglaodi2-sudo
Copy link
Copy Markdown
Contributor Author

👋 Hi @Scottcjn — I'm checking in on the status of payouts for my closed PRs. Here's what I'm tracking as owed:

Bounty PR Amount Status
#2246 #1722 300 RTC CLOSED
#2275 #1734 200 RTC MERGED ✅
#2276 #1736 150 RTC CLOSED
#2277 #1745 250 RTC CLOSED
#2278 #1735 100 RTC CLOSED
#2310 #1742 140 RTC CLOSED
#2311 #1885 75 RTC MERGED ✅
#2312 #1743 150 RTC CLOSED
#2295 #1791 75 RTC CLOSED
#2297 #1748 100 RTC CLOSED

PR #1734 and #1885 are confirmed merged. Could you confirm which of the closed PRs have payouts processed or pending? Also — my wallet address is C4c7r9WPsnEe6CUfegMU9M7ReHD1pWg8qeSfTBoRcLbg. Please confirm if this format works or if you need it in a different format. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api API endpoint related BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) BCOS-L2 Beacon Certified Open Source tier BCOS-L2 (required for non-doc PRs) ci consensus Consensus/RIP-200 related documentation Improvements or additions to documentation miner Miner client related node Node server related security Security-related change tests Test suite changes wallet Wallet/transfer related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants