Cairo漏洞扫描器Skill cairo-vulnerability-scanner

这个技能专用于扫描和审计Cairo/StarkNet智能合约的安全漏洞,识别包括felt252算术溢出、L1-L2消息传递问题、地址转换问题和签名重放在内的6个关键漏洞。适用于区块链项目的安全审计,帮助开发者在部署前发现和修复安全问题,确保智能合约的安全性。关键词:Cairo,StarkNet,智能合约,安全审计,漏洞扫描,区块链安全。

智能合约 0 次安装 0 次浏览 更新于 3/14/2026

名称:cairo-vulnerability-scanner 描述:扫描Cairo/StarkNet智能合约中的6个关键漏洞,包括felt252算术溢出、L1-L2消息传递问题、地址转换问题和签名重放。用于审计StarkNet项目。

Cairo/StarkNet漏洞扫描器

1. 目的

系统性地扫描StarkNet上的Cairo智能合约,查找与算术、跨层消息传递和加密操作相关的平台特定安全漏洞。此技能编码了Cairo/StarkNet生态系统中6个独特的漏洞模式。

2. 何时使用此技能

  • 审计StarkNet智能合约(Cairo)
  • 审查L1-L2桥接实现
  • StarkNet应用程序的预发布安全评估
  • 验证跨层消息处理
  • 审查签名验证逻辑
  • 评估L1处理函数

3. 平台检测

文件扩展名和指示器

  • Cairo文件.cairo

语言/框架标记

// Cairo合约指示器
#[contract]
mod MyContract {
    use starknet::ContractAddress;

    #[storage]
    struct Storage {
        balance: LegacyMap<ContractAddress, felt252>,
    }

    #[external(v0)]
    fn transfer(ref self: ContractState, to: ContractAddress, amount: felt252) {
        // 合约逻辑
    }

    #[l1_handler]
    fn handle_deposit(ref self: ContractState, from_address: felt252, amount: u256) {
        // L1消息处理器
    }
}

// 常见模式
felt252, u128, u256
ContractAddress, EthAddress
#[external(v0)], #[l1_handler], #[constructor]
get_caller_address(), get_contract_address()
send_message_to_l1_syscall

项目结构

  • src/contract.cairo - 主合约实现
  • src/lib.cairo - 库模块
  • tests/ - 合约测试
  • Scarb.toml - Cairo项目配置

工具支持

  • Caracal:Trail of Bits的Cairo静态分析器
  • 安装:pip install caracal
  • 使用:caracal detect src/
  • cairo-test:内置测试框架
  • Starknet Foundry:测试和开发工具包

4. 这个技能如何工作

调用时,我将:

  1. 搜索您的代码库中的Cairo文件
  2. 分析每个合约以查找6个漏洞模式
  3. 报告发现,包含文件引用和严重性
  4. 为每个识别的问题提供修复方案
  5. 检查L1-L2交互以查找消息传递漏洞

5. 示例输出

当发现漏洞时,您会得到类似这样的报告:

=== CAIRO/STARKNET漏洞扫描结果 ===


---

## 5. 漏洞模式(6个模式)

我检查Cairo/Starknet中6个独特的漏洞模式。有关详细检测模式、代码示例、缓解措施和测试策略,请参阅[VULNERABILITY_PATTERNS.md](resources/VULNERABILITY_PATTERNS.md)。

### 模式摘要:

1. **未检查的算术** ⚠️ 关键 - felt252中的整数溢出/下溢
2. **存储冲突** ⚠️ 关键 - 冲突的存储变量哈希
3. **缺少访问控制** ⚠️ 关键 - 敏感函数上没有调用者验证
4. **不正确的Felt252边界** ⚠️ 高 - 未验证felt252范围
5. **未验证的合约地址** ⚠️ 高 - 使用不受信任的合约地址
6. **缺少调用者验证** ⚠️ 关键 - 没有get_caller_address()检查

有关完整的漏洞模式及代码示例,请参阅[VULNERABILITY_PATTERNS.md](resources/VULNERABILITY_PATTERNS.md)。
## 5. 扫描工作流程

### 步骤1:平台识别
1. 验证Cairo语言和StarkNet框架
2. 检查Cairo版本(Cairo 1.0+ 与旧版Cairo 0)
3. 定位合约文件(`src/*.cairo`)
4. 识别L1-L2桥接合约(如适用)

### 步骤2:算术安全扫描
```bash
# 在算术中查找felt252使用
rg "felt252" src/ | rg "[-+*/]"

# 查找使用felt252的余额/金额存储
rg "felt252" src/ | rg "balance|amount|total|supply"

# 应优先使用u128、u256

步骤3:L1处理器分析

对于每个#[l1_handler]函数:

  • [ ] 验证from_address参数
  • [ ] 检查地址不等于零
  • [ ] 有适当的访问控制
  • [ ] 发出事件以进行监控

步骤4:签名验证审查

对于基于签名的函数:

  • [ ] 包括nonce跟踪
  • [ ] 使用后增加nonce
  • [ ] 域分隔符包括链ID和合约地址
  • [ ] 无法重放签名

步骤5:L1-L2桥接审计

如果合约包括桥接功能:

  • [ ] L1验证地址 < STARKNET_FIELD_PRIME
  • [ ] L1实现消息取消
  • [ ] L2在处理器中验证from_address
  • [ ] L1 ↔ L2的对称访问控制
  • [ ] 测试完整往返流程

步骤6:使用Caracal进行静态分析

# 运行Caracal检测器
caracal detect src/

# 特定检测器
caracal detect src/ --detectors unchecked-felt252-arithmetic
caracal detect src/ --detectors unchecked-l1-handler-from
caracal detect src/ --detectors missing-nonce-validation

6. 报告格式

发现模板

## [关键] L1处理器中未检查的from_address

**位置**:`src/bridge.cairo:145-155`(handle_deposit函数)

**描述**:
`handle_deposit` L1处理器函数未验证`from_address`参数。任何L1合约都可以向此函数发送消息,并为任意用户铸造代币,绕过预期的L1桥接访问控制。

**漏洞代码**:
```rust
// bridge.cairo, line 145
#[l1_handler]
fn handle_deposit(
    ref self: ContractState,
    from_address: felt252,  // 未验证!
    user: ContractAddress,
    amount: u256
) {
    let current_balance = self.balances.read(user);
    self.balances.write(user, current_balance + amount);
}

攻击场景

  1. 攻击者部署恶意L1合约
  2. 恶意合约调用starknetCore.sendMessageToL2(l2Contract, selector, [attacker_address, 1000000])
  3. L2处理器处理消息而不检查发送者
  4. 攻击者在未存入任何资金的情况下收到1,000,000代币
  5. 协议遭受无限铸造漏洞

建议: 验证from_address与授权的L1桥接地址:

#[l1_handler]
fn handle_deposit(
    ref self: ContractState,
    from_address: felt252,
    user: ContractAddress,
    amount: u256
) {
    // 验证L1发送者
    let authorized_l1_bridge = self.l1_bridge_address.read();
    assert(from_address == authorized_l1_bridge, '未经授权的L1发送者');

    let current_balance = self.balances.read(user);
    self.balances.write(user, current_balance + amount);
}

参考

  • building-secure-contracts/not-so-smart-contracts/cairo/unchecked_l1_handler_from
  • Caracal检测器:unchecked-l1-handler-from

---

## 7. 优先级指南

### 关键(立即修复)
- L1处理器中未检查的from_address(无限铸造)
- L1-L2地址转换问题(资金到零地址)

### 高(部署前修复)
- Felt252算术溢出/下溢(余额操纵)
- 缺少签名重放保护(重放攻击)
- L1-L2消息失败而无取消(锁定资金)

### 中(审计中处理)
- 过度受限的L1-L2交互(被困资金)

---

## 8. 测试建议

### 单元测试
```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_felt252_overflow() {
        // 测试算术边界情况
    }

    #[test]
    #[should_panic]
    fn test_unauthorized_l1_handler() {
        // 错误的from_address应失败
    }

    #[test]
    fn test_signature_replay_protection() {
        // 同一签名两次应失败
    }
}

集成测试(与L1)

// 测试完整L1-L2流程
#[test]
fn test_deposit_withdraw_roundtrip() {
    // 1. 在L1存款
    // 2. 等待L2处理
    // 3. 验证L2余额
    // 4. 提款到L1
    // 5. 验证L1余额恢复
}

Caracal CI集成

# .github/workflows/security.yml
- name: 运行Caracal
  run: |
    pip install caracal
    caracal detect src/ --fail-on high,critical

9. 额外资源


10. 快速参考清单

在完成Cairo/StarkNet审计前:

算术安全(高)

  • [ ] 没有使用felt252处理余额/金额(使用u128/u256)
  • [ ] 或有felt252算术显式边界检查
  • [ ] 溢出/下溢场景已测试

L1处理器安全(关键)

  • [ ] 所有#[l1_handler]函数都验证from_address
  • [ ] from_address与存储的L1合约地址比较
  • [ ] 不能通过部署替代L1合约绕过

L1-L2消息传递(高)

  • [ ] L1桥接验证地址 < STARKNET_FIELD_PRIME
  • [ ] L1桥接实现消息取消
  • [ ] L2处理器检查from_address
  • [ ] L1 ↔ L2的对称验证规则
  • [ ] 完整往返流程已测试

签名安全(高)

  • [ ] 签名包括nonce跟踪
  • [ ] 每次使用后增加nonce
  • [ ] 域分隔符包括链ID和合约地址
  • [ ] 签名重放已测试并防止
  • [ ] 防止跨链重放

工具使用

  • [ ] Caracal扫描完成,无关键发现
  • [ ] 单元测试覆盖所有漏洞场景
  • [ ] 集成测试验证L1-L2流程
  • [ ] 测试网部署在主线网前测试