substrate-vulnerability-scanner

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Substrate Vulnerability Scanner

Substrate漏洞扫描器

1. Purpose

1. 用途

Systematically scan Substrate runtime modules (pallets) for platform-specific security vulnerabilities that can cause node crashes, DoS attacks, or unauthorized access. This skill encodes 7 critical vulnerability patterns unique to Substrate/FRAME-based chains.
系统性扫描Substrate运行时模块(pallet)中特定于平台的安全漏洞,这些漏洞可能导致节点崩溃、DoS攻击或未授权访问。本工具涵盖了7种Substrate/FRAME链特有的严重漏洞模式。

2. When to Use This Skill

2. 使用场景

  • Auditing custom Substrate pallets
  • Reviewing FRAME runtime code
  • Pre-launch security assessment of Substrate chains (Polkadot parachains, standalone chains)
  • Validating dispatchable extrinsic functions
  • Reviewing weight calculation functions
  • Assessing unsigned transaction validation logic
  • 审计自定义Substrate pallet
  • 审查FRAME运行时代码
  • Substrate链(Polkadot平行链、独立链)上线前的安全评估
  • 验证可调度外部函数
  • 审查权重计算函数
  • 评估未签名交易验证逻辑

3. Platform Detection

3. 平台识别

File Extensions & Indicators

文件扩展名与识别标识

  • Rust files:
    .rs
  • Rust文件
    .rs

Language/Framework Markers

语言/框架标识

rust
// Substrate/FRAME indicators
#[pallet]
pub mod pallet {
    use frame_support::pallet_prelude::*;
    use frame_system::pallet_prelude::*;

    #[pallet::config]
    pub trait Config: frame_system::Config { }

    #[pallet::call]
    impl<T: Config> Pallet<T> {
        #[pallet::weight(10_000)]
        pub fn example_function(origin: OriginFor<T>) -> DispatchResult { }
    }
}

// Common patterns
DispatchResult, DispatchError
ensure!, ensure_signed, ensure_root
StorageValue, StorageMap, StorageDoubleMap
#[pallet::storage]
#[pallet::call]
#[pallet::weight]
#[pallet::validate_unsigned]
rust
// Substrate/FRAME indicators
#[pallet]
pub mod pallet {
    use frame_support::pallet_prelude::*;
    use frame_system::pallet_prelude::*;

    #[pallet::config]
    pub trait Config: frame_system::Config { }

    #[pallet::call]
    impl<T: Config> Pallet<T> {
        #[pallet::weight(10_000)]
        pub fn example_function(origin: OriginFor<T>) -> DispatchResult { }
    }
}

// Common patterns
DispatchResult, DispatchError
ensure!, ensure_signed, ensure_root
StorageValue, StorageMap, StorageDoubleMap
#[pallet::storage]
#[pallet::call]
#[pallet::weight]
#[pallet::validate_unsigned]

Project Structure

项目结构

  • pallets/*/lib.rs
    - Pallet implementations
  • runtime/lib.rs
    - Runtime configuration
  • benchmarking.rs
    - Weight benchmarks
  • Cargo.toml
    with
    frame-*
    dependencies
  • pallets/*/lib.rs
    - Pallet实现文件
  • runtime/lib.rs
    - 运行时配置文件
  • benchmarking.rs
    - 权重基准测试文件
  • 包含
    frame-*
    依赖的
    Cargo.toml

Tool Support

工具支持

  • cargo-fuzz: Fuzz testing for Rust
  • test-fuzz: Property-based testing framework
  • benchmarking framework: Built-in weight calculation
  • try-runtime: Runtime migration testing

  • cargo-fuzz:Rust模糊测试工具
  • test-fuzz:基于属性的测试框架
  • 基准测试框架:内置权重计算工具
  • try-runtime:运行时迁移测试工具

4. How This Skill Works

4. 工作原理

When invoked, I will:
  1. Search your codebase for Substrate pallets
  2. Analyze each pallet for the 7 vulnerability patterns
  3. Report findings with file references and severity
  4. Provide fixes for each identified issue
  5. Check weight calculations and origin validation

调用本工具时,将执行以下步骤:
  1. 扫描代码库,定位Substrate pallet
  2. 分析每个pallet,检测7类漏洞模式
  3. 输出检测结果,包含文件引用和漏洞严重等级
  4. 提供修复方案,针对每个发现的问题给出建议
  5. 检查权重计算和源验证逻辑

5. Vulnerability Patterns (7 Critical Patterns)

5. 漏洞模式(7类严重模式)

I check for 7 critical vulnerability patterns unique to Substrate/FRAME. For detailed detection patterns, code examples, mitigations, and testing strategies, see VULNERABILITY_PATTERNS.md.
本工具检测7种Substrate/FRAME特有的严重漏洞模式。如需详细的检测模式、代码示例、缓解措施和测试策略,请查看VULNERABILITY_PATTERNS.md

Pattern Summary:

模式摘要:

  1. Arithmetic Overflow ⚠️ CRITICAL
    • Direct
      +
      ,
      -
      ,
      *
      ,
      /
      operators wrap in release mode
    • Must use
      checked_*
      or
      saturating_*
      methods
    • Affects balance/token calculations, reward/fee math
  2. Don't Panic ⚠️ CRITICAL - DoS
    • Panics cause node to stop processing blocks
    • No
      unwrap()
      ,
      expect()
      , array indexing without bounds check
    • All user input must be validated with
      ensure!
  3. Weights and Fees ⚠️ CRITICAL - DoS
    • Incorrect weights allow spam attacks
    • Fixed weights for variable-cost operations enable DoS
    • Must use benchmarking framework, bound all input parameters
  4. Verify First, Write Last ⚠️ HIGH (Pre-v0.9.25)
    • Storage writes before validation persist on error (pre-v0.9.25)
    • Pattern: validate → write → emit event
    • Upgrade to v0.9.25+ or use manual
      #[transactional]
  5. Unsigned Transaction Validation ⚠️ HIGH
    • Insufficient validation allows spam/replay attacks
    • Prefer signed transactions
    • If unsigned: validate parameters, replay protection, authenticate source
  6. Bad Randomness ⚠️ MEDIUM
    • pallet_randomness_collective_flip
      vulnerable to collusion
    • Must use BABE randomness (
      pallet_babe::RandomnessFromOneEpochAgo
      )
    • Use
      random(subject)
      not
      random_seed()
  7. Bad Origin ⚠️ CRITICAL
    • ensure_signed
      allows any user for privileged operations
    • Must use
      ensure_root
      or custom origins (ForceOrigin, AdminOrigin)
    • Origin types must be properly configured in runtime
For complete vulnerability patterns with code examples, see VULNERABILITY_PATTERNS.md.

  1. 算术溢出 ⚠️ 严重
    • 直接使用
      +
      -
      *
      /
      运算符在发布模式下会发生溢出换行
    • 必须使用
      checked_*
      saturating_*
      方法
    • 影响余额/代币计算、奖励/手续费逻辑
  2. 避免恐慌 ⚠️ 严重 - DoS风险
    • 恐慌会导致节点停止处理区块
    • 禁止使用
      unwrap()
      expect()
      ,禁止无边界检查的数组索引
    • 所有用户输入必须通过
      ensure!
      验证
  3. 权重与手续费 ⚠️ 严重 - DoS风险
    • 权重配置不当会引发垃圾邮件攻击
    • 可变成本操作使用固定权重会导致DoS
    • 必须使用基准测试框架,为所有输入参数设置边界
  4. 先验证,后写入 ⚠️ 高风险(适用于v0.9.25之前版本)
    • 在v0.9.25之前的版本中,验证前执行存储写入会在错误发生时保留状态变更
    • 正确模式:验证 → 写入 → 触发事件
    • 升级至v0.9.25+版本,或手动添加
      #[transactional]
      属性
  5. 未签名交易验证 ⚠️ 高风险
    • 验证不足会引发垃圾邮件/重放攻击
    • 优先使用签名交易
    • 若使用未签名交易:需验证参数、添加重放保护、验证来源合法性
  6. 随机数不安全 ⚠️ 中风险
    • pallet_randomness_collective_flip
      易受合谋攻击
    • 必须使用BABE随机数(
      pallet_babe::RandomnessFromOneEpochAgo
    • 使用
      random(subject)
      而非
      random_seed()
  7. 源验证不当 ⚠️ 严重
    • ensure_signed
      会允许任意用户执行特权操作
    • 必须使用
      ensure_root
      或自定义源(ForceOrigin、AdminOrigin)
    • 运行时中必须正确配置源类型
如需包含代码示例的完整漏洞模式说明,请查看VULNERABILITY_PATTERNS.md

6. Scanning Workflow

6. 扫描流程

Step 1: Platform Identification

步骤1:平台识别

  1. Verify Substrate/FRAME framework usage
  2. Check Substrate version (v0.9.25+ has transactional storage)
  3. Locate pallet implementations (
    pallets/*/lib.rs
    )
  4. Identify runtime configuration (
    runtime/lib.rs
    )
  1. 确认使用Substrate/FRAME框架
  2. 检查Substrate版本(v0.9.25+支持事务性存储)
  3. 定位pallet实现文件(
    pallets/*/lib.rs
  4. 识别运行时配置文件(
    runtime/lib.rs

Step 2: Dispatchable Analysis

步骤2:可调度函数分析

For each
#[pallet::call]
function:
  • Arithmetic: Uses checked/saturating operations?
  • Panics: No unwrap/expect/indexing?
  • Weights: Proportional to cost, bounded inputs?
  • Origin: Appropriate validation level?
  • Validation: All checks before storage writes?
针对每个
#[pallet::call]
函数:
  • 算术操作:是否使用checked/saturating方法?
  • 恐慌风险:是否无unwrap/expect/无边界索引?
  • 权重配置:是否与成本成比例,是否设置输入边界?
  • 源验证:是否使用合适的验证级别?
  • 验证顺序:是否在存储写入前完成所有检查?

Step 3: Panic Sweep

步骤3:恐慌风险排查

bash
undefined
bash
undefined

Search for panic-prone patterns

Search for panic-prone patterns

rg "unwrap()" pallets/ rg "expect(" pallets/ rg "[.*]" pallets/ # Array indexing rg " as u\d+" pallets/ # Type casts rg ".unwrap_or" pallets/
undefined
rg "unwrap()" pallets/ rg "expect(" pallets/ rg "[.*]" pallets/ # Array indexing rg " as u\d+" pallets/ # Type casts rg ".unwrap_or" pallets/
undefined

Step 4: Arithmetic Safety Check

步骤4:算术安全检查

bash
undefined
bash
undefined

Find direct arithmetic

Find direct arithmetic

rg " + |+=| - |-=| * |*=| / |/=" pallets/
rg " + |+=| - |-=| * |*=| / |/=" pallets/

Should find checked/saturating alternatives instead

Should find checked/saturating alternatives instead

rg "checked_add|checked_sub|checked_mul|checked_div" pallets/ rg "saturating_add|saturating_sub|saturating_mul" pallets/
undefined
rg "checked_add|checked_sub|checked_mul|checked_div" pallets/ rg "saturating_add|saturating_sub|saturating_mul" pallets/
undefined

Step 5: Weight Analysis

步骤5:权重分析

  • Run benchmarking:
    cargo test --features runtime-benchmarks
  • Verify weights match computational cost
  • Check for bounded input parameters
  • Review weight calculation functions
  • 运行基准测试:
    cargo test --features runtime-benchmarks
  • 验证权重与计算成本匹配
  • 检查是否设置输入参数边界
  • 审查权重计算函数

Step 6: Origin & Privilege Review

步骤6:源与权限审查

bash
undefined
bash
undefined

Find privileged operations

Find privileged operations

rg "ensure_signed" pallets/ | grep -E "pause|emergency|admin|force|sudo"
rg "ensure_signed" pallets/ | grep -E "pause|emergency|admin|force|sudo"

Should use ensure_root or custom origins

Should use ensure_root or custom origins

rg "ensure_root|ForceOrigin|AdminOrigin" pallets/
undefined
rg "ensure_root|ForceOrigin|AdminOrigin" pallets/
undefined

Step 7: Testing Review

步骤7:测试审查

  • Unit tests cover all dispatchables
  • Fuzz tests for panic conditions
  • Benchmarks for weight calculation
  • try-runtime tests for migrations

  • 单元测试覆盖所有可调度函数
  • 针对恐慌条件的模糊测试
  • 针对权重计算的基准测试
  • 针对迁移的try-runtime测试

7. Priority Guidelines

7. 优先级指南

Critical (Immediate Fix Required)

严重(需立即修复)

  • Arithmetic overflow (token creation, balance manipulation)
  • Panic DoS (node crash risk)
  • Bad origin (unauthorized privileged operations)
  • 算术溢出(代币创建、余额操作)
  • 恐慌DoS(节点崩溃风险)
  • 源验证不当(未授权特权操作)

High (Fix Before Launch)

高风险(上线前修复)

  • Incorrect weights (DoS via spam)
  • Verify-first violations (state corruption, pre-v0.9.25)
  • Unsigned validation issues (spam, replay attacks)
  • 权重配置错误(垃圾邮件DoS)
  • 先验证后写入规则违反(状态损坏,适用于v0.9.25之前版本)
  • 未签名交易验证问题(垃圾邮件、重放攻击)

Medium (Address in Audit)

中风险(审计阶段处理)

  • Bad randomness (manipulation possible but limited impact)

  • 随机数不安全(存在被操纵可能,但影响有限)

8. Testing Recommendations

8. 测试建议

Fuzz Testing

模糊测试

rust
// Use test-fuzz for property-based testing
#[cfg(test)]
mod tests {
    use test_fuzz::test_fuzz;

    #[test_fuzz]
    fn fuzz_transfer(from: AccountId, to: AccountId, amount: u128) {
        // Should never panic
        let _ = Pallet::transfer(from, to, amount);
    }

    #[test_fuzz]
    fn fuzz_no_panics(call: Call) {
        // No dispatchable should panic
        let _ = call.dispatch(origin);
    }
}
rust
// Use test-fuzz for property-based testing
#[cfg(test)]
mod tests {
    use test_fuzz::test_fuzz;

    #[test_fuzz]
    fn fuzz_transfer(from: AccountId, to: AccountId, amount: u128) {
        // Should never panic
        let _ = Pallet::transfer(from, to, amount);
    }

    #[test_fuzz]
    fn fuzz_no_panics(call: Call) {
        // No dispatchable should panic
        let _ = call.dispatch(origin);
    }
}

Benchmarking

基准测试

bash
undefined
bash
undefined

Run benchmarks to generate weights

Run benchmarks to generate weights

cargo build --release --features runtime-benchmarks ./target/release/node benchmark pallet
--chain dev
--pallet pallet_example
--extrinsic "*"
--steps 50
--repeat 20
undefined
cargo build --release --features runtime-benchmarks ./target/release/node benchmark pallet
--chain dev
--pallet pallet_example
--extrinsic "*"
--steps 50
--repeat 20
undefined

try-runtime

try-runtime测试

bash
undefined
bash
undefined

Test runtime upgrades

Test runtime upgrades

cargo build --release --features try-runtime try-runtime --runtime ./target/release/wbuild/runtime.wasm
on-runtime-upgrade live --uri wss://rpc.polkadot.io

---
cargo build --release --features try-runtime try-runtime --runtime ./target/release/wbuild/runtime.wasm
on-runtime-upgrade live --uri wss://rpc.polkadot.io

---

9. Additional Resources

9. 额外资源



10. Quick Reference Checklist

10. 快速参考检查清单

Before completing Substrate pallet audit:
Arithmetic Safety (CRITICAL):
  • No direct
    +
    ,
    -
    ,
    *
    ,
    /
    operators in dispatchables
  • All arithmetic uses
    checked_*
    or
    saturating_*
  • Type conversions use
    try_into()
    with error handling
Panic Prevention (CRITICAL):
  • No
    unwrap()
    or
    expect()
    in dispatchables
  • No direct array/slice indexing without bounds check
  • All user inputs validated with
    ensure!
  • Division operations check for zero divisor
Weights & DoS (CRITICAL):
  • Weights proportional to computational cost
  • Input parameters have maximum bounds
  • Benchmarking used to determine weights
  • No free (zero-weight) expensive operations
Access Control (CRITICAL):
  • Privileged operations use
    ensure_root
    or custom origins
  • ensure_signed
    only for user-level operations
  • Origin types properly configured in runtime
  • Sudo pallet removed before production
Storage Safety (HIGH):
  • Using Substrate v0.9.25+ OR manual
    #[transactional]
  • Validation before storage writes
  • Events emitted after successful operations
Other (MEDIUM):
  • Unsigned transactions use signed alternative if possible
  • If unsigned: proper validation, replay protection, authentication
  • BABE randomness used (not RandomnessCollectiveFlip)
  • Randomness uses
    random(subject)
    not
    random_seed()
Testing:
  • Unit tests for all dispatchables
  • Fuzz tests to find panics
  • Benchmarks generated and verified
  • try-runtime tests for migrations
完成Substrate pallet审计前,请检查以下内容:
算术安全(严重):
  • 可调度函数中未直接使用
    +
    -
    *
    /
    运算符
  • 所有算术操作使用
    checked_*
    saturating_*
    方法
  • 类型转换使用
    try_into()
    并处理错误
恐慌预防(严重):
  • 可调度函数中未使用
    unwrap()
    expect()
  • 未进行无边界检查的直接数组/切片索引
  • 所有用户输入通过
    ensure!
    验证
  • 除法操作检查除数是否为零
权重与DoS防护(严重):
  • 权重与计算成本成比例
  • 输入参数设置了最大边界
  • 使用基准测试确定权重
  • 不存在免费(零权重)的高成本操作
访问控制(严重):
  • 特权操作使用
    ensure_root
    或自定义源
  • ensure_signed
    仅用于用户级操作
  • 运行时中正确配置了源类型
  • 生产环境前移除Sudo pallet
存储安全(高风险):
  • 使用Substrate v0.9.25+版本,或手动添加
    #[transactional]
    属性
  • 存储写入前完成所有验证
  • 操作成功后触发事件
其他(中风险):
  • 尽可能使用签名交易替代未签名交易
  • 若使用未签名交易:需进行适当验证、添加重放保护、验证来源
  • 使用BABE随机数(而非RandomnessCollectiveFlip)
  • 随机数使用
    random(subject)
    而非
    random_seed()
测试:
  • 所有可调度函数均有单元测试覆盖
  • 针对恐慌条件的模糊测试
  • 已生成并验证基准测试结果
  • 针对迁移的try-runtime测试