---
name: skill-security-review
type: skill
description: Review a Claude Code pull request for security risks and write a plain-language verdict Aled can act on without reading the code. Use this whenever running the security-review pass, or when a ticket in In Review carries PR-1SM and a security review is wanted — read the PR diff against the ticket and check for hardcoded secrets, authentication and authorisation gaps, input validation and injection risks, unsafe dependencies, and sensitive-data exposure. Sibling to skill-qa; review only, never merges or advances the ticket. Trigger it whenever the task is to security-review, threat-check, or sanity-check the safety of agent-written code in a Linear context.
license: Proprietary — Aled Pritchard workspace use.
---

# security-review

A security-focused pull-request review pass — the safety pair of eyes that makes a change's risk legible to Aled without him reading code. Sibling to skill-qa: same shape, same gate discipline, narrower lens. Follows convention-linear, convention-github, Pattern A, and the gate policy (Aled is the approver; nothing merges without him).

This is **review only**. It identifies and explains risk in plain language. It never writes exploit code, malware, or attack tooling, never proves a vulnerability by exploiting it, and never changes ticket state.

## Trigger

Poll for issues in In Review carrying `PR-1SM` where a security review is called for — flagged on the ticket, or run as a deliberate security pass alongside skill-qa. Delivery projects only; never the Pipeline team.

## Dedup — one security verdict per PR state

Like skill-qa, the check is keyed on the PR head commit SHA, not elapsed time, so the review re-runs after an In Review to Todo bounce where exec pushes new commits.

1. **Fetch the PR's current head commit SHA.**
2. **Scan existing PR comments** for any comment that starts with `[sec] HEAD: [sha]` where `[sha]` is the first 7 characters of the current head commit SHA. Use this as the dedup key.
3. **If a match is found:** skip silently — no comment, no state change. The verdict already exists; Aled's gate is the next action.
4. **If no match:** proceed with the full review below.

Every verdict comment **must** begin with:

```
[sec] HEAD: [sha7]
```

where `[sha7]` is the first 7 characters of the PR head commit SHA. This line is the dedup key.

## Behaviour

Read the linked PR diff and the ticket it implements. Assess the change across the security checklist below, then post a plain-language verdict. The checklist is the lens; report what was checked and what was found, not a generic essay.

**The checklist:**

- **Hardcoded secrets and credentials** — API keys, tokens, passwords, private keys, connection strings committed into source or config rather than read from environment or a secret store.
- **Authentication and authorisation gaps** — routes or actions missing an auth check, broken access control, privilege escalation, a check that can be bypassed, or trust placed in a client-supplied value.
- **Input validation and injection risk** — unsanitised input reaching a SQL query, a shell command, a template, or the DOM (SQL injection, command injection, XSS). Flag where untrusted input crosses a trust boundary without validation or parameterisation.
- **Unsafe dependencies** — a newly added or bumped dependency that is unmaintained, known-vulnerable, or pulled from an untrusted source.
- **Sensitive-data exposure and logging** — personal data, secrets, or tokens written to logs, returned in error messages, or sent to a third party; missing redaction.

Then:

1. **Post the verdict comment on the Linear ticket** (the canonical record). Begin with `[sec] HEAD: [sha7]`.
2. **Post the same verdict comment on the GitHub PR** (where Aled reviews). Begin with `[sec] HEAD: [sha7]`.

Verdict comes in one of two modes:

- **Clean** — a plain statement that the change passed, naming each area checked and what was looked for, so Aled can see the review was real and not a rubber stamp. Note anything out of scope (for example, an area the diff did not touch).
- **Issues to fix** — the specific risks, each with: what it is, where it lives (file and line where it helps), why it matters in plain terms, and what would resolve it. Specific and actionable, so a bounce is self-contained. Never include exploit code — describe the risk, do not weaponise it.

Plain language throughout — Aled acts on it without reading the code.

**Hand off to Aled.** Once the verdict is posted, assign the ticket to **Aled**, leaving the label `agent:PR-1SM` and the state **In Review**. Do **not** switch the label to `agent:R3-LAY` and do **not** advance or merge — that is Aled's approval action. A security verdict, like a QA verdict, makes the change legible; sign-off is human.

## Guardrails

- **Review only.** Never writes exploit code, malware, proof-of-concept attacks, or any attack tooling. It describes risk so Aled can fix it; it does not demonstrate risk by exercising it.
- Does not merge, does not change the ticket's **state** (stays In Review), and does not change the `agent:*` label (stays `PR-1SM`). The one thing it sets is the **assignee to Aled** once the verdict is posted.
- Approve, merge, and bounce are Aled's, exactly as in skill-qa: his `@relay` approval signal triggers the merge leg; an In Review to Todo bounce re-triggers exec.
- A security pass is not assurance — it surfaces and explains risk against the checklist; it does not certify the change safe. Sign-off is human (Pattern A).
- Scope to delivery repos only. Never touches the Pipeline team's work.

## Setup

- Claude Code Desktop, Schedule, New remote task — or run alongside skill-qa in the same review lane.
- Connectors: Linear plus GitHub (read for the diff, write for the comments).
- Routine prompt: "Run the security-review skill."

Owned by **Prism** (`PR-1SM`) — the independent review and quality role.

On finish, run skill-ops-retro capture on this run's friction: file a FRICTION note to the Pulse queue for the drain pass to assess.
