substrate-vulnerability-scanner
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSubstrate 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
项目结构
- - Pallet implementations
pallets/*/lib.rs - - Runtime configuration
runtime/lib.rs - - Weight benchmarks
benchmarking.rs - with
Cargo.tomldependenciesframe-*
- - Pallet实现文件
pallets/*/lib.rs - - 运行时配置文件
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:
- Search your codebase for Substrate pallets
- Analyze each pallet for the 7 vulnerability patterns
- Report findings with file references and severity
- Provide fixes for each identified issue
- Check weight calculations and origin validation
调用本工具时,将执行以下步骤:
- 扫描代码库,定位Substrate pallet
- 分析每个pallet,检测7类漏洞模式
- 输出检测结果,包含文件引用和漏洞严重等级
- 提供修复方案,针对每个发现的问题给出建议
- 检查权重计算和源验证逻辑
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:
模式摘要:
-
Arithmetic Overflow ⚠️ CRITICAL
- Direct ,
+,-,*operators wrap in release mode/ - Must use or
checked_*methodssaturating_* - Affects balance/token calculations, reward/fee math
- Direct
-
Don't Panic ⚠️ CRITICAL - DoS
- Panics cause node to stop processing blocks
- No ,
unwrap(), array indexing without bounds checkexpect() - All user input must be validated with
ensure!
-
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
-
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]
-
Unsigned Transaction Validation ⚠️ HIGH
- Insufficient validation allows spam/replay attacks
- Prefer signed transactions
- If unsigned: validate parameters, replay protection, authenticate source
-
Bad Randomness ⚠️ MEDIUM
- vulnerable to collusion
pallet_randomness_collective_flip - Must use BABE randomness ()
pallet_babe::RandomnessFromOneEpochAgo - Use not
random(subject)random_seed()
-
Bad Origin ⚠️ CRITICAL
- allows any user for privileged operations
ensure_signed - Must use or custom origins (ForceOrigin, AdminOrigin)
ensure_root - Origin types must be properly configured in runtime
For complete vulnerability patterns with code examples, see VULNERABILITY_PATTERNS.md.
-
算术溢出 ⚠️ 严重
- 直接使用、
+、-、*运算符在发布模式下会发生溢出换行/ - 必须使用或
checked_*方法saturating_* - 影响余额/代币计算、奖励/手续费逻辑
- 直接使用
-
避免恐慌 ⚠️ 严重 - DoS风险
- 恐慌会导致节点停止处理区块
- 禁止使用、
unwrap(),禁止无边界检查的数组索引expect() - 所有用户输入必须通过验证
ensure!
-
权重与手续费 ⚠️ 严重 - DoS风险
- 权重配置不当会引发垃圾邮件攻击
- 可变成本操作使用固定权重会导致DoS
- 必须使用基准测试框架,为所有输入参数设置边界
-
先验证,后写入 ⚠️ 高风险(适用于v0.9.25之前版本)
- 在v0.9.25之前的版本中,验证前执行存储写入会在错误发生时保留状态变更
- 正确模式:验证 → 写入 → 触发事件
- 升级至v0.9.25+版本,或手动添加属性
#[transactional]
-
未签名交易验证 ⚠️ 高风险
- 验证不足会引发垃圾邮件/重放攻击
- 优先使用签名交易
- 若使用未签名交易:需验证参数、添加重放保护、验证来源合法性
-
随机数不安全 ⚠️ 中风险
- 易受合谋攻击
pallet_randomness_collective_flip - 必须使用BABE随机数()
pallet_babe::RandomnessFromOneEpochAgo - 使用而非
random(subject)random_seed()
-
源验证不当 ⚠️ 严重
- 会允许任意用户执行特权操作
ensure_signed - 必须使用或自定义源(ForceOrigin、AdminOrigin)
ensure_root - 运行时中必须正确配置源类型
如需包含代码示例的完整漏洞模式说明,请查看VULNERABILITY_PATTERNS.md。
6. Scanning Workflow
6. 扫描流程
Step 1: Platform Identification
步骤1:平台识别
- Verify Substrate/FRAME framework usage
- Check Substrate version (v0.9.25+ has transactional storage)
- Locate pallet implementations ()
pallets/*/lib.rs - Identify runtime configuration ()
runtime/lib.rs
- 确认使用Substrate/FRAME框架
- 检查Substrate版本(v0.9.25+支持事务性存储)
- 定位pallet实现文件()
pallets/*/lib.rs - 识别运行时配置文件()
runtime/lib.rs
Step 2: Dispatchable Analysis
步骤2:可调度函数分析
For each function:
#[pallet::call]- 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
undefinedbash
undefinedSearch 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/
undefinedrg "unwrap()" pallets/
rg "expect(" pallets/
rg "[.*]" pallets/ # Array indexing
rg " as u\d+" pallets/ # Type casts
rg ".unwrap_or" pallets/
undefinedStep 4: Arithmetic Safety Check
步骤4:算术安全检查
bash
undefinedbash
undefinedFind 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/
undefinedrg "checked_add|checked_sub|checked_mul|checked_div" pallets/
rg "saturating_add|saturating_sub|saturating_mul" pallets/
undefinedStep 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
undefinedbash
undefinedFind 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/
undefinedrg "ensure_root|ForceOrigin|AdminOrigin" pallets/
undefinedStep 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
undefinedbash
undefinedRun 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
--chain dev
--pallet pallet_example
--extrinsic "*"
--steps 50
--repeat 20
undefinedcargo build --release --features runtime-benchmarks
./target/release/node benchmark pallet
--chain dev
--pallet pallet_example
--extrinsic "*"
--steps 50
--repeat 20
--chain dev
--pallet pallet_example
--extrinsic "*"
--steps 50
--repeat 20
undefinedtry-runtime
try-runtime测试
bash
undefinedbash
undefinedTest 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
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
on-runtime-upgrade live --uri wss://rpc.polkadot.io
---9. Additional Resources
9. 额外资源
- Building Secure Contracts:
building-secure-contracts/not-so-smart-contracts/substrate/ - Substrate Documentation: https://docs.substrate.io/
- FRAME Documentation: https://paritytech.github.io/substrate/master/frame_support/
- test-fuzz: https://github.com/trailofbits/test-fuzz
- Substrate StackExchange: https://substrate.stackexchange.com/
- 安全合约构建指南:
building-secure-contracts/not-so-smart-contracts/substrate/ - Substrate文档:https://docs.substrate.io/
- FRAME文档:https://paritytech.github.io/substrate/master/frame_support/
- test-fuzz:https://github.com/trailofbits/test-fuzz
- Substrate StackExchange:https://substrate.stackexchange.com/
10. Quick Reference Checklist
10. 快速参考检查清单
Before completing Substrate pallet audit:
Arithmetic Safety (CRITICAL):
- No direct ,
+,-,*operators in dispatchables/ - All arithmetic uses or
checked_*saturating_* - Type conversions use with error handling
try_into()
Panic Prevention (CRITICAL):
- No or
unwrap()in dispatchablesexpect() - 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 or custom origins
ensure_root - only for user-level operations
ensure_signed - 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 not
random(subject)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测试