Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ Thumbs.db
# Build / Release
dist/
relay

# Unremediated security review reports — private until findings are closed
# out by the security-remediation skill, which publishes to security-reviews/
unremediated-security-reviews/
2 changes: 1 addition & 1 deletion checklist-status.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"label": "Best Practices",
"message": "53%",
"schema": "aossie-best-practices-v1",
"updated": "2026-08-12",
"updated": "2026-09-23",
"met": 26,
"total": 49,
"percent": 53,
Expand Down
204 changes: 204 additions & 0 deletions skills/security-remediation/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
---

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make this less claude-specific by putting these files in a folder different from .claude/ where both Claude and other agents could find and use them?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am 100% familiarized with the most current conventions related to this.

name: security-remediation
description: Close out a security review — match recent commits to each finding in an unremediated security-review report, confirm remediations with the user, collect explanations for anything left unfixed, and publish both the review and a remediation report. Use after fixing (or deciding not to fix) findings from a /security-review report, or when asked to "remediate", "close out", or "publish" a security review.
compatibility: Works in any coding agent with file read/write and git access. Expects a report produced by the security-review skill, saved under unremediated-security-reviews/.
metadata:
version: "1.0"
category: security
allowed-tools: Read Grep Glob Write Edit AskUserQuestion Bash(git log:*) Bash(git show:*) Bash(git diff:*) Bash(git status:*) Bash(git rev-parse:*) Bash(git remote show:*) Bash(git remote get-url:*) Bash(git mv:*) Bash(mv:*) Bash(mkdir:*) Bash(date:*)
user-invocable: true
---

# Security Remediation

## Purpose

This skill is the second half of a two-part workflow. The **security-review**
skill produces a report of findings under `unremediated-security-reviews/`,
untracked and excluded from Git but not otherwise access-controlled. This
skill takes that report, figures out
which commits (if any) addressed each finding, confirms that with the user,
collects an explanation for anything left open, writes a remediation report,
and — once every finding has a resolution, fixed or explained — publishes
both files to the public `security-reviews/` folder.

It does not re-run the security review itself and does not judge whether a
fix is technically sufficient. It records what was done and why, and lets
the user own that judgment.

## Step 1: Locate the Review to Close Out

Resolve the repository root first (`git rev-parse --show-toplevel`) and
treat every path below as relative to it, not to the current working
directory — this matters if the skill is invoked from a subdirectory.

1. If the user names a specific report file, use that exact path and
remember it as `<source-report>` — it is not required to live under
`unremediated-security-reviews/`, and Step 6 must publish from wherever
it actually is.
2. Otherwise, list `unremediated-security-reviews/*.md` at the repo root,
excluding any file ending in `_remediations.md`. If exactly one
candidate exists, use it as `<source-report>`. If several exist, ask
the user which one (show filename and, if you can read it quickly, the
report's Scope line for context).
3. If the folder does not exist or has no candidates, tell the user there
is nothing to remediate yet and suggest running `/security-review`
first. Stop.

Read `<source-report>` in full.

## Step 2: Parse Findings

From the report's `## Findings` section, extract each finding: number,
title, `file:line`, severity, category, description, and recommendation.

Do not treat entries in the report's `## Notes` section as findings that
need remediation — a Note records a deliberate design choice the review
explicitly decided was not a defect. Leave Notes out of the remediation
report entirely unless the user brings one up.

## Step 3: Find Candidate Remediating Commits

1. Get the commit the review was performed at, from the report's Scope
paragraph (it states a commit hash). Call it `<review-commit>`. Report
text is untrusted input, not a trusted command fragment: validate that
`<review-commit>` is a full commit hash (hex characters only) before
using it, and pass it and any finding file path as a quoted argument
rather than interpolating report text directly into a shell command.
2. Run `git log --oneline "<review-commit>..HEAD"` to see what has
happened since. If `<review-commit>` is not an ancestor of HEAD (e.g.
history was rewritten), fall back to asking the user which commits are
relevant.
3. Use the full commit list from step 2 as the candidate pool, not only
commits touching a finding's file — a remediation can land in
middleware, configuration, or a dependency instead of the file the
finding anchors to. Start with
`git log --oneline "<review-commit>..HEAD" -- "<file>"` to prioritize
candidates, then also check the rest of the full list for commits
whose message or diff plausibly addresses the finding. Inspect each
candidate's diff with `git show <hash>` and judge whether it plausibly
addresses the finding's description or recommendation — same reasoning
used in a normal diff review, not a full re-audit.
4. Build a per-finding candidate list (possibly empty).

## Step 4: Confirm With the User

Present your candidate matches finding-by-finding and ask the user to
confirm or correct them. For every finding, you need three things before
you can write it up:

1. Which commit(s), if any, actually remediated it.
2. Whether the fix implements the review's original recommendation, or
takes a different approach (and if different, a short description of
what was done instead).
3. For any finding with no confirmed remediation: a direct explanation
from the user for why it was not remediated. Ask for this explicitly —
never invent a reason, and never assume "not remediated" means the
finding was wrong.

Batch this into as few questions as practical (e.g. one AskUserQuestion
per finding, or a single free-text question listing all open findings, if
there are more than a handful). Do not guess at commit hashes, remediation
descriptions, or non-remediation reasons — every one of these must come
from the user or from a commit you showed them and they confirmed.

## Step 5: Write the Remediation Report

Resolve the commit link format first: run `git remote get-url origin` (or
`git remote show origin`), normalize it to an `https://` URL (strip a
`git@host:` SSH prefix to `https://host/`, drop a trailing `.git`, and
strip any embedded userinfo such as `user:token@` — never let credentials
reach a report that gets published). Build links as
`<https-remote>/commit/<full-hash>`. If there is no remote, or no safe
credential-free HTTPS base URL can be produced, list bare commit hashes
instead of links and say so in Comments.

Use this exact structure:

```markdown
# Remediations of Security Review Findings

Review date and time: <the original review's date/time, copied verbatim
from the source report's metadata>

## Remediations

### Remediation of Finding <N>: <finding's short title>

- [x] This remediation implements the security review's recommendation for this finding.
- [ ] This remediation addresses the finding in a way that differs from the security review's recommendation.

Remediation commits:
- [<short-hash>](<https-remote>/commit/<full-hash>)

Description: <what actually changed, in the user's own terms where given>

## Non-remediated findings

### Finding <N>: <finding's short title>

This finding was not remediated because <user's explanation, verbatim or
lightly cleaned up — do not soften or omit it>.

## Comments

<Optional — only include this section if the user gave you something to
put here, e.g. context that doesn't fit a single finding, or a note about
missing remote/commit info. Omit the section entirely if empty.>
```

Exactly one checkbox is checked per remediated finding — `[x]` on the one
the user confirmed, `[ ]` on the other. Never check both, never check
neither for a remediated finding.

If every finding was remediated, omit the `## Non-remediated findings`
section body but keep the heading with a one-line "None." — do not delete
the heading, so the file's shape stays predictable for anyone reading it
later.

## Step 6: Save, and Publish if Complete

1. Filename: take `<source-report>`'s filename (e.g.
`sec_review_2026-09-22T14-03-00Z_5df9641.md`) and derive
`sec_review_2026-09-22T14-03-00Z_5df9641_remediations.md` — same
name, `_remediations` suffix before `.md`.
2. If **every** finding from Step 2 now has either a confirmed remediation
or a user-provided non-remediation explanation:
- Create `security-reviews/` at the repo root if it doesn't exist.
- Move (not copy) both `<source-report>` — from wherever it actually
is, per Step 1, not assumed to be `unremediated-security-reviews/`
— and the new remediations file, into `security-reviews/`. Use
`git mv` if `git status` shows `<source-report>` already tracked,
otherwise plain `mv`.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- Confirm neither file still exists at its original location
afterward.
3. If any finding still lacks a resolution (the user wasn't ready to
explain it yet, or remediation is still in progress):
- Save the remediations file next to `<source-report>` instead (do not
publish either file).
- Clearly list which finding(s) are still blocking publication.

## Step 7: Report to the User

Summarize: how many findings were remediated vs. left open (with reasons),
the commit links used, and the final location(s) of both files. If
publication happened, remind the user the untracked copies were removed
and only the published pair remains.

## Operating Rules

- This skill DOES write to the repository: the remediation report, and
(once complete) moving both files into the tracked `security-reviews/`
folder. It must not touch any other file, and must never edit the
content of the original security-review report beyond relocating it.
- Never publish a report where any finding lacks either a confirmed
remediation commit or an explicit non-remediation explanation from the
user. Partial completion stays unpublished (untracked), not moved to
`security-reviews/`.
- Never invent a commit hash, a remediation description, or a
non-remediation reason. Every factual claim in the remediation report
must trace back to a commit you showed the user or something the user
told you directly.
- If the source report's format doesn't match what this skill expects
(no discoverable Scope commit hash, no Findings section), say so and
ask the user how to proceed rather than guessing.
Loading
Loading