Security review with a confidence gate - a finding exists only with a concrete exploit scenario and a high/medium/low confidence rating; everything else goes to a worth-hardening list, never inflated. Sweeps five surfaces: auth gates, secrets hygiene, injection and unsafe sinks, unsafe deserialization/crypto/transport, and LLM tool-use trust boundaries. Reports only, never fixes. Use when the user asks for a security review or to check vulnerabilities, secrets, or auth.
Scanned 9/28/2026
Install to Claude Code
npx -y skills add AaravChadha/acstack --skill secure --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Secure?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/aaravchadha-secure)More formats (shields.io, HTML) on the badges page.
---
name: secure
description: "Security review with a confidence gate - a finding exists only with a concrete exploit scenario and a high/medium/low confidence rating; everything else goes to a worth-hardening list, never inflated. Sweeps five surfaces: auth gates, secrets hygiene, injection and unsafe sinks, unsafe deserialization/crypto/transport, and LLM tool-use trust boundaries. Reports only, never fixes. Use when the user asks for a security review or to check vulnerabilities, secrets, or auth."
argument-hint: "[path | surface | notes]"
allowed-tools: Read, Grep, Glob, Bash(git log:*), Bash(git ls-files:*), Bash(git status:*), Bash(grep:*), Bash(ls:*)
---
# /secure — findings you can exploit, not vibes you can fear
A security report full of maybes trains people to ignore it. This skill
earns attention the only way that works: every finding is a story a
specific attacker could act on, rated by how sure the evidence is —
and everything short of that bar is filed as hardening, not findings.
`Adjacent skills:` /qa (exercises functionality; /secure hunts
vulnerabilities — /qa's auth anomalies land here) · /audit code
(general defects; /secure is security-only) · /migrate-check (DB change
safety; shares the structurally-read-only stance).
<!-- acstack:runtime -->
Run before the skill's steps — per invocation, not per session (4.36); failures degrade to markdown:
```bash
link="$(readlink "$HOME/.claude/skills/health" 2>/dev/null || true)" # empty = not symlinked
pack="$(dirname "$(dirname "$link")")" # NEVER trust this unless $link was non-empty
if [ "${link#/}" != "$link" ] && [ -x "$pack/bin/acstack-config" ] && ! "$pack/bin/acstack-config" runtime | grep -q '=off'; then
"$pack/bin/acstack-config" || true # resolved keys, with sources
"$pack/bin/acstack-update-check" || true # ≤1 fetch/day; silent ONLY if already checked today
"$pack/bin/acstack-recall" || true # LEARNINGS.md + bug-class names, capped 3KB
else
echo "runtime off — proceeding without recall/update-check"
fi
```
<!-- /acstack:runtime -->
<!-- acstack:principles -->
## Operating principles
- Be direct. Push back in writing when the plan or the user is wrong. No sycophancy.
- Never delete a decision. Supersede it: `~~old~~ → **Verdict (YYYY-MM-DD):** new call — reason.`
- Never fix, tune, or delete a test or eval case to raise a score. Log the miss honestly and leave the case unchanged.
- Name exact things: regex patterns, function signatures, model names, before → after numbers. Never "fixed bugs".
- Attribution: follow the project's `attribution` setting (default `none`) — no AI-tool mentions in generated docs, no attribution trailers in commits or PRs. Commit with explicit `-m`/`-F` messages only.
- Config: read `.claude/acstack.md` at the project root (fall back to `~/.claude/acstack.md`) before acting. `## Settings` keys override pack defaults; a `## <skill-name>` section overrides both. Unknown keys and sections are ignored.
- Docs: BRIEF.md (frozen seed) / PLAN.md (living plan) / JOURNAL.md (rolling journal). If the repo uses legacy names (PLANNING_PROMPT.md / PLANNING.md / STATUS.md), use those instead — never create both.
- Recall: if `LEARNINGS.md` exists at the project root, read it before starting.
- Conduct: follow the `acstack-conduct` block in this repo's AGENTS.md — the word is the mode; the user sets the pace.
- Hackathon lane: if the project's AGENTS.md carries the `acstack:hackathon-lane` block, only `/do` changes the repository during the event. Any other skill that would write a tracked file, commit or push says what it would have done and stops; a change that is not a task goes through the lane's operator route.
<!-- /acstack:principles -->
## The confidence gate
A finding exists ONLY if it carries both:
- **An exploit scenario** — who sends what request or input, and what
they obtain. Concrete: "an authenticated user swaps the `id` in
GET /api/orders/:id and reads another user's order", not
"IDs might be guessable".
- **A confidence rating:**
- `high` — demonstrated, or the vulnerable path is directly evidenced
in code with no unmet precondition.
- `medium` — the code path exists; a precondition (config, reachable
route, data shape) is unverified.
- `low` — pattern-level suspicion; the mechanism is plausible but not
traced.
**A written justification demotes a finding; it never deletes one.** Where
the code carries an inline comment explaining why a risk is accepted — a
pickle load documented as reading a repo-shipped file, a `verify=False`
marked as talking to a pinned internal host — the finding moves to **Worth
hardening** with that reason quoted. It does not silently disappear. Two
reasons: the justification may be stale or wrong, and a reader deserves to
see the trade someone made rather than a clean report that hides it. If the
stated reason is *itself* incorrect, that is a finding, argued against the
reason rather than the line.
Suspicions that can't clear the gate go to **Worth hardening** — a
separate list, honestly labeled. Promoting a maybe into a finding is
the security version of inflating an eval score; the never-inflate rule
applies verbatim.
## The five surfaces
Checklists and grep patterns per surface live in
`references/security-surfaces.md`. Sweep every surface the stack has;
an argument can narrow to one path or surface. Apply the patterns with
the Grep tool — this skill grants no shell `git grep`. No Grep tool in the
harness? Use `grep -rnE`, never `git grep`.
1. **Auth gates.** The rival-user test: can authenticated user A reach
user B's data by swapping an ID. Unauthenticated reach of gated
routes. Server-side checks missing behind client-side hiding.
2. **Secrets hygiene.** .env-class files tracked or recoverable in
history (in history = burned → "rotate", not just "delete"); the
gitignore-negation trap; hardcoded keys and tokens; secrets leaking
into error messages or logs.
3. **Injection surface.** String-built SQL and raw-query escapes out of
the ORM; shell interpolation of user input; path traversal into file
operations; unsanitized HTML sinks.
4. **Unsafe deserialization, crypto, and transport.** The `pickle`
family, `yaml.load`, and `torch.load` are arbitrary code execution
whenever the blob crosses a trust boundary; ECB and `createCipher`
are key-handling defects; `verify=False` and its cousins switch off
the only thing making TLS meaningful; unsafe XML parsing is XXE. Each
finding names where the input comes from — a load of a file the repo
itself ships is not a finding.
5. **LLM tool-use trust boundaries.** Untrusted content flowing into
tool calls or system prompts; over-scoped tool permissions;
prompt-injection paths from user-supplied documents; model output
executed or rendered without checks.
## Stance: structurally read-only
/secure reports; it never fixes, not even the one-liner. Fixes change
attack surface and deserve their own reviewed commits. Each finding
carries a fix DIRECTION (one line); the user decides what gets built.
One honest caveat: the `git log` grant accepts `--output=FILE`, and a
prefix grant cannot forbid a flag — so the tool set is read-only in use,
not provably read-only under every argument. /secure never writes; the
residual is recorded in check.sh §13.
## Report shape
First line is the verdict. The count form is used whenever there is at
least one finding at ANY confidence — `<N> findings (<X> high, <Y>
medium, <Z> low)` — so a medium-only report never hides behind
"no high-confidence findings". `no findings` is stated only when the
count is truly zero; `no high-confidence findings, <Y> medium / <Z> low`
when there are lower-confidence findings but no high ones. Then:
- **Findings**, severity-ordered: surface · `file:line` · the exploit
scenario · confidence (with what evidence sets it) · fix direction.
- **`Safety checks:`** the exact grep/git commands run per surface and
what they matched — the sweep must be reproducible.
- **Worth hardening:** the below-gate list, one line each.
- **Scope:** paths and surfaces covered, and NOT covered — a partial
sweep that reads as total is itself a security failure.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!