Skip to content

[RWF] asset-hub-westend: NonTransfer incorrectly claims Governance containment #12724

Description

@xlc

Summary

NonTransfer declares itself a superset of Governance while its filter explicitly denies
Treasury, ConvictionVoting, Referenda, and Whitelist calls that Governance accepts.
pallet_proxy trusts is_superset when authorizing proxy creation, so a NonTransfer
proxy can add a Governance proxy and expand its effective permissions.

This finding was found by Runtime Whitebox Fuzzer.

Severity / Sensitivity

Medium severity, non-sensitive. Asset Hub Westend is a testnet runtime, so this proxy-lattice defect is suitable for a public issue.

Source Evidence

  • cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs:832-847: NonTransfer denies governance call families.
  • cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs:936-943: Governance accepts those call families.
  • cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs:989-996: NonTransfer claims Governance as a subset.
  • substrate/frame/proxy/src/lib.rs:1005-1023: proxy management relies on is_superset for authorization.

PoC Unit Test

Place this in
cumulus/parachains/runtimes/assets/asset-hub-westend/src/generated_tests.rs
and declare #[cfg(test)] mod generated_tests; from lib.rs if needed.

use super::*;
use frame_support::traits::InstanceFilter;

// RWF-INVARIANTS: inv_unbsyysa
// RWF-RISKS: risk_prf8tjaf
#[ignore]
#[test]
fn test_prf8tjaf_lattice_superset_consistency() {
	let governance_call = RuntimeCall::Treasury(
		pallet_treasury::Call::<Runtime>::void_spend { index: 0u32 },
	);
	assert!(
		ProxyType::NonTransfer.is_superset(&ProxyType::Governance),
		"NonTransfer is declared a superset of Governance"
	);
	assert!(
		ProxyType::Governance.filter(&governance_call),
		"Governance must accept Treasury::void_spend"
	);
	assert!(
		ProxyType::NonTransfer.filter(&governance_call),
		"Lattice violated: NonTransfer claims to cover Governance but rejects Treasury::void_spend"
	);
}

Reproduction Command

cargo test -p asset-hub-westend-runtime \
  generated_tests::test_prf8tjaf_lattice_superset_consistency \
  -- --ignored --exact --nocapture

Observed Result

panicked at cumulus/parachains/runtimes/assets/asset-hub-westend/src/generated_tests.rs:20:5:
Lattice violated: NonTransfer claims to cover Governance but rejects Treasury::void_spend

Expected Behavior

The effective filter must contain every call admitted by a declared subset, or the
is_superset relation must return false. Asset Hub Westend is a testnet runtime, so
route this as a non-sensitive public issue to paritytech/polkadot-sdk.

Likely Fix Direction

Either make NonTransfer.filter contain all Governance-admitted calls or make NonTransfer.is_superset(&Governance) return false.

RWF Metadata

  • Found by Runtime Whitebox Fuzzer

  • Finding: find_hfsh4vguwx

  • Target: asset-hub-westend-runtime

  • Severity: medium

  • Category: access control

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions