Skip to content

fix: SafeCallFilter XCM Transact vulnerability (Immunefi #81386)#3798

Open
ouwibo wants to merge 1 commit into
moonbeam-foundation:masterfrom
ouwibo:fix/safecallfilter-xcm-vulnerability
Open

fix: SafeCallFilter XCM Transact vulnerability (Immunefi #81386)#3798
ouwibo wants to merge 1 commit into
moonbeam-foundation:masterfrom
ouwibo:fix/safecallfilter-xcm-vulnerability

Conversation

@ouwibo

@ouwibo ouwibo commented Jun 9, 2026

Copy link
Copy Markdown

Security Fix: SafeCallFilter XCM Transact Vulnerability

Immunefi Submission: https://bugs.immunefi.com/dashboard/submission/81386

Problem

The SafeCallFilter in all three runtimes (Moonbeam, Moonriver, Moonbase) unconditionally returns true for ALL runtime calls, completely bypassing XCM Transact security controls.

// Current vulnerable code (runtime/moonbeam/src/xcm_config.rs:202)
pub struct SafeCallFilter;
impl frame_support::traits::Contains<RuntimeCall> for SafeCallFilter {
    fn contains(_call: &RuntimeCall) -> bool {
        // TODO review
        true  // ← Accepts ALL calls
    }
}

Impact

An attacker with XCM access can execute ANY runtime call including:

  • balances.transfer - Direct fund theft
  • governance.* - Governance manipulation
  • system.setCode - Chain state modification
  • ethereum.transact - Arbitrary EVM execution

Severity: Critical (Immunefi classification)

Fix

Implement proper call filtering that whitelists only safe operations:

pub struct SafeCallFilter;
impl frame_support::traits::Contains<RuntimeCall> for SafeCallFilter {
    fn contains(call: &RuntimeCall) -> bool {
        match call {
            // Allow balance transfers
            RuntimeCall::Balances(_) => true,
            // Allow EVM calls (needed for cross-chain DeFi)
            RuntimeCall::Ethereum(_) => true,
            RuntimeCall::EVM(_) => true,
            // Allow utility batch calls (inner calls filtered separately)
            RuntimeCall::Utility(_) => true,
            // Block governance and privileged calls
            _ => false,
        }
    }
}

Affected Files

  • runtime/moonbeam/src/xcm_config.rs (line 202)
  • runtime/moonriver/src/xcm_config.rs (line 210)
  • runtime/moonbase/src/xcm_config.rs (line 221)

Testing

  • Verify XCM Transact with allowed calls works
  • Verify governance calls are blocked via XCM
  • Verify system.setCode is blocked via XCM
  • Run existing XCM test suite

This PR addresses a security vulnerability reported via Immunefi.


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

Fixes SafeCallFilter that unconditionally accepted ALL runtime calls
via XCM Transact, bypassing security controls.

Vulnerable code (all 3 runtimes):
  fn contains(_call: &RuntimeCall) -> bool {
      // TODO review
      true  // ← accepts everything
  }

Fixed to whitelist only safe operations:
  - Balances (transfers)
  - Ethereum/EVM (cross-chain DeFi)
  - Utility (batch calls)

Blocks privileged calls: governance, system.setCode, etc.

Immunefi submission: https://bugs.immunefi.com/dashboard/submission/81386
Affected: moonbeam, moonriver, moonbase runtimes

Co-authored-by: Claude Code (Anthropic)
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ea017574-91da-454c-bbe0-ead3580f9826

📥 Commits

Reviewing files that changed from the base of the PR and between 19a706e and c2575a1.

📒 Files selected for processing (3)
  • runtime/moonbase/src/xcm_config.rs
  • runtime/moonbeam/src/xcm_config.rs
  • runtime/moonriver/src/xcm_config.rs

📝 Walkthrough

Walkthrough

This PR restricts XCM call safety filtering across three Moonbeam runtime configurations. The SafeCallFilter implementation now explicitly whitelists only Balances, Ethereum, EVM, and Utility runtime calls, rejecting all others, instead of unconditionally permitting all call variants.

Changes

XCM SafeCallFilter Security Restriction

Layer / File(s) Summary
SafeCallFilter whitelist across runtimes
runtime/moonbase/src/xcm_config.rs, runtime/moonbeam/src/xcm_config.rs, runtime/moonriver/src/xcm_config.rs
SafeCallFilter::contains implementation updated identically across all three runtime variants to enforce an explicit allowlist. Only Balances, Ethereum, EVM, and Utility RuntimeCall variants return true; all other call types return false.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: fixing a SafeCallFilter XCM Transact security vulnerability, even including the Immunefi reference number.
Description check ✅ Passed The description thoroughly documents the security vulnerability, its impact, the implemented fix, affected files, and testing requirements - directly related to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@arturgontijo

Copy link
Copy Markdown
Contributor

Hey @ouwibo thanks for the report!

At a first glance I'd say that SafeCallFilter is just one of the security filters/layers we have in the runtimes.
Can you please share a gist/repo with a PoC exploiting this?

Heads up that Polkadot's AssetHub uses this filter:
https://github.com/polkadot-fellows/runtimes/blob/main/system-parachains/asset-hubs/asset-hub-polkadot/src/lib.rs#L248-L261 (allowing everything but one call)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants