From buidl
Audits OP_NET code in btc-runtime, opnet-node, op-vm repos for 27 real-bug patterns across serialization, storage/pointers, arithmetic/AMM, access-control, business-logic, memory/bounds, gas, networking, type-safety.
npx claudepluginhub bc1plainview/buidl-opnet-pluginThis skill uses the workspace's default tool permissions.
You are performing a security audit using patterns derived from 27 real OP_NET bugs. Apply ALL checks to every file you review. Do not stop at the first finding.
Audits Cairo/Starknet smart contracts for security vulnerabilities. Discovers in-scope files, runs preflight scans, spawns agents, and merges findings into reports with default, deep, or file-specific modes.
Orchestrates interactive Solidity smart contract security audits using Map-Hunt-Attack methodology: static analysis (Slither, Aderyn), fuzzing (Echidna, Medusa, Halmos), verification, and reporting.
Audits EVM smart contracts for vulnerabilities using 20+ specialized checklists across domains like DeFi, ERC20, proxies via parallel sub-agents. Synthesizes findings and files GitHub issues.
Share bugs, ideas, or general feedback.
You are performing a security audit using patterns derived from 27 real OP_NET bugs. Apply ALL checks to every file you review. Do not stop at the first finding.
Full pattern documentation with code examples: knowledge/slices/security-audit.md (section "Real-Bug Vulnerability Patterns")
[CRITICAL] PAT-S1: Generic integer read — Search for value[0] as T in any generic read/deserialize method. This returns only the low byte of any integer. Must use new BytesReader(value).read<T>(). (btc-runtime PR #137)
[CRITICAL] PAT-S2: BytesReader/BytesWriter offset — For every readUXX() / writeUXX() method: must read/write at currentOffset (not currentOffset + BYTE_LENGTH), must increment currentOffset += BYTE_LENGTH after. (btc-runtime PR #57)
[HIGH] PAT-S3: Save/load type matrix — Build a matrix of every writeU8/16/32/64() in save() paired with readU8/16/32/64() in load(). Any mismatch = upper bytes silently truncated. (btc-runtime PR #88)
[HIGH] PAT-S4: Hex prefix stripping — Search for .replace('0x', ''). ALWAYS wrong for hex stripping. Replace with str.startsWith('0x') ? str.slice(2) : str. (opnet PR #135)
[MEDIUM] PAT-S5: Implicit integer narrowing — Every writeU16(x), writeU8(x), writeU32(x) — verify x is explicitly cast to the matching type or is already that type. (btc-runtime PR #52)
[CRITICAL] PAT-P1: Key concatenation collision — Any template literal joining two string keys: `${a}${b}` without a delimiter. Must use length-prefix: `${a.length}:${a}${b.length}:${b}`. (btc-runtime PR #61)
[HIGH] PAT-P2: Conditional hash bypass — Search for typed.length !== 32 ? hash(typed) : typed or similar. Always hash unconditionally. (btc-runtime PR #61)
[HIGH] PAT-P3: verifyEnd parameter — In verifyEnd(size), condition must be size > buffer.byteLength, NOT currentOffset > buffer.byteLength. (btc-runtime PR #60)
[HIGH] PAT-A1: Silent zero return for undefined math — Search for if (x.isZero()) return u256.Zero in functions where zero input is undefined (log, sqrt of negative). Must throw new Revert(...). (btc-runtime PR #129)
[CRITICAL] PAT-A2: AMM constant-product integrity — Any reserve update function: verify BOTH sides maintain k = B * T. Pattern T -= dT; B += dB independently is WRONG. Must: k = B*T; T -= dT; B = k/T. (native-swap PR #63)
[CRITICAL] PAT-A3: Proportional reserve removal on purge/slash — Any function removing tokens from virtual token reserve must remove proportional BTC: btcOut = (tokens * virtualBTC) / virtualTokens. Both updated atomically. (native-swap PR #51)
[HIGH] PAT-L2: Trade accumulator exhaustion — Before adding to any buy/sell accumulator, verify total + new < projectedReserve. Revert if accumulation would exhaust the pool. (native-swap PR #63)
[CRITICAL] PAT-C1: Signature replay protection — Any verifySignature call: verify the signed payload includes a per-address monotonically-increasing nonce. Increment after success. (btc-runtime PR #60)
[HIGH] PAT-C2: Selector type string accuracy — Every encodeSelector('funcname(type1,type2,...)') call: cross-check every type against actual AssemblyScript parameter types. (btc-runtime PR #61, PR #60)
[CRITICAL] PAT-C3: Decrypt returns null on failure — Any decrypt function: return type must be T | null. NEVER return the original ciphertext on failure. (opnet-node PR #192)
[HIGH] PAT-C4: EC public key prefix validation — Any code identifying EC public key by buffer length: must also validate buf[0] in {0x02, 0x03} for 33 bytes, or buf[0] === 0x04 for 65 bytes. (opnet-node PR #225)
[CRITICAL] PAT-L1: CEI order in AMM activation — Provider activation that reads liquidity for reserve calculation must occur BEFORE any subtract/decrease on that provider's liquidity in the same call path. (native-swap PR #67)
[HIGH] PAT-L3: UTXO commitment placement — reportUTXOUsed() / markUTXOSpent() must only appear in confirmed-success paths, never at a point where both success and failure branches have merged. (native-swap PR #48)
[HIGH] PAT-M1: Array push off-by-one — All push() bounds checks: > MAX must be >= MAX for 0-indexed arrays where valid indices are 0..MAX-1. (btc-runtime PR #61)
[HIGH] PAT-M2: Memory padding offset — In write-data-then-pad-to-length operations: track bytes_written = slice.len(), use that as padding base offset, NOT source_buffer.len(). (op-vm PR #130)
[HIGH] PAT-G1: Gas capture before ExitData — In any VM exit handler: get_used_gas() must be called BEFORE constructing the ExitData/ExitResult. (op-vm PR #109)
[CRITICAL] PAT-G2: Mutex double-lock — In Rust async code: search for two mutex.lock() calls on the same mutex within the same task/scope. Second lock while first guard is alive = deadlock. (op-vm PR #77)
[HIGH] PAT-N1: Null-safe Buffer construction — Any Buffer.from(x, 'hex') || fallback where x may be null/undefined: || doesn't catch exceptions. Must be x ? Buffer.from(x, 'hex') : fallback. (opnet-node PR #218)
[HIGH] PAT-N2: Promise resolve in search loop — Any Promise that resolves a found-item: resolve INSIDE the loop at the point of match (resolve(item); return;), not outside after the loop ends. (opnet-node PR #192)
[MEDIUM] PAT-T1: Abstract interface return types — Every abstract method implementing an external interface: return type must exactly match the interface specification. (transaction PR #86)
[MEDIUM] PAT-T2: Browser ECPair RNG — Any ECPair.makeRandom() without custom rng option in browser-capable code: must provide rng: (size) => Buffer.from(randomBytes(size)). (transaction PR #109)
[MEDIUM] PAT-T3: Reassigned variable used for fallback — Any code pattern x = x[key]; if (!x) x = x[fallbackKey] — after the first assignment, x is no longer the original map. Preserve original reference. (opnet PR #78)
For each finding:
**[SEVERITY] PAT-XX: Title**
- File: path/to/file.ts
- Line: N
- Pattern: which pattern above triggered
- Evidence: the actual code fragment
- Impact: what can go wrong
- Fix: specific remediation
- Ref: original bug PR
Always check ALL 27 patterns. Do not stop at the first finding.