code-review — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited code-review (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
"Code is read far more often than it is written. A review is the first reading after the first write." — adapted from the Go proverbs.
This skill conducts a structured, evidence-first review of a code change set. It is read-only by default — it never edits code, it produces a report. It is language-aware for Go, Rust, TypeScript (Node and Bun), and Python (CPython 3.13 / 3.14 on FastAPI / Django / Flask); other languages are best-effort using the generic principles. It is lifecycle-driven: detect → sweep → read → assess → report → cross-link.
The skill exists because LLM reviewers tend to hallucinate findings: invented function names, wrong file paths, fabricated CVEs, and severity inflation. Every guardrail in the Constraints section is there to push back on those failure modes.
'review code', 'code review', 'revisar código', 'PR review', 'auditar código', or invokes /valarmindskills:code-review.@code-debugger for runtime issues.@github-commit or @github-release-note.@<lang> skill). Surface the gap and ask whether the user wants a generic pass.@code-debugger. This skill may run optional verification commands only when they are explicitly requested or needed to validate a review finding.@code-security-review (Next branch — references/nextjs/; Go branch — references/golang/; Python branch — references/python/) or @ci-cd-generator for those domains.Install before starting a review. Each tool's absence is logged and the related Phase is degraded but never silently skipped. The default mode is static review: read diffs, run linters, type checks, SAST, and dependency audit. Tests and runtime commands are optional verification, not part of the default review.
| Tool | Purpose |
|---|---|
git | Diff and blame inspection |
gh (GitHub CLI) | Pull request metadata, review comments |
rg (ripgrep) | Pattern sweep across the diff |
fd | Fast file finder |
jscpd | Multi-language clone detection |
semgrep | Polyglot SAST with rules per language |
golangci-lint | Go meta-linter (50+ linters) |
staticcheck | Go advanced static analysis |
govulncheck | Go CVE scan |
cargo clippy | Rust idiomatic linter |
cargo audit | Rust CVE scan |
cargo deny | Rust dependency policy |
tsc | TypeScript compiler (--noEmit) |
eslint / biome | TypeScript linter |
knip | Find unused TS exports/files/deps |
npm audit / bun audit | Node/Bun CVE scan |
ruff | Python lint + format (replaces flake8/black/isort/most of pylint) |
mypy / pyright | Python strict type check |
bandit | Python SAST (CWE-mapped) |
pip-audit / safety | Python CVE scan |
pytest | Python test runner (optional verification only) |
Test runners (go test, cargo test, bun test, vitest, pytest) | Optional verification only |
Required access:
gh pr diff)The skill does not require write access. It never commits, never pushes, never edits source files.
Detect language, package manager, review scope, and diff range before sweeping anything. Run the steps in order; stop at the first conclusive match per axis.
# Step 1 — language at the repo root
test -f go.mod && echo "language: go"
test -f Cargo.toml && echo "language: rust"
test -f package.json && echo "language: typescript"
test -f tsconfig.json && echo " ts-config: present"
test -f pyproject.toml && echo "language: python"
test -f requirements.txt && echo "language: python (legacy manifest)"
# Step 2 — TypeScript runtime (only if language=typescript)
test -f bun.lockb && echo "runtime: bun, pm: bun"
test -f pnpm-lock.yaml && echo "runtime: node, pm: pnpm"
test -f yarn.lock && echo "runtime: node, pm: yarn"
test -f package-lock.json && echo "runtime: node, pm: npm"
# Step 2b — Python package manager (only if language=python)
test -f uv.lock && echo " pm: uv"
test -f poetry.lock && echo " pm: poetry"
test -f Pipfile.lock && echo " pm: pipenv"
# Step 3 — review scope and base branch
git rev-parse --abbrev-ref HEAD
gh pr view --json number,title,baseRefName,headRefName 2>/dev/null
BASE_REF="$(gh pr view --json baseRefName --jq .baseRefName 2>/dev/null || git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null | sed 's@^origin/@@' || echo main)"
BASE_REMOTE="origin/$BASE_REF"
BASE_SHA="$(git merge-base "$BASE_REMOTE" HEAD 2>/dev/null || git merge-base "$BASE_REF" HEAD)"
DIFF_RANGE="$BASE_SHA...HEAD"
git diff --name-only "$DIFF_RANGE" | wc -l
git diff --shortstat "$DIFF_RANGE"
# Step 4 — polyglot or monorepo
fd -t f -d 5 '^(go.mod|Cargo.toml|package.json|pyproject.toml)$' . # multiple roots → monorepoPersist as $LANG ∈ {go, rust, typescript, python, polyglot, other}, $BASE_REF, $BASE_SHA, and $DIFF_RANGE.
$LANG | Reference to load | Primary linter |
|---|---|---|
go | references/GOLANG.md | golangci-lint |
rust | references/RUST.md | cargo clippy |
typescript | references/TYPESCRIPT.md (+ references/NEXTJS.md if Next.js 16+ App Router detected via package.json and app/) | tsc --noEmit + eslint/biome |
python | references/PYTHON.md | ruff + mypy/pyright + bandit |
polyglot | Run Phase 1–5 per language detected | per-language |
other | Skip Phase 1.2 sweeps; run Phase 2 + generic Phase 3–5 | semgrep generic ruleset |
If the diff exceeds 50 files or 1500 lines, ask the user to split the review or to scope it to a subset before proceeding. Large reviews dilute attention and amplify hallucination risk.
Default to the diff. A finding is in scope only when the changed line is in $DIFF_RANGE or the changed code makes an existing line newly reachable, newly exposed, or newly unsafe. Issues outside the diff are reported as Out-of-scope observation unless the user explicitly requested a baseline audit.
Use null-delimited file lists when passing changed files between tools. The loop is portable across empty diffs and file names with spaces:
git diff --name-only -z "$DIFF_RANGE" -- '*.go' | while IFS= read -r -d '' file; do rg -n '<pattern>' "$file"; done
git diff --name-only -z "$DIFF_RANGE" -- '*.rs' | while IFS= read -r -d '' file; do rg -n '<pattern>' "$file"; done
git diff --name-only -z "$DIFF_RANGE" -- '*.ts' '*.tsx' | while IFS= read -r -d '' file; do rg -n '<pattern>' "$file"; done
git diff --name-only -z "$DIFF_RANGE" -- '*.py' | while IFS= read -r -d '' file; do rg -n '<pattern>' "$file"; doneWhen multiple go.mod, Cargo.toml, or package.json files are present, map each changed file to the nearest owning root before running toolchains. Run Phase 1–5 per touched root, not from the repository root unless the project convention requires it.
| Root type | Ownership rule | Static command root |
|---|---|---|
| Go module | nearest ancestor go.mod | run Go tools from that module |
| Cargo workspace | workspace root if workspace exists; otherwise crate root | run Cargo tools with package filters when available |
| npm/pnpm/yarn/bun workspace | nearest package or workspace root from lockfile config | run package scripts in touched package first |
| Python project | nearest ancestor pyproject.toml (else requirements.txt) | run ruff / mypy / bandit from that root |
Run the static toolchain first; treat results as leads, never as conclusions. Calibration: every linter has known false-positive classes — start each automated finding at Medium severity and only promote to High with manual confirmation in Phase 2.
# Polyglot SAST (always run if available)
semgrep --config=auto --error --severity=ERROR --severity=WARNING
# Go
golangci-lint run ./...
staticcheck ./...
go vet -all ./...
govulncheck ./...
# Rust
cargo clippy --all-targets --all-features -- -D warnings
cargo audit
cargo deny check
# TypeScript / Node / Bun
bunx tsc --noEmit # or: npx tsc --noEmit
bunx biome check . # or: bunx eslint .
bunx knip
bun audit # or: npm audit --omit=dev
# Python
ruff check .
ruff format --check .
mypy --strict . # or: pyright
bandit -r . -q # run from package root (pyproject.toml dir); use src/ if project uses src-layout
pip-audit
safety check
# Duplication (any language)
npx jscpd --min-lines 5 --min-tokens 50 ./For each tool, capture the raw output and keep the version (<tool> --version) in the findings report. A finding without a tool version is not reproducible.
Run tests only when the user asks, CI output is unavailable, or a finding needs confirmation. Label them separately from static tools in the report.
go test ./... # add -race only for concurrency findings or explicit request
cargo test --all-features
bun test # or: npx vitest run
pytest -q # PythonNever claim pass/fail unless the command and relevant output are shown in the report.
For each category below, run the grep across changed files only using $DIFF_RANGE and null-delimited file lists, then read the matching files for context.
| # | Category | Detection | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Hardcoded secrets | `rg -i '(password\ | secret\ | api[_-]?key\ | token\ | bearer)\s[:=]\s["\x27][A-Za-z0-9/+=_-]{8,}["\x27]'` | |||||
| 2 | TODO/FIXME/XXX | `rg -n '\b(TODO\ | FIXME\ | XXX\ | HACK)\b'` (finding only when newly introduced, shipping to main, and not linked to an issue) | ||||||
| 3 | Stack trace exposure | `rg -n '(stack\ | stacktrace\ | traceback\ | panic)' --type-add 'web:*.{go,ts,tsx,rs,py}' --type web` | ||||||
| 4 | Unbounded loops / collections | `rg -n 'for\s\(\s;;\s*\)\ | while\s*\(true\)\ | loop\s*\{' ` | |||||||
| 5 | Disabled error handling | `rg -n '_ =\ | catch\s\(\s_\s*\)\ | \.unwrap\(\)\ | \.expect\(\ | \.ok\(\)\.unwrap\(\ | except\s*:\ | except\s+Exception\s*:'` | |||
| 6 | Insecure crypto | `rg -n '(md5\ | sha1\ | des\ | InsecureSkipVerify\ | crypto/rand vs math/rand)'` | |||||
| 7 | Logging of sensitive data | `rg -n 'log\.(Info\ | Debug\ | Print).*\b(password\ | token\ | secret\ | cookie\ | authorization)\b'` | |||
| 8 | Wide-open CORS | `rg -n 'Access-Control-Allow-Origin.\\ | AllowAllOrigins\ | origin: ["\x27]\*'` | |||||||
| 9 | Disabled lints / suppressions | `rg -n '(// nolint\ | //nolint\ | #\[allow\(\ | @ts-ignore\ | @ts-nocheck\ | eslint-disable\ | # noqa\ | # ruff: noqa\ | # type: ignore\ | # pyright: ignore)'` |
| 10 | Test code in production paths | `rg -n '(println\!\ | console\.log\ | fmt\.Println\ | ^\sprint\()' --glob '!/test*'` |
Per-language sweeps live in references/GOLANG.md, references/RUST.md, references/TYPESCRIPT.md, and references/PYTHON.md.
Read the diff with the same posture a teammate would: from base branch to head, file by file, top to bottom. The automated tools cannot judge intent — this phase is where intent meets implementation.
For every changed function or block, answer in your head:
A finding is born only when the answer is unsatisfactory and the evidence is in the diff. Hallucinations are findings born without one of those two preconditions.
| Smell | Detection | Action |
|---|---|---|
| Unrelated changes mixed in | git diff --name-only against the PR description | Ask the author to split |
| Whitespace-only churn | git diff --ignore-all-space shows a smaller diff | Note as Low severity, not blocking |
| Large generated files committed | *.lock, *.min.js, dist/ in the diff | Verify intentional; check .gitignore |
| Re-formatted file alongside a tiny logic change | Many lines changed, few semantic | Ask for a separate format-only commit |
Run after Phase 2 because security findings depend on understanding intent. The OWASP API Top 10 (2023) and OWASP Web Top 10 (2025) are the reference frames.
| OWASP | Category | What to read |
|---|---|---|
| API1 | Broken Object Level Authorization (BOLA / IDOR) | Every handler that takes an ID — does it check ownership? |
| API2 | Broken Authentication | Token issue/refresh/revoke paths; password handling |
| API3 | Broken Object Property Level Authorization | Mass assignment; allow-listed fields on update |
| API4 | Unrestricted Resource Consumption | Rate limits, body size limits, pagination caps |
| API5 | Broken Function Level Authorization | Admin / non-admin route separation, RBAC checks |
| API6 | Unrestricted Access to Sensitive Business Flows | Captcha / quotas on signup, order, transfer |
| API7 | Server-Side Request Forgery | Outbound HTTP calls with user-supplied URLs |
| API8 | Security Misconfiguration | Headers (CSP, HSTS), TLS, debug flags, default creds |
| API9 | Improper Inventory Management | Public endpoints not in OpenAPI / spec |
| API10 | Unsafe Consumption of APIs | Deserialization of upstream JSON without schema |
| Web1–10 | Web equivalents | XSS, SQLi, SSRF, etc. — see per-language reference |
For deeper stack-specific OWASP audits, hand off to @code-security-review (Go branch — references/golang/; Next branch — references/nextjs/; Python branch — references/python/). This skill stops at "this PR likely introduces a class-X issue at file.ext:LINE — recommend running the dedicated skill".
Every language's reference file (GOLANG, RUST, TYPESCRIPT, PYTHON) lists detection commands and code examples for: SQL injection, XSS / SSTI, SSRF, path traversal, command injection, insecure deserialization (pickle / yaml in Python), hardcoded secrets, insecure crypto, log injection, open redirect, race conditions (including free-threaded races on python3.14t), resource exhaustion.
Performance findings have the lowest hallucination tolerance — the LLM cannot benchmark. Constrain claims to patterns known to scale poorly, not to predicted latencies.
For Next.js 16.2.x App Router projects, also load references/NEXTJS.md — covers the <img> rule, Server Components / RSC payload minimization, "use cache", Turbopack notes, and experimental.prefetchInlining trade-offs.
| # | Anti-pattern | Sweep | |||
|---|---|---|---|---|---|
| 1 | N+1 queries | Loop body containing a DB call (`rg -n -C 3 'for .*\{ | db\. | tx\. | repo\.' --type go`) |
| 2 | Missing index hint | New WHERE/JOIN on a column not in any migration in the diff | |||
| 3 | Sync I/O on hot path | Blocking call inside a request handler (e.g. time.Sleep, fs.readFileSync, block_on) | |||
| 4 | Unbounded buffering | bufio.Scanner without Buffer(); Vec::new() then unbounded push; for await ... of stream without limit | |||
| 5 | Premature serialization | Marshalling 10k-row collections into a single response | |||
| 6 | Missing context / cancellation | New goroutine / task without context.Context / CancellationToken / AbortSignal | |||
| 7 | Lock granularity | Mutex held across an I/O call; Arc<Mutex<HashMap>> where DashMap/RwLock would suffice | |||
| 8 | Allocation in hot loop | string + concatenation in a tight loop; clone() per iteration | |||
| 9 | Memory leak via closure capture | Long-lived closure capturing a request-scoped value | |||
| 10 | Cache poisoning / unbounded cache | New cache without TTL or size cap |
Every finding must cite a file:line and quote the exact code; "this might be slow" without code is not a finding.
-race, Rust loom, TypeScript fast-check).TestServer_RejectsUnauthenticatedRequest).Do not file "missing test" as a finding until you have searched for existing coverage in the touched package. If coverage exists but does not cover the changed branch, cite the missing branch precisely.
@clean-code)For deep refactor recommendations, hand off to @clean-code.
Rely on the project's auto-formatter (gofmt, rustfmt, prettier/biome). Style differences that the formatter would catch are not findings — they are bugs in the CI configuration.
Aggregate, deduplicate, and rank. Each finding is a row in the report; each row needs every column filled or it is dropped.
| Severity | Definition | Examples |
|---|---|---|
| Critical | Direct exploit, data loss, or full service outage if merged | RCE, plain-text creds, missing auth on admin route |
| High | Likely exploit, partial outage, or silent data corruption | BOLA in a list endpoint, panic in a handler, unbounded query |
| Medium | Latent bug, fragile code, or notable maintainability hit | Missing test, swallowed error, function > 60 lines |
| Low | Style, naming, comment hygiene, minor smells | Stuttering name, unnecessary clone(), magic number |
| Info | Observation, not a defect | "Consider extracting helper", "Worth a benchmark" |
Calibration aids — see references/SEVERITY_RUBRIC.md for the full Impact × Likelihood matrix and per-tool false-positive notes.
Tag every suggested change so the author can triage:
SAFE — isolated, no behavior change, no public API impact.REVIEW — touches middleware, auth, shared utils, or a module boundary.BREAKING — changes a signature, response shape, schema, or observable behavior.High — the evidence is exhaustive and the reasoning is mechanical.Medium — the pattern matches but intent could plausibly justify it.Low — the reviewer would benefit from a second opinion.If Confidence=Low and Severity ≥ High, escalate explicitly: state "needs human review before action".
Edit/Write calls.govulncheck, cargo audit, npm audit, pip-audit, safety, or semgrep output of this run.@code-security-review Go branch — references/golang/; Next branch — references/nextjs/; Python branch — references/python/; @clean-code, @code-debugger; Next.js performance — references/NEXTJS.md here).Print verbatim after every successful run. The report is the deliverable.
code-review: <branch / PR# / commit range>
language(s): <go | rust | typescript | python | polyglot>
mode: <static review | static + optional verification>
base: <base ref> @ <merge-base sha>
scope: <files changed> files / <lines added>+ / <lines deleted>-
tools: semgrep <ver>, golangci-lint <ver>, ...
verification: <not run | go test ./...: pass | cargo test: fail | ...>
duration: Phase 0–6 walked
Findings (ranked by severity, then by file):
| ID | Sev | Conf | Risk | File:Line | Title |
| --- | -------- | ------ | -------- | ------------------------ | ---------------------------------- |
| R001 | High | High | REVIEW | api/handlers/order.go:42 | BOLA — missing user_id check |
| R002 | High | Medium | SAFE | api/store/db.go:118 | Unbounded SELECT without LIMIT |
| R003 | Medium | High | SAFE | api/util/log.go:7 | Logs Authorization header verbatim |
| R004 | Low | High | SAFE | api/handlers/order.go:8 | Stuttering name OrderOrder |
Detailed findings:
R001 — BOLA — missing user_id check
File: api/handlers/order.go:42
Code:
| order, err := h.store.GetOrder(ctx, c.Param("id"))
| if err != nil { ... }
| c.JSON(200, order)
Impact: Any authenticated user can read any order by guessing IDs.
Suggested fix (REVIEW):
| order, err := h.store.GetOrder(ctx, c.Param("id"))
| if err != nil { ... }
+ if order.UserID != claims.UserID { c.AbortWithStatus(403); return }
| c.JSON(200, order)
Verification: add an integration test that asserts a 403 when user A
requests user B's order id.
Cross-link: See @code-security-review (Go branch — references/golang/API.md Phase 2) for full BOLA audit.
R002 — Unbounded SELECT without LIMIT
File: api/store/db.go:118
Code:
| rows, err := db.QueryContext(ctx, "SELECT * FROM orders WHERE user_id=$1", uid)
Impact: Memory exhaustion when a user has many orders.
Suggested fix (SAFE): add LIMIT/OFFSET pagination + max-page-size guard.
Verification: load test with 10k-row user; verify p99 latency stays bounded.
... (one block per finding) ...
Summary:
Critical: 0 High: 2 Medium: 1 Low: 1 Info: 0
Blocking-merge findings: 2 (R001, R002)
Suggested next step:
1. Author addresses R001 and R002 before re-request.
2. Run @code-security-review (Go branch — references/golang/API.md Phase 2) to confirm no further BOLA cases.
3. Re-review with `/valarmindskills:code-review` after fixes.
Skill version: code-review @ <git rev of SKILL.md>When there are zero findings, print this shape instead of inventing minor findings:
Findings (ranked by severity, then by file):
| ID | Sev | Conf | Risk | File:Line | Title |
| -- | --- | ---- | ---- | --------- | ----- |
| (no findings) | | | | | |
Detailed findings:
(none)
Summary:
Critical: 0 High: 0 Medium: 0 Low: 0 Info: 0
Blocking-merge findings: 0
LGTM — no blocking issues found in scope.Info-level observations are allowed after the LGTM only when grounded in exact files read during the review.
@code-debugger — when a finding is a runtime failure rather than a code-review concern, hand off here.@clean-code — for refactor patterns and Rule-of-Three deduplication recommendations.@code-security-review — multi-language + Go (Gin/Fiber) + Python (FastAPI/Django/Flask, references/python/) + Next.js 16 App Router security lifecycle: design patterns + active runtime testing + stack-specific vulns + 100-vuln catalog (references/WEB_VULNERABILITIES.md) for cross-linking findings.@github-pr-review — GitHub-flavored PR review (posts comments via gh).@github-commit — when the author wants help drafting the fix commit.@superpowers — engineering posture (TDD, evidence-first) for the author addressing findings.<img>, "use cache", Turbopack)~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.