Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff changes C, C++ or Objective-C, Rust unsafe blocks, Go unsafe or cgo, JNI, Python ctypes/cffi or C extensions, Swift unsafe pointers, C# unsafe or Marshal code, or a native plugin, parser or loader that sees untrusted bytes - bounds, integer overflow before allocation, unit confusion, lifetimes, uninitialized memory, format strings, FFI ownership and library search order
インストールする前に、エージェントに与えられる指示の中身を確認できます。
The hard exclusion on memory safety covers memory-safe languages. Native code is the opposite case: in C, C++, Objective-C, unsafe Rust, cgo, JNI and ctypes, one wrong length turns a packet, a save file, a mod, an image or a model file into a read or write outside the buffer. These bugs are in scope whenever untrusted bytes reach the code.
Core principle: re-derive every length, index and lifetime from the worst value the attacker can send — not from the value the tests use — and state the effect you can show (read, write, use-after-free, crash) without inflating it.
A finding needs a realistic untrusted source: a network peer, a file the user opens or downloads (save, replay, mod, asset, document, model), an IPC message from a less-trusted process, a plugin from a third party. A buffer bug reachable only from the program's own constant data, or from a developer's local CLI flag, is a bug, not a vulnerability.
// ❌ len comes from the packet; dst holds 64 bytes
uint16_t len = read_u16(pkt);
memcpy(dst, pkt->data, len);
// ✅ check against the destination AND what the source actually holds
if (len > sizeof(dst) || len > pkt->remaining) return ERR_MALFORMED;
memcpy(dst, pkt->data, len);
Check both sides of every copy. Recompute the room left after a header, a prefix, alignment padding or a terminator. strcpy, strcat, sprintf, gets and strncpy (no terminator when it truncates) on input are findings by shape; std::vector::operator[] and std::span do not check, .at() does.
// ❌ both factors come from the wire: the 32-bit product wraps, the allocation is tiny,
// and the loop still writes count records of rec bytes
uint32_t count = r.u32(), rec = r.u32();
uint8_t* buf = (uint8_t*)malloc(count * rec);
for (uint32_t i = 0; i < count; ++i) r.read(buf + (size_t)i * rec, rec);
// ✅ upper bounds, then checked multiplication in size_t
size_t bytes;
if (count > kMaxRecords || rec > kMaxRecordSize ||
__builtin_mul_overflow((size_t)count, (size_t)rec, &bytes)) return Reject();
High-hit shapes: a - b where b > a can happen; a 64-bit length narrowed to int or uint16_t; a signed length that is negative passed as size_t; -1 as a sentinel that becomes SIZE_MAX; an addition near the type's maximum. Rust: checked_mul/checked_add, or try_into() instead of as for narrowing.
Bytes vs elements vs UTF-16 code units vs pages; sizeof(ptr) where sizeof(*ptr) was meant; a length validated in one unit and used in another. A bounds check that uses the same wrong unit as the allocation is still wrong.
push_back/erase on a container while iterating it; a reference into a vector kept across a resize.c_str() or std::string_view of a temporary; a pointer into a buffer that is reallocated.unsafe: slice::from_raw_parts(ptr, len) with len from input, get_unchecked, set_len before initialization, transmute between unrelated types, a hand-written unsafe impl Send/Sync.static_cast<Derived*>(base) after if (msg.kind == …)) where the object's real type was never checked; a union read through the wrong member.printf(user), syslog(LOG_INFO, user), NSLog(user), String(format: user) — a fixed format with the input as an argument is the fix.
unsafe.Slice/unsafe.String over a C buffer with a length from input.GetByteArrayElements/GetStringUTFChars without the matching release; ctypes calls with no argtypes/restype, so 64-bit pointers are truncated to int.extern "C" boundary.A process — especially one that runs elevated or starts automatically — loads a library, plugin or helper by bare name or relative path, from the working directory, a downloads folder or a user-writable plugin directory: LoadLibrary("x.dll"), dlopen("libx.so") with an attacker-influenced LD_LIBRARY_PATH, a plugin folder scanned without a signature check. A user loading their own plugin into their own process is not a boundary.
This review never compiles or runs the code. Settle it from source: write the worst accepted input through the arithmetic, name the allocation and the access with file:line, and say which effect the trace shows — out-of-bounds read, out-of-bounds write, use-after-free, or only a clean rejection or abort. If the decisive fact is a build flag, architecture, allocator or a foreign library you cannot read, it is a needs-validation note (source-visibility-needs-validation), not a block.
An attacker-controlled out-of-bounds write or use-after-free reachable from the network or from an opened file → CRITICAL (HIGH when it needs a rare precondition). An out-of-bounds read that returns memory to the peer → HIGH. A crash of a shared process (a game server, a daemon) from one input → MEDIUM to HIGH as availability with shared impact (security-hard-exclusions-and-precedents §4). A crash of only the attacker's own client → not a finding.
strcpy on a constant or a length-checked buffer.C.CString, a missing free) as a vulnerability — it is a bug.memcpy, malloc, an index or a loop bound with no check against the buffer.count * size or a - b before an allocation or copy, with no overflow check.strcpy, sprintf, gets, or printf(var).from_raw_parts, get_unchecked, set_len, transmute inside a new unsafe block.LoadLibrary/dlopen with a relative name in a privileged or auto-started process.SEI CERT C Coding Standard · SEI CERT C++ · cgo pointer passing rules · The Rustonomicon · CWE-119, 125, 131, 134, 190, 416, 426, 787, 843 · Cloudflare security-audit-skill
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
日本語の概要は準備中です。原文の説明を表示しています。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
日本語の概要は準備中です。原文の説明を表示しています。
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
日本語の概要は準備中です。原文の説明を表示しています。
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
日本語の概要は準備中です。原文の説明を表示しています。
Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation
日本語の概要は準備中です。原文の説明を表示しています。