ln-628-concurrency-auditor by levnikolaevich/claude-code-skills
npx skills add https://github.com/levnikolaevich/claude-code-skills --skill ln-628-concurrency-auditorPaths: File paths (
shared/,references/,../ln-*) are relative to skills repo root. If not found at CWD, locate this SKILL.md directory and go up one level for repo root. Ifshared/is missing, fetch files via WebFetch fromhttps://raw.githubusercontent.com/levnikolaevich/claude-code-skills/master/skills/{path}.
专门用于审计并发、异步模式和跨进程资源访问的工作器。
必读: 加载 shared/references/audit_worker_core_contract.md。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
接收包含以下内容的 contextStore:tech_stack, best_practices, codebase_root, output_dir。
必读: 加载 shared/references/two_layer_detection.md 了解检测方法。
shared/references/audit_scoring.md{output_dir}/628-concurrency.md(原子性单次写入)统一的严重性升级: 对于所有检查 — 如果发现影响支付/认证/金融代码 → 无论其他因素如何,均升级为严重。
内容: 在单线程异步代码中,跨 await/yield 边界导致共享状态损坏。
第 1 层 — Grep 模式:
| 语言 | 模式 | Grep |
|---|---|---|
| JS/TS | 跨 await 的读-改-写 | \w+\s*[+\-*/]?=\s*.*await (例如,result += await something) |
| JS/TS | 检查-然后-初始化竞争 | if\s*\(!?\w+\) 后跟同一代码块中的 \w+\s*=\s*await |
| Python | 跨 await 的读-改-写 | \w+\s*[+\-*/]?=\s*await 在 async def 内部 |
| Python | 异步中的共享模块级状态 | 模块级 \w+\s*= + 在 async def 内部修改 |
| All | 无锁的共享缓存 | `.set( |
第 2 层 — 关键问题:
严重性: 严重(支付/认证) | 高(面向用户) | 中(后台)
安全模式排除: 局部变量、const 声明、单次使用的 await(不可能交错)。
工作量: 中
内容: 多个线程/goroutine 在没有同步的情况下访问共享可变状态。
第 1 层 — Grep 模式:
| 语言 | 模式 | Grep |
|---|---|---|
| Go | 无互斥锁的 Map 访问 | 结构体中 map\[.*\].*= 且没有 sync.Mutex 或 sync.RWMutex |
| Go | 被 goroutine 捕获的变量 | go func + 修改来自外部作用域的变量 |
| Python | 在线程中修改全局变量 | 同一文件中 global\s+\w+ 在函数内 + threading.Thread |
| Java | 线程间共享的 HashMap | 同一类中 HashMap + `Thread |
| Rust | 多线程上下文中的 Rc | 同一文件中 Rc<RefCell + `thread::spawn |
| Node.js | Worker Threads 共享状态 | `workerData |
第 2 层 — 关键问题:
go func 是按值捕获(安全)还是按引用捕获(不安全)?严重性: 严重(支付/认证) | 高(可能导致数据损坏) | 中(内部)
安全模式排除: Go map 在 goroutine 启动前的 init() 或 main() 中。Rust Arc<Mutex<T>>(已安全)。Java Collections.synchronizedMap()。
工作量: 中
内容: 检查资源状态,然后使用,但状态可能在检查和使用之间发生变化。
第 1 层 — Grep 模式:
| 语言 | 检查 | 使用 | Grep |
|---|---|---|---|
| Python | os.path.exists() | open() | os\.path\.exists\( 靠近同一变量的 open\( |
| Python | os.access() | os.open() | os\.access\( 靠近 `os.open( |
| Node.js | fs.existsSync() | fs.readFileSync() | existsSync\( 靠近 `readFileSync( |
| Node.js | fs.accessSync() | fs.openSync() | accessSync\( 靠近 openSync\( |
| Go | os.Stat() | os.Open() | os\.Stat\( 靠近 `os.Open( |
| Java | .exists() | new FileInputStream | \.exists\(\) 靠近 `new File |
第 2 层 — 关键问题:
严重性: 严重(安全敏感:权限、认证令牌、配置) | 高(面向用户的文件操作) | 中(内部/后台)
安全模式排除: 检查在带有重试的 try/catch 内部。仅用于日志记录/指标。检查 + 使用包装在文件锁中。
工作量: 小-中(用直接使用 + 错误处理替换检查-然后-使用)
内容: 锁获取顺序不一致,或在阻塞操作期间持有锁。
第 1 层 — Grep 模式:
| 语言 | 模式 | Grep |
|---|---|---|
| Python | 嵌套锁 | with\s+\w+_lock: (多行:两个不同的锁嵌套) |
| Python | 循环中的锁 | for.*: 且循环体内有 \.acquire\(\) |
| Python | 锁 + 外部调用 | \.acquire\(\) 后跟 `await |
| Go | 缺少 defer unlock | \.Lock\(\) 下一行没有 defer.*\.Unlock\(\) |
| Go | 嵌套锁 | 同一函数中两次 \.Lock\(\) 调用,中间没有 \.Unlock\(\) |
| Java | 嵌套 synchronized | synchronized\s*\( (多行:嵌套块使用不同的监视器) |
| JS | 异步互斥锁嵌套 | await\s+\w+\.acquire\(\) (同一函数中两个不同的互斥锁) |
第 2 层 — 关键问题:
严重性: 严重(支付/认证) | 高(应用冻结风险)
安全模式排除: 可重入锁(同一锁获取两次)。具有显式超时的锁(asyncio.wait_for, tryLock)。
工作量: 大(锁顺序重新设计)
内容: 在异步函数或事件循环处理程序中进行同步阻塞调用。
第 1 层 — Grep 模式:
| 语言 | 阻塞调用 | Grep | 替代方案 |
|---|---|---|---|
| Python | async def 中的 time.sleep | async def 内部的 time\.sleep | await asyncio.sleep |
| Python | async def 中的 requests.* | async def 内部的 `requests.(get | post |
| Python | async def 中的 open() | async def 内部的 open\( | aiofiles.open |
| Node.js | 异步中的 fs.readFileSync | `fs.readFileSync | fs.writeFileSync |
| Node.js | 异步中的 execSync | 异步处理程序中的 `execSync | spawnSync` |
| Node.js | 异步中的同步加密 | `crypto.pbkdf2Sync | crypto.scryptSync` |
第 2 层 — 关键问题:
严重性: 高(阻塞事件循环/异步上下文) | 中(轻微阻塞 <100ms)
安全模式排除: 阻塞调用在 if __name__ == "__main__" 中(启动)。初始化时配置加载中的 readFileSync。小输入的同步加密。
工作量: 小-中(替换为异步替代方案)
内容: 多个并发访问者竞争同一资源而没有协调。
第 1 层 — Grep 模式:
| 模式 | 风险 | Grep |
|---|---|---|
| 无同步的共享内存 | 数据损坏 | `SharedArrayBuffer |
| 无协调的 IPC | 消息顺序 | 并发循环中的 `process.send |
| 并发文件追加 | 交错写入 | 并行任务对同一路径的多个 `appendFile |
第 2 层 — 关键问题:
O_APPEND)严重性: 高(数据损坏) | 中(顺序问题)
安全模式排除: 单写入者模式。操作系统保证的原子操作(小管道写入、O_APPEND)。具有顺序保证的消息队列。
工作量: 中
内容: 多个进程或进程+操作系统访问同一独占资源,包括对共享操作系统资源具有非明显副作用的操作。
第 1 层 — Grep 入口点:
| 模式 | 风险 | Grep |
|---|---|---|
| 剪贴板双重访问 | 同一流程中的 OSC 52 + 原生剪贴板 | 同一文件中 `osc52 |
| 子进程 + 共享文件 | 父进程和子进程写入同一文件 | `spawn |
| 操作系统独占资源 | Win32 剪贴板、串口、命名管道 | `OpenClipboard |
| 终端转义序列 | stdout 触发终端操作系统访问 | `\x1b\] |
| 外部剪贴板工具 | 通过生成进程的剪贴板 | `pbcopy |
第 2 层 — 此项检查比其他任何检查都更依赖推理:
| 资源 | 独占? | 访问者 1 | 访问者 2 | 存在同步? |
|---|
追踪时间线:
t=0ms operation_A() -> 访问 resource_X t=?ms side_effect -> 外部进程访问 resource_X t=?ms operation_B() -> 再次访问 resource_X -> 冲突?
关键问题:
* 另一个进程(终端、操作系统、子进程)能否同时访问此资源?
* 此操作是否对共享操作系统资源具有不可见的副作用?
* 如果外部进程比预期慢/快会发生什么?
* 如果用户快速触发此操作两次会发生什么?
严重性: 严重(两个访问者访问独占操作系统资源而无同步) | 高(子进程 + 共享文件无锁) | 高(通过推理检测到不可见副作用)
安全模式排除: 单访问者。存在重试/退避模式。操作通过显式延迟/await 排序。
工作量: 中-大(可能需要移除冗余访问路径)
必读: 加载 shared/references/audit_worker_core_contract.md 和 shared/references/audit_scoring.md。
必读: 加载 shared/references/audit_worker_core_contract.md 和 shared/templates/audit_worker_report_template.md。
将报告写入 {output_dir}/628-concurrency.md,其中 category: "Concurrency" 和检查项:async_races, thread_safety, toctou, deadlock_potential, blocking_io, resource_contention, cross_process_races。
返回摘要给协调器:
Report written: docs/project/.audit/ln-620/{YYYY-MM-DD}/628-concurrency.md
Score: X.X/10 | Issues: N (C:N H:N M:N L:N)
必读: 加载 shared/references/audit_worker_core_contract.md。
必读: 加载 shared/references/audit_worker_core_contract.md。
shared/references/audit_scoring.md 计算分数{output_dir}/628-concurrency.md(原子性单次写入调用)shared/references/two_layer_detection.mdshared/references/audit_output_schema.md版本: 4.0.0 最后更新: 2026-03-04
每周安装数
170
仓库
GitHub 星标
262
首次出现
2026年1月24日
安全审计
安装于
claude-code156
cursor152
opencode152
codex151
gemini-cli151
github-copilot144
Paths: File paths (
shared/,references/,../ln-*) are relative to skills repo root. If not found at CWD, locate this SKILL.md directory and go up one level for repo root. Ifshared/is missing, fetch files via WebFetch fromhttps://raw.githubusercontent.com/levnikolaevich/claude-code-skills/master/skills/{path}.
Specialized worker auditing concurrency, async patterns, and cross-process resource access.
MANDATORY READ: Load shared/references/audit_worker_core_contract.md.
Receives contextStore with: tech_stack, best_practices, codebase_root, output_dir.
MANDATORY READ: Load shared/references/two_layer_detection.md for detection methodology.
shared/references/audit_scoring.md{output_dir}/628-concurrency.md (atomic single Write)Unified severity escalation: For ALL checks — if finding affects payment/auth/financial code → escalate to CRITICAL regardless of other factors.
What: Shared state corrupted across await/yield boundaries in single-threaded async code.
Layer 1 — Grep patterns:
| Language | Pattern | Grep |
|---|---|---|
| JS/TS | Read-modify-write across await | \w+\s*[+\-*/]?=\s*.*await (e.g., result += await something) |
| JS/TS | Check-then-initialize race | if\s*\(!?\w+\) followed by \w+\s*=\s*await in same block |
| Python | Read-modify-write across await | \w+\s*[+\-*/]?=\s*await inside async def |
| Python |
Layer 2 — Critical questions:
Severity: CRITICAL (payment/auth) | HIGH (user-facing) | MEDIUM (background)
Safe pattern exclusions: Local variables, const declarations, single-use await (no interleaving possible).
Effort: M
What: Shared mutable state accessed from multiple threads/goroutines without synchronization.
Layer 1 — Grep patterns:
| Language | Pattern | Grep |
|---|---|---|
| Go | Map access without mutex | map\[.*\].*= in struct without sync.Mutex or sync.RWMutex |
| Go | Variable captured by goroutine | go func + variable from outer scope modified |
| Python | Global modified in threads | global\s+\w+ in function + threading.Thread in same file |
| Java | HashMap shared between threads |
Layer 2 — Critical questions:
go func capturing by value (safe) or by reference (unsafe)?Severity: CRITICAL (payment/auth) | HIGH (data corruption possible) | MEDIUM (internal)
Safe pattern exclusions: Go map in init() or main() before goroutines start. Rust Arc<Mutex<T>> (already safe). Java Collections.synchronizedMap().
Effort: M
What: Resource state checked, then used, but state can change between check and use.
Layer 1 — Grep patterns:
| Language | Check | Use | Grep |
|---|---|---|---|
| Python | os.path.exists() | open() | os\.path\.exists\( near open\( on same variable |
| Python | os.access() | os.open() | os\.access\( near `os.open( |
Layer 2 — Critical questions:
Severity: CRITICAL (security-sensitive: permissions, auth tokens, configs) | HIGH (user-facing file ops) | MEDIUM (internal/background)
Safe pattern exclusions: Check inside try/catch with retry. Check for logging/metrics only. Check + use wrapped in file lock.
Effort: S-M (replace check-then-use with direct use + error handling)
What: Lock acquisition in inconsistent order, or lock held during blocking operation.
Layer 1 — Grep patterns:
| Language | Pattern | Grep |
|---|---|---|
| Python | Nested locks | with\s+\w+_lock: (multiline: two different locks nested) |
| Python | Lock in loop | for.*: with \.acquire\(\) inside loop body |
| Python | Lock + external call | \.acquire\(\) followed by `await |
| Go | Missing defer unlock | \.Lock\(\) without defer.*\.Unlock\(\) on next line |
Layer 2 — Critical questions:
Severity: CRITICAL (payment/auth) | HIGH (app freeze risk)
Safe pattern exclusions: Reentrant locks (same lock acquired twice). Locks with explicit timeout (asyncio.wait_for, tryLock).
Effort: L (lock ordering redesign)
What: Synchronous blocking calls inside async functions or event loop handlers.
Layer 1 — Grep patterns:
| Language | Blocking Call | Grep | Replacement |
|---|---|---|---|
| Python | time.sleep in async def | time\.sleep inside async def | await asyncio.sleep |
| Python | requests.* in async def | `requests.(get | post |
| Python | open() in async def | inside |
Layer 2 — Critical questions:
Severity: HIGH (blocks event loop/async context) | MEDIUM (minor blocking <100ms)
Safe pattern exclusions: Blocking call in if __name__ == "__main__" (startup). readFileSync in config loading at init time. Sync crypto for small inputs.
Effort: S-M (replace with async alternative)
What: Multiple concurrent accessors compete for same resource without coordination.
Layer 1 — Grep patterns:
| Pattern | Risk | Grep |
|---|---|---|
| Shared memory without sync | Data corruption | `SharedArrayBuffer |
| IPC without coordination | Message ordering | `process.send |
| Concurrent file append | Interleaved writes | Multiple `appendFile |
Layer 2 — Critical questions:
O_APPEND for small writes)Severity: HIGH (data corruption) | MEDIUM (ordering issues)
Safe pattern exclusions: Single writer pattern. OS-guaranteed atomic operations (small pipe writes, O_APPEND). Message queues with ordering guarantees.
Effort: M
What: Multiple processes or process+OS accessing same exclusive resource, including operations with non-obvious side effects on shared OS resources.
Layer 1 — Grep entry points:
| Pattern | Risk | Grep |
|---|---|---|
| Clipboard dual access | OSC 52 + native clipboard in same flow | `osc52 |
| Subprocess + shared file | Parent and child write same file | `spawn |
| OS exclusive resource | Win32 clipboard, serial port, named pipe | `OpenClipboard |
| Terminal escape sequences | stdout triggers terminal OS access | `\x1b\] |
| External clipboard tools | Clipboard via spawned process | `pbcopy |
Layer 2 — This check relies on reasoning more than any other:
| Resource | Exclusive? | Accessor 1 | Accessor 2 | Sync present? |
|---|
Trace Timeline:
t=0ms operation_A() -> resource_X accessed
t=?ms side_effect -> resource_X accessed by external process
t=?ms operation_B() -> resource_X accessed again -> CONFLICT?
Critical Questions:
Severity: CRITICAL (two accessors to exclusive OS resource without sync) | HIGH (subprocess + shared file without lock) | HIGH (invisible side effect detected via reasoning)
Safe pattern exclusions: Single accessor. Retry/backoff pattern present. Operations sequenced with explicit delay/await.
Effort: M-L (may require removing redundant access path)
MANDATORY READ: Load shared/references/audit_worker_core_contract.md and shared/references/audit_scoring.md.
MANDATORY READ: Load shared/references/audit_worker_core_contract.md and shared/templates/audit_worker_report_template.md.
Write report to {output_dir}/628-concurrency.md with category: "Concurrency" and checks: async_races, thread_safety, toctou, deadlock_potential, blocking_io, resource_contention, cross_process_races.
Return summary to coordinator:
Report written: docs/project/.audit/ln-620/{YYYY-MM-DD}/628-concurrency.md
Score: X.X/10 | Issues: N (C:N H:N M:N L:N)
MANDATORY READ: Load shared/references/audit_worker_core_contract.md.
MANDATORY READ: Load shared/references/audit_worker_core_contract.md.
shared/references/audit_scoring.md{output_dir}/628-concurrency.md (atomic single Write call)shared/references/two_layer_detection.mdshared/references/audit_output_schema.mdVersion: 4.0.0 Last Updated: 2026-03-04
Weekly Installs
170
Repository
GitHub Stars
262
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
claude-code156
cursor152
opencode152
codex151
gemini-cli151
github-copilot144
OpenClaw 安全 Linux 云部署指南:私有优先、SSH隧道、Podman容器化
33,700 周安装
| Shared module-level state in async |
Module-level \w+\s*= + modified inside async def |
| All | Shared cache without lock | `.set( |
HashMap + `Thread |
| Rust | Rc in multi-thread context | Rc<RefCell + `thread::spawn |
| Node.js | Worker Threads shared state | `workerData |
| Node.js | fs.existsSync() | fs.readFileSync() | existsSync\( near `readFileSync( |
| Node.js | fs.accessSync() | fs.openSync() | accessSync\( near openSync\( |
| Go | os.Stat() | os.Open() | os\.Stat\( near `os.Open( |
| Java | .exists() | new FileInputStream | \.exists\(\) near `new File |
| Go | Nested locks | Two \.Lock\(\) calls in same function without intervening \.Unlock\(\) |
| Java | Nested synchronized | synchronized\s*\( (multiline: nested blocks with different monitors) |
| JS | Async mutex nesting | await\s+\w+\.acquire\(\) (two different mutexes in same function) |
open\(async defaiofiles.open |
| Node.js | fs.readFileSync in async | `fs.readFileSync | fs.writeFileSync |
| Node.js | execSync in async | `execSync | spawnSync` in async handler |
| Node.js | Sync crypto in async | `crypto.pbkdf2Sync | crypto.scryptSync` |