Skip to content

fix: 3 security vulnerabilities — XSS in faucet & ledger, anti-Sybil bypass in airdrop#1830

Merged
Scottcjn merged 1 commit into
Scottcjn:mainfrom
AliaksandrNazaruk:fix/security-bugs-batch2
Mar 25, 2026
Merged

fix: 3 security vulnerabilities — XSS in faucet & ledger, anti-Sybil bypass in airdrop#1830
Scottcjn merged 1 commit into
Scottcjn:mainfrom
AliaksandrNazaruk:fix/security-bugs-batch2

Conversation

@AliaksandrNazaruk

Copy link
Copy Markdown
Contributor

Bug Report (Bounty #305)

Bug 1: DOM XSS in faucet.py (High Severity)

The faucet response handler uses innerHTML to render wallet addresses. A malicious wallet like 0x executes JS.
Fix: Replace innerHTML with textContent + createElement.

Bug 2: Stored XSS in payout_ledger.py (Medium Severity)

Jinja2 template renders bounty_id, contributor, pr_url etc without escaping. POST /api/ledger accepts arbitrary strings → stored XSS on admin ledger page.
Fix: Add |e escape filter to all user-controlled variables.

Bug 3: Anti-Sybil Bypass in airdrop_v2.py (High Severity)

/api/airdrop/eligibility reads skip_antisybil from user JSON body → bypasses all anti-Sybil checks (wallet balance, wallet age, GitHub age). Attacker drains 50k wRTC allocation.
Fix: Hardcode skip_antisybil=False in API handler.

Wallet: grim-cod-29

Bug 1 (High): faucet.py — DOM XSS via innerHTML injection
  The faucet response handler used innerHTML to render wallet addresses
  and error messages from the server. A malicious wallet address like
  '0x<img src=x onerror=alert(1)>' would execute arbitrary JavaScript.
  Fix: Replace innerHTML with textContent + createElement (safe DOM API).

Bug 2 (Medium): payout_ledger.py — Stored XSS via unescaped Jinja2 variables
  Template rendered bounty_id, bounty_title, contributor, status, pr_url,
  and tx_hash without escaping. Any of these fields could contain HTML/JS
  injected via the POST /api/ledger endpoint, executing in admin browsers.
  Fix: Add |e (escape) filter to all user-controlled template variables.

Bug 3 (High): airdrop_v2.py — Anti-Sybil bypass via API parameter
  The /api/airdrop/eligibility endpoint accepted skip_antisybil from
  user-supplied JSON body, allowing anyone to bypass wallet balance,
  wallet age, and GitHub age checks. An attacker could claim airdrops
  with fresh/empty wallets and new GitHub accounts.
  Fix: Hardcode skip_antisybil=False in API handler; parameter only
  available via direct Python calls for testing.
@github-actions github-actions Bot added BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) node Node server related size/S PR: 11-50 lines labels Mar 24, 2026
@Scottcjn Scottcjn merged commit 16c0fb8 into Scottcjn:main Mar 25, 2026
3 checks passed
@AliaksandrNazaruk

Copy link
Copy Markdown
Contributor Author

Bounty claim — RTC wallet: RTCf720a28c62e0724b9f745e6dd64ad37b520c0b96 (consolidated claim on PR #1843)

@FlintLeng

Copy link
Copy Markdown
Contributor

Code Review — PR #1830

Reviewer: FlintLeng

✅ LGTM

— FlintLeng

@FlintLeng FlintLeng left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work on this PR — clean implementation with good attention to edge cases.

@FlintLeng FlintLeng left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #1830 — Review:

XSS fix — replaces innerHTML with textContent + DOM element creation (createElement + className). This prevents script injection through wallet addresses or amount fields. Critical security fix. ✅

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

Labels

BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) node Node server related size/S PR: 11-50 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants