
AI 技能AI 插件应用安全网络安全AI 评测【免费下载链接】skillsTrail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows项目地址https://gitcode.com/gh_mirrors/skills8/skills点击查看免费下载导读本文深入解析 GitHub 加速计划 skills8 仓库Trail of Bits Claude Code security skills中 rust-review 插件的send-sync-bounds检测 passsend-sync-bounds-finder.md。该 pass 专门定位一类隐蔽的 Rust 线程安全漏洞非Send或非static的值或闭包穿越线程边界时约束没有被编译器强制实施而是被unsafe构造清洗launder掉了。读完本文你将掌握该检测的 Bug shape、双门控判定、误报清单、ripgrep 搜索种子与修复策略并理解它与UNSAFESYNC、STATICMUT等同簇 pass 的边界划分。一、检测目标被 unsafe 清洗掉的线程安全约束Rust 的Send与Sync是两个自动推导auto trait的线程安全标记Send表示类型可以安全地转移到另一个线程Sync表示类型可以安全地被多个线程共享引用。编译器在安全代码中自动推导并强制这些约束——std::thread::spawn、tokio::spawn、rayon::spawn都要求传入的闭包满足F: Send static不满足的代码直接编译失败。send-sync-bounds-finder关注的是那些绕过编译器强制的形态。其核心 Bug shape 是一个非Send或非static的值/闭包穿过了线程边界而该约束没有被强制实施——但不是通过直接的std::thread::spawn/tokio::spawn/rayon::spawn它们本身就要求F: Send static一个忘记写约束的包装器只会编译失败这不算 bug。真正不健全unsound的形态是把约束通过unsafe清洗掉裸thread::Buildermem::transmute处理闭包或生命周期FFI / 自定义线程创建绕过标准库的类型检查std::thread::scope的误用用transmute凭空捏造缺失的Send/Sync约束。而一个裸的、针对非线程安全负载的手动unsafe impl Send/Sync定义则属于UNSAFESYNC不属于本 pass——两者在簇级提示中有明确的 Deconfliction 规则详见下文。二、pass 在 rust-review 中的注册与触发条件send-sync-bounds是 rust-review 插件concurrency-data-race簇concurrency-data-race.md的五个 pass 之一。簇的注册信息位于 prompts/clusters/manifest.json{ cluster_id: concurrency-data-race, consolidated: false, gate: has_concurrency, passes: [ { bug_class: atomic-race, prefix: ATOMICRACE, prompt: prompts/general/atomic-race-finder.md }, { bug_class: unsafe-sync-impl, prefix: UNSAFESYNC, prompt: prompts/general/unsafe-sync-impl-finder.md, requires: [has_unsafe] }, { bug_class: send-sync-bounds, prefix: SENDSYNCBOUND,prompt: prompts/general/send-sync-bounds-finder.md }, { bug_class: shared-memory-race, prefix: SHMRACE, prompt: prompts/general/shared-memory-race-finder.md }, { bug_class: static-mut-race, prefix: STATICMUT, prompt: prompts/general/static-mut-race-finder.md, requires: [has_unsafe] } ] }关键信息Finding ID 前缀SENDSYNCBOUND与ATOMICRACE、UNSAFESYNC、SHMRACE、STATICMUT并列。簇门控gate: has_concurrency——当 Phase 1 能力探测确认审计范围内存在并发相关代码std::thread、Atomic*、static mut、UnsafeCell、unsafe impl Send/Sync、mmap 共享内存、信号处理等具体见 SKILL.md 中的探测正则时该簇才被选中。无requires约束与同簇的UNSAFESYNCrequires: [has_unsafe]和STATICMUT同样需要has_unsafe不同send-sync-bounds没有额外的requires字段——只要has_concurrencytrue就会运行。这一点有测试用例佐证。scripts/test_gating.py 中test_data_race_unsafe_passes_filtered断言当has_concurrencytrue, has_unsafefalse时concurrency-data-race簇仍然被选中且SENDSYNCBOUND、ATOMICRACE、SHMRACE都在 pass 列表中只有UNSAFESYNC与STATICMUT被过滤掉。这背后的逻辑是Send/Sync边界清洗虽然常与unsafe代码相伴但其检查点spawn 原语、transmute 调用在代码中并不一定以unsafe关键字形式出现因此不需要用has_unsafe门控。该 pass 在 SARIF 导出中的简短描述为Missing or incorrect Send or Sync bounds见 scripts/generate_sarif.py可作为对SENDSYNCBOUND发现项的一行概括。三、Bug shape 详解哪些形态真正不健全按文档send-sync-bounds-finder.md的分类本 pass 只处理通过 unsafe 清洗缺失约束的形态可以归纳为四类裸thread::Buildermem::transmute用thread::Builder::new().spawn(...)替代thread::spawn后者强制Send static再通过transmute把闭包或生命周期改成可发送/可 static 的类型。类型检查被transmute整体绕过原类型的!Send约束随之失效。FFI / 自定义线程创建通过extern C或自定义的线程库接口把闭包指针传给其他线程Rust 编译器无法对 FFI 边界做Send/Sync检查。std::thread::scope误用scoped 线程允许借用非static数据若使用不当如把本应在 scope 内使用的引用/闭包通过 unsafe 手段送出 scope 生命周期则static约束被破坏。transmute捏造约束用mem::transmute把非Send/非Sync类型直接改写成携带这些约束的类型凭空制造缺失的 bound。判断的核心原则是约束是否真的没有被强制代码之所以能编译仅仅是因为某个unsafe构造绕过了它。而直接的std::thread::spawn/tokio::spawn/rayon::spawn自身不可能是漏洞点——它强制Send static因此任何能在它周围编译通过的代码其实已经携带了该约束。四、双门控判定两个 Gate 必须同时满足文档明确了两个必须同时成立的 GateGate 1 —— 存在 unsafe 清洗路径。一个值/闭包通过以下方式到达线程或通道边界unsafespawn 原语裸thread::Buildertransmute、FFI 线程创建、scoped 线程误用或一个捏造缺失Send/Sync约束的transmute。注意手动unsafe impl Send/Sync的定义是UNSAFESYNC的事不要为 impl 本身提交SENDSYNCBOUND发现项下方搜索正则找到 impl 的唯一目的是追踪是否存在其他unsafe 清洗路径把它的值带过了线程。Gate 2 —— 缺失的约束确实未被 sink 强制。代码能编译仅仅是因为 unsafe 构造绕过了它。如果 sink 本身就是std::thread::spawn这类强制Send static的原语则不存在不健全性因为能编译就意味着约束已经满足。两个 Gate 的关系是AND只找到 unsafe 构造但没有确认约束未被强制或只发现约束缺失但没有确认清洗路径都不能提交SENDSYNCBOUND发现项。五、误报FPs清单哪些场景不该提交文档明确列出的三个 FP 场景在实际审计中非常常见标准 spawn 的包装器忘记显式写Send约束一个包裹裸std::thread::spawn/tokio::spawn/rayon::spawn的包装器省略了显式Sendbound——如果约束不成立它根本无法编译所以没有 bug。线程本地执行器thread-local executortokio::task::spawn_local这类不需要Send的场景。内部 trait 约束已隐含Send例如T: FutureOutput: Send Send这类写法Send已经由外部约束保证不构成缺失。判断 FP 的核心思路与 Gate 2 一脉相承只要约束最终是由编译器强制的无论它被显式写出、被推导出来还是被包装器忘记都不构成SENDSYNCBOUND漏洞——真正的问题永远出在 unsafe 清洗路径上。六、搜索模式Search seeds用 ripgrep 定位候选点文档为审计 worker 提供了一组 ripgrep 语法\s、\d、\b、\w的搜索种子用于在审计范围内定位候选点\bspawn\s*[(] FnOnce|FnMut|Fn\b where|:\s*Send unsafe\simpl\b.*\b(Send|Sync)\b|thread::Builder|\btransmute\b|thread::scope从源码结构看这些种子的设计意图如下第一行匹配所有spawn调用含thread::Builder::spawn、std::thread::spawn、tokio::spawn等作为穿越线程边界的锚点第二、三行匹配闭包 trait 约束FnOnce/FnMut/Fn与where子句 /: Send写法用于确认约束是否被显式声明第四行同时覆盖四类清洗路径的关键词unsafe impl ... Send/Sync用于追踪而非直接作为发现点、thread::Builder裸 Builder spawn、transmute约束捏造、thread::scopescoped 线程误用。worker 在运行该 pass 时应通过Bash调用rg执行这些种子详见 rust-review-worker.md 的Search withrg规则rg缺失时需显式降级为grep -E并转换字符类绝不能让\s被某些 grep 静默当作字面量s而返回假空结果。命中后用Read逐一验证确认值确实跨过线程边界、确认约束确实未被强制、排除上述 FP 场景。七、同簇 Deconfliction与 UNSAFESYNC 等 pass 的边界concurrency-data-race簇的五个 pass 覆盖数据竞争的多个层面簇级提示concurrency-data-race.md明确定义了彼此的去重Deconfliction规则UNSAFESYNCvsSENDSYNCBOUND与本 pass 最相关手动unsafe impl Send/Sync的定义针对非线程安全负载属于UNSAFESYNCSENDSYNCBOUND只在不存在的约束被unsafe spawn 原语 / transmute 清洗跨线程时提交不由手动 impl 本身触发。当同一个unsafe impl Send for W {}既存在又让它的值跨过线程时在 impl 位置提交UNSAFESYNC不要为同一个 impl 重复提交SENDSYNCBOUND。STATICMUTvsUNSAFESYNCstatic mut竞争不会被包装器上不健全的Syncimpl 修复优先在static mut位置提交STATICMUT。STATICMUTvsATOMICRACE无同步的static mut或对其的裸访问vs 错误的Atomic*排序不同位置可同时提交两者。SHMRACEvsSTATICMUT跨进程 mmap vs 进程内static mut信任边界不同。与SENDSYNCBOUND最需要警惕的是第一条发现unsafe impl Send时先判断它本身是否是漏洞若是归UNSAFESYNC再判断是否有其他unsafe 清洗路径利用了它跨线程传递这才是SENDSYNCBOUND的切入点。姊妹 pass unsafe-sync-impl-finder.md 对UNSAFESYNC的判定有更详细的展开非线程安全字段、self内部变更、// SAFETY:注释不足以证明健全性等可作为交叉参考。八、修复建议Patch恢复编译期强制文档给出的修复方向清晰且可操作传播约束在包装器上显式传播 Send static让约束重新被编译器强制。这是首选修复——直接消除约束缺失这一根本原因。替换清洗原语把unsafespawn /transmute清洗路径替换为健全的原语如std::thread::spawn/tokio::spawn/rayon::spawn让Send/Sync在编译期被强制。这样任何不满足约束的负载会直接编译失败而不是在运行时产生数据竞争或未定义行为。区分修复归属如果是手动unsafe impl Send/Sync本身定义错误则在UNSAFESYNC下修复移除手动 impl 让类型保持!Send/!Sync或使负载真正线程安全而不是本 pass。修复的最终目标是把线程安全责任交还给编译器非Send数据不应无声地跨线程流动static借用不应被 unsafe 手段送出生命周期。九、发现项在审计流水线中的流转SENDSYNCBOUND发现项并不是终稿它会经历 rust-review 的三阶段流水线架构详见 SKILL.mdWorker 阶段运行concurrency-data-race簇的 worker 按 manifest.json 的顺序执行ATOMICRACE→UNSAFESYNC→SENDSYNCBOUND→SHMRACE→STATICMUT确认的 bug 写入findings/SENDSYNCBOUND-NNN.mdYAML frontmatter 含id、bug_class: send-sync-bounds、location、function、confidence、worker并在 coverage 文件中记录filed:或cleared状态。Dedup 阶段rust-review-dedup-judge按(path, line, bug_class)等键合并重复项并处理与同簇其他 pass 的交叉重复。FP Severity 阶段rust-review-fp-judge为每个主发现项分配fp_verdictTRUE_POSITIVE / LIKELY_TP / LIKELY_FP / FALSE_POSITIVE / OUT_OF_SCOPE与severity/attack_vector/exploitability最终汇入REPORT.md与REPORT.sarif。这意味着审计中发现的SENDSYNCBOUND候选会经过误报裁决与严重性评级最终以标准化的 SARIF 格式输出便于接入现有安全工具链。结语send-sync-bounds-finder是 rust-review 并发数据竞争簇中一个定位精准的检测 pass它不重复编译器已经完成的工作标准 spawn 的约束强制而是聚焦于unsafe清洗路径——thread::Buildertransmute、FFI 线程创建、scoped 线程误用、约束捏造——这些让Send/Sync/static约束形同虚设的构造。掌握它的 Bug shape、双 Gate 判定与同簇 Deconfliction 规则就能在 Rust 安全审计中准确识别这类被编译器检查网漏掉的线程安全漏洞并将修复锚定在恢复编译期强制这一正确方向上。赞分享AI 技能AI 插件应用安全网络安全AI 评测【免费下载链接】skillsTrail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows项目地址https://gitcode.com/gh_mirrors/skills8/skills点击查看免费下载相关推荐深入 Rust 无畏并发Fearless Concurrency线程、消息传递、共享状态与 Send/Sync 完整指南深入 Rust 无畏并发Fearless Concurrency线程、消息传递、共享状态与 Send/Sync 完整指南 并发与并行正在成为所有程序的核心教程文档Rust By Example 深入解析Unsafe Rust 的五大使用场景与安全边界Rust By Example 深入解析Unsafe Rust 的五大使用场景与安全边界 在 Rust 中 unsafe 是绕过编译器安全检查、把正确性责任文档教程CSDN博客下载器5分钟学会免费下载CSDN技术文章的终极指南CSDN博客下载器5分钟学会免费下载CSDN技术文章的终极指南 你是否曾经遇到过这样的情况在网上找到一篇优质的CSDN技术文章想要保存下来离线阅读却只能网页爬虫桌面应用上一篇dynamic-datasource多模块依赖版本属性统一终极指南下一篇webpack 命名 Chunk 实战解析同名代码分割点如何合并、Named Chunk 如何生成与输出examples/named-chunks 源码级拆解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考