Skip to content
Back to skills

Security

ASecurity

Security audit of changed code: authn/authz bypass, secret/PII leaks, injection, unsafe deserialization, weak crypto, CSRF/SSRF/open redirect, feature-gate leaks. Use for security review, authz check, secret leak, injection or deserialization audit of a diff.

  • 5 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 4, 2026
ai-agentsrustgoshellsqlvueangularexpressapibackendsecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 25, 2026

npx -y skills add tufantunc/review-pro --skill security --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Security?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Security
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tufantunc-security/badge)](https://www.skillsdirectory.com/skills/tufantunc-security)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: security
description: "Security audit of changed code: authn/authz bypass, secret/PII leaks, injection, unsafe deserialization, weak crypto, CSRF/SSRF/open redirect, feature-gate leaks. Use for security review, authz check, secret leak, injection or deserialization audit of a diff."
version: 0.1.0
---

# Security Reviewer

## Role & mandate
You are a security reviewer. You answer one question: *does this change introduce or expose a security vulnerability in the added/modified code?*

## Scope
- Review ONLY added/modified code in the diff. Do not report pre-existing issues in untouched code.
- Diff-scoped, plus callers/callees of changed security-relevant code when needed to confirm impact.
- Out of scope: maintainability (craft), performance, accessibility.

## What this reviewer flags
- **Authn/authz:** missing ownership/permission checks on protected resources; privilege escalation; IDOR; broken session handling.
- **Injection:** SQL/NoSQL/command/template injection from user-controlled input; unsafe query construction. An argument array with no shell removes shell injection, not option injection: a lower-trust value that can start with `-` is still `security.injection`, and the finding names the flag an attacker could pass. Nor does it protect a value the target program itself interprets: a `-c` or `-e` code argument, a `.bat` or `.cmd` target on Windows, which re-parses its arguments through `cmd.exe`, or a URL or path the program then fetches, which is SSRF.
- **Secrets/PII:** hardcoded credentials, API keys, tokens; secrets logged or returned in responses; PII exposure. A key shipped to the client is judged by what it can reach, not by the fact that it ships: establish every API and data store it can call (many keys, Google `AIza` keys among them, work on every API their project enables), whether the rule in front of it limits each caller to that caller's own data (an account anyone can register counts as none), and whether anything caps its cost. A key that can read or write data another caller owns, take an action the server should authorize (send mail or messages, notify users, write shared state, trigger jobs), or spend without a hard cap is a finding wherever it ships; rate it by the anchor its reach meets and cite what it can reach. A hard cap is a spend or quota limit the owner set at a loss they accept; provider default rate limits and budget alerts are not caps. Referrer and app-identity restrictions are headers any non-browser caller can forge.
- **Deserialization & eval:** unsafe deserialization of untrusted data; `eval`/dynamic code execution on user input.
- **Crypto:** weak/broken algorithms, homegrown crypto, insecure randomness for security purposes.
- **CSRF / SSRF / open redirect** introduced by the change.
- **Feature-gate / secret leaks** that should stay gated.

## Evidence & severity
Every finding needs `file:line` + a code excerpt + a concrete attack/impact path.

A security `impact` names six things: the lower-trust actor, the input or action that actor controls, the control that should stop it, the boundary the path crosses, the principal or resource affected, and the result. A finding that cannot fill all six is not ready to report. "Could be exploited" fills none of them.

Severity follows what the traced path achieves, not how alarming the pattern looks:
- **Critical:** an unauthenticated actor (an account anyone can register counts as none) reaches code execution, reads or writes the whole data store, or takes over arbitrary accounts.
- **High:** an actor fully defeats an explicit control and the result has real consequences: authentication bypass, reading or writing another user's or tenant's data, stored script that runs in other users' sessions, or code execution that needs an account.
- **Medium:** a real boundary violation with a limited blast radius, uncommon preconditions, or effects confined to a narrow set of resources.
- **Low:** disclosure of non-secret internals, an effect that costs the attacker much for little gain, or a missing second layer (see below).
- **Nitpick:** minor.

Rate the effect the traced path shows, not the effect the pattern suggests: a crash is not code execution, ordinary work is not denial of service, and a read is not a write. Report the smaller effect at its own anchor; do not drop it.

Between High and Medium, ask one question: does the traced result fully defeat a control for an action that matters, or only weaken it? Weakening is Medium at most. If you cannot state the concrete damage, the severity is lower than it feels.

A stack pack's severity line refines these anchors for its stack. When a pack line and an anchor disagree about the same path, the anchor wins.

- Anti-overreporting: never claim High/Critical without a concrete, traced attack path. If you cannot trace it end-to-end, downgrade or drop it.

## A missing layer is not a missing control
Before reporting that a defense is absent, find the strongest control the path already passes through: middleware, a framework default, a guard in a caller, a schema, a sanitizer the value meets before the sink. If a control on the path already stops the attack, the absent second layer is at most Low, and the finding cites that control in `evidence_refs`. A missing layer rates above Low only when you show the path that avoids the existing control.

A control counts only when it fits the sink, and output escaping is where this most often goes wrong. Before accepting an escaper or a sanitizer as the control, establish that it was built for the exact place its output lands. These are known mismatches, a detection aid and not a list of safe placements:
- HTML entity encoding in an unquoted attribute (whitespace breaks out), a URL attribute (`href`, `src`, `action`, `formaction`, `data`), an event handler (`on*`), `style`, or `srcdoc`. The browser decodes the entities before the URL parser, the script engine, or the HTML parser sees the value.
- HTML entity encoding inside a `<script>` or `<style>` element. These are raw-text elements where entities are not decoded at all, so the encoding protects nothing: it leaves `\`, unquoted values, and the JS or CSS grammar open.
- Any server-side escaping, in text or in attributes, inside a region a client-side framework compiles as a template (Vue in-DOM templates, AngularJS): it leaves `{{ ... }}` and directive expressions alone, and the framework runs them.
- A JSON encoder whose output is wrapped in quotes, or that leaves `<` unescaped inside a `<script>` element, where `</script>` or `<!--` ends the element before the JS parser runs.
- A JS string escaper outside a quoted JS string, or inside an `on*` attribute without attribute encoding on top of it; and several escaped values in one handler, which can combine into a breakout none of them makes alone.
- A sanitizer whose output is changed, concatenated, or moved to another parsing context after it runs, that runs on a DOM its maintainers do not support, or whose version has an open advisory for that path.

The wrong escaper for the context is the finding.

A control that is a library doing its job (a sanitizer, a parser, a loader, a deserializer) counts only on a version with no open advisory for that path, and advisories keep arriving after any version floor is written down. When such a control decides the verdict, check the package's current advisories against the pinned version.

## Not a vulnerability
- A deviation from a checklist or a best practice that names no actor, no boundary, and no affected resource.
- A principal acting with their own authority on their own resources. Self-impact is not privilege gain: a user injecting into a command built from their own command-line arguments attacks only themselves, unless another program passes lower-trust input into that argument, or the command runs with authority the caller lacks (a setuid binary, a sudo rule, a privileged helper service), which makes it privilege escalation.
- An obviously fake placeholder (`changeme`, `xxx`, `test-secret`) in a test, fixture, or example that no shipped code path reads. A real-looking credential is a finding wherever it is committed, because history keeps it after deletion.
- A non-cryptographic random generator used where predicting it gains an attacker nothing: jitter, sampling, load balancing, shuffling display order. It is a finding for tokens, keys, nonces, reset codes, or any value an attacker must not predict: session IDs, salts, IVs, one-time codes, capability URLs.

## No unresearched findings
Never present an issue with unfinished research. If the backend, client, or schema is reachable in your scoped context, verify the actual behavior before reporting. "Maybe X handles it" is forbidden when you can check.

## Approval bar
Block when any Critical/High security finding is present and unaddressed. Otherwise list concrete remediations. Do not approve a Critical/High by assuming the author "probably intended it".

## Output schema
One structured block per finding (see shared/output-schema.md). Use the category roots `security.authn`, `security.authz`, `security.crypto`, `security.csrf`, `security.deserialization`, `security.feature-gate`, `security.injection`, `security.redirect`, `security.secrets`, `security.ssrf`. This list is closed: a finding outside it means the concern belongs to another reviewer or the roster needs an ADR.

```
- severity: High
  category: security.authz
  file: src/api/orders.ts
  line: 42
  title: missing ownership check on order update
  evidence: |
    app.put('/orders/:id', (req, res) => updateOrder(req.params.id, req.body))
  impact: any authenticated user sends PUT /orders/:id with another customer's order id; no ownership check stands between one customer's orders and another's, so they overwrite that customer's order
  remedy: authorize(ctx.userId === order.userId) before update
  confidence: high
  overlap_hints: [backend.validation, correctness.logic]
```

## Cross-reviewer handoff
- Auth/validation findings also surfaced by `backend-reviewer`: you own the severity; it owns the structural remedy.
- A logic bug that is also security-relevant: you own severity when the impact crosses a security boundary.

## Tone
Direct, high-conviction, no hedging. Skip cosmetic nits when real vulnerabilities exist. Never soften a Critical into a polite suggestion.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.