agentsclimarketplace

Resource review

Skill photostructure/coding-skills/plugins/cpp/skills/resource-review

Opinionated Claude Code and Codex workflow skills: iterative planning, proof-based review, and clean Conventional Commits.

Install
npx -y skills add photostructure/coding-skills --skill resource-review

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Top-level memory- and resource-safety code review for modern C/C++ (C++17), including Node.js native addons (node-addon-api / Node-API). Use when the user asks to "review C++/C for memory safety", "find a memory leak", "why does this segfault", "check for use-after-free / double-free / buffer overflow / data race", "resource/handle/fd leak", "review this native addon", "N-API / node-addon-api review", or to check native code with AddressSanitizer/UBSan/TSan/Valgrind. Reports only defects backed by a sanitizer trace, reproducer, or fully traced lifetime. Do not restart the full workflow for a delegated leaf validation task.

SKILL.md

15.3 KB, as published. Nobody here has run it

C/C++ Resource & Memory Review

Leaf-mode guard

If the task identifies your role as leaf-reviewer or sets delegation-budget: 0, read and follow references/validation-pass.md, validate only the supplied candidates, return the verdicts to the caller, and stop before the full workflow below.

Identify provable memory- and resource-safety defects in modern C/C++ (C++17), including Node.js native addons built with node-gyp and node-addon-api. Reason about object lifetimes and resource ownership the way an AddressSanitizer report would — then report only what you can back with concrete proof. Signal over noise.

This skill finds defects (a leak, a use-after-free, a race that actually exists). For "is this project set up with the right hardening flags, sanitizers, CI, and conventions?" use the project-setup skill, which assesses preventive controls, not exploitable bugs. A missing hardening flag is not a defect; a heap-buffer-overflow is.

Scope

In scope: C and C++ translation units (.c/.cc/.cpp/.cxx/.h/.hpp), especially Node.js native addons (Napi::ObjectWrap, AsyncWorker, ThreadSafeFunction, finalizers), the C ABI boundary between C++ and C libraries, and the binding.gyp defines that change runtime behavior.

Out of scope: the surrounding JavaScript/TypeScript (defer to the web-security-review skill), and pure build-hardening/convention gaps (defer to the project-setup skill).

Report vs. research — the prime directive

  • Report on: only the file, diff, or path the user asked about.
  • Research: the entire module to establish the facts — who allocates, who frees, which thread touches what, when a destructor or finalizer actually runs, and what the C library's ownership contract says.

A native defect is almost never visible in one function. Trace the allocation to its free, the handle to its close, the pointer to the object's real lifetime, and the napi_value to the call that created it. Never report on pattern-match alone.

Reporting gate: proof, not probability

Report a finding only when you can construct concrete proof. If you cannot describe how the defect actually manifests at runtime, it is not a finding. Use one of these proof shapes:

  • Dynamic proof (strongest): a sanitizer or Valgrind report with a stack trace — ASan (use-after-free, heap/stack-buffer-overflow, double-free), LSan (leak), UBSan (signed overflow, misaligned access, invalid cast), TSan (data race), or Valgrind memcheck/helgrind. Reproduce it when a toolchain is available.
  • Reproducer proof: a concrete, deterministic sequence of calls (or inputs from JS) that drives the code to the defect, with the exact lifetime step that goes wrong.
  • Traced-lifetime proof: the full ownership path in code — the allocation/acquisition site, every branch to release, and the specific path that double-frees, leaks, frees early, or reads freed/uninitialized memory — with file:line for each step.

Every shape must establish the trigger (what sequence or input reaches it), the mechanism (the exact lifetime error), and the impact (crash, corruption, leak, disclosure). Prefer to miss a theoretical issue than to flood the report.

Do not assign confidence percentages or 1–10 scores — the complete proof is the evidence. Every candidate is in exactly one state:

StateYou have…Action
Provenone complete proof shape above, with the lifetime error described concretelyReport, with that proof in the finding
Leada suspicious lifetime, ownership ambiguity, or static-analyzer hit with a missing proof elementList under "Needs verification" as a question
Theoreticala pattern match, style nit, or missing hardening control with no demonstrable errorDrop (hardening belongs to the project-setup skill)

Read references/proof-and-tooling.md before reporting anything — it defines how to obtain each proof and the false-positive discipline (a static-analyzer warning is a Lead, not a finding; a sanitizer suppression may be hiding the very bug you are looking for).

Review workflow

Run these steps in order. Load reference files as each step needs them.

1. Scope resolution

  • If a path/diff was given, review only that. Otherwise review the working changes, including untracked files:
    if git rev-parse --verify --quiet origin/HEAD >/dev/null; then
      git diff --merge-base origin/HEAD
    else
      git diff HEAD
    fi
    git ls-files --others --exclude-standard
    
  • Establish the toolchain and shape: language standard and defines from binding.gyp / CMakeLists.txt, node-addon-api and NAPI_VERSION, whether NAPI_CPP_EXCEPTIONS is set, target OSes/arches, and any vendored C sources. This tells you which classes are reachable and whether you can build a sanitized reproducer.

2. Map the defect surface

For each file, decide which defect classes are even reachable, then load the matching sections of references/defect-classes.md:

Code under reviewPrimary classes to check
Manual new/delete, malloc/free, owning raw pointersleaks, use-after-free, double/mismatched free
OS handles / fds / sockets / library handlesresource/handle/fd leaks, use-after-close
Buffers, arrays, pointer arithmetic, memcpy/strcpyheap/stack overflow, out-of-bounds read/write
Size/length math, casts between int widths/signsinteger overflow/truncation → under-allocation
Uninitialized locals/members, partial constructionuninitialized reads
Filesystem path checks then useTOCTOU
Threads, AsyncWorker::Execute, shared mutable statedata races, lock-ordering, atomics misuse
Napi::ObjectWrap, Reference, ThreadSafeFunction, finalizersNode-API lifetime — see napi-resource-model.md

For any addon code, load references/napi-resource-model.md: the addon-specific hazards a general C++ reviewer misses (call-scoped napi_value stored too long, reference/handle-scope leaks, finalizers that run late or under restricted API rules, threadsafe-function acquire/release imbalance, exceptions crossing the C ABI).

3. Deep lifetime scan

The core pass. Reason about ownership; do not grep-and-report. For each allocation or acquisition, answer: who owns it, is release guaranteed on every path (including exceptions and early returns), can it be released twice, and can anyone use it after release? For each buffer, answer: is every index and length bound-checked against the real allocation size, computed without overflow? Apply the detection signals and safe patterns in defect-classes.md.

4. Cross-boundary lifetime analysis

Step back and trace lifetimes across function, thread, and language boundaries — where the real defects hide:

  • C++ ↔ C library: does the code honor the library's ownership contract (which allocator frees it, required teardown order, when error accessors are still valid)?
  • Native ↔ JS: does a JS object outlive the native resource it wraps, or vice versa? Is a napi_value, Reference, or ObjectWrap pointer used after the object is gone?
  • Thread ↔ thread: is every field touched from a worker thread and the main thread synchronized or atomic? Does Execute() touch napi_env/napi_value (forbidden)?
  • Teardown: what runs during environment/process teardown, and in what order — can a finalizer, cleanup hook, or destructor touch something already freed?

5. Obtain proof

Promote each surviving candidate to Proven or drop it. When a toolchain is available, build a sanitized target and drive the path (see proof-and-tooling.md) — an ASan/UBSan/ TSan/LSan or Valgrind trace is the gold standard. When you cannot build, construct a complete traced-lifetime proof with file:line for every step, or downgrade it to a Lead.

6. Adversarial self-verification

For each surviving candidate, try to refute it before it makes the report. For a non-trivial finding set, use at most two leaf validation tasks total. Partition or batch the candidates between them; never launch one task per candidate or a second validation round.

Prefer the tool-restricted cpp:reviewer agent when the host exposes it; otherwise use a general task-local subagent. Start every prompt with role: leaf-reviewer and delegation-budget: 0, omit workflow skill names, and point it at the resolved path of <plugin-root>/skills/resource-review/references/validation-pass.md. When context inheritance is configurable, do not pass the surrounding conversation. Ask each reviewer to disprove its assigned candidates using references/proof-and-tooling.md:

  • Re-read the lifetime with fresh eyes. Is release actually missing, or is there an RAII guard, unique_ptr, tracking set, or cleanup hook that handles it?
  • Is the pointer really used after free, or was ownership transferred/nulled first?
  • Is the buffer access truly unbounded, or is there an upstream length/SafeCast check?
  • Is the "race" real, or is the state single-threaded by construction / mutex-protected?
  • Is the "leak" first-party, or a one-time library init that a suppression legitimately covers?

Drop anything without a complete applicable proof after refutation.

7. Report

Emit the report in the structure defined by references/report-format.md: a severity summary table, then findings grouped by defect class, each with location, proof (sanitizer trace / reproducer / traced lifetime), a plain-English trigger, impact, and a minimal fix. If nothing survives, say so explicitly and state what was scanned — "No proven memory/resource defects identified in <scope>."

8. Propose fixes (do not auto-apply)

For each Critical/High finding, propose a concrete, minimal patch (vulnerable → fixed), preserving surrounding style and names, and prefer the RAII/ownership fix that removes the class of bug (see the project-setup skill's modern-cpp-conventions.md) over a one-off patch. State plainly: "Review each patch before applying — nothing has been changed." Never edit files as part of the review unless the user explicitly asks.

Severity

SeverityImpactNative examples
CriticalMemory corruption reachable from untrusted inputHeap-buffer-overflow or use-after-free driven by attacker-influenced JS input; write past a buffer
HighCorruption/crash under realistic conditionsUse-after-free on a teardown/close race; double-free; unbounded write with a plausible trigger
MediumReal defect, bounded or conditional impactOut-of-bounds read; integer truncation feeding a size; leak on a hot path; data race on non-critical state
LowDemonstrable but limitedOne-time leak only at process exit; missing close on a rare error path with small impact

Rate by demonstrated impact and trigger reachability, not by how alarming the class sounds. A theoretical overflow with no reachable trigger is not a finding at all.

Output rules

  • Lead with a findings summary table (counts by severity).
  • Group by defect class, not by file.
  • Every finding: file:line, an evidence snippet, its proof (the applicable shape), a plain-English trigger scenario, impact, and a fix.
  • Never auto-apply patches — present them for human review.
  • A clean result is a valid result: say what was scanned and that nothing was proven.

Reference files

Load on demand — keep SKILL.md context lean.

FileLoad duringCovers
references/defect-classes.mdsteps 2, 3Per-class detection signals, safe patterns, CWE/CERT mapping, and which sanitizer proves each: UAF, double/mismatched free, leaks, OOB, uninitialized reads, integer overflow/truncation, TOCTOU, data races
references/napi-resource-model.mdsteps 2, 4Node-API / node-addon-api lifetime hazards: call-scoped handles, handle scopes, reference RAII, ObjectWrap finalizer timing and API restrictions, ThreadSafeFunction/AsyncWorker ownership, exceptions across the C ABI, context-aware instance data
references/proof-and-tooling.mdsteps 5, 6The proof hierarchy; running ASan/UBSan/TSan/LSan/Valgrind against a Node addon; what each tool misses; legitimate vs. bug-masking suppressions; the Proven/Lead/Theoretical gate
references/report-format.mdstep 7Output template and finding card

Adapting for your project

Point this skill at AGENTS.md and optional CLAUDE.md for the module's threading model, ownership conventions, and known-safe patterns. Record the project's real invariants (for example "statements are single-threaded by construction", "explicit close orders native teardown before finalization") in references/napi-resource-model.md so the review credits them instead of re-flagging them, and add any project-specific RAII wrappers to references/defect-classes.md so their release contracts are understood.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.