Skip to content
Back to skills

Qa Sec

ASecurity

Defensive security review of a web app you own, driven by agents that operate the real app — audit headers, cookies, token handling and the JS bundle passively; hunt broken access control across roles (forced browsing, IDOR/BOLA, privilege escalation, session invalidation); and probe input handling and business-logic abuse with benign markers. Detection-first — it proves a hole exists and stops, never extracting data, persisting payloads or stress-testing. Use when asked to "check the securit...

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 22, 2026
testinggoshellsqlnodetestinggitsecurity

Works with

  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 22, 2026

npx -y skills add victoraguilarsantamariadev/qa-explore --skill qa-sec --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Qa Sec?

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

Security grade badge for Qa Sec
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/victoraguilarsantamariadev-qa-sec/badge)](https://www.skillsdirectory.com/skills/victoraguilarsantamariadev-qa-sec)

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: qa-sec
description: Defensive security review of a web app you own, driven by agents that operate the real app — audit headers, cookies, token handling and the JS bundle passively; hunt broken access control across roles (forced browsing, IDOR/BOLA, privilege escalation, session invalidation); and probe input handling and business-logic abuse with benign markers. Detection-first — it proves a hole exists and stops, never extracting data, persisting payloads or stress-testing. Use when asked to "check the security of the app", "look for vulnerabilities", "is this app safe", "audit access control / permissions", "find security holes before the client does", or to add a security pass to an existing qa-explore setup. Sibling of qa-explore; same engine, different question.
---

# qa-sec

qa-explore asks *is this broken?*. qa-sec asks *can someone abuse this?* — on an app **you own**, so you can fix it.

It is a **review, not an attack**: every pass finds a hole, proves it exists, and stops there.

## The passes

```
Surface          map what is actually exposed: inputs, ids, uploads, redirects, privileged actions
Passive          (always) headers/CSP/CORS · cookies + token lifecycle · secrets & source maps in the
                 bundle · leaky error pages · HIGH/CRITICAL dependency advisories
Access-control   (the expensive bugs) forced browsing · hidden-but-not-blocked actions · IDOR/BOLA on
                 ids · mass assignment · session/tenant boundaries — one agent per role
Input & logic    (safe-active only) reflection · injection error signals · traversal · open redirect ·
                 SSRF · upload type enforcement · server-side validation · BUSINESS-LOGIC abuse
Verify           an independent skeptic reproduces each serious finding, in both directions
```

Findings come out in the **same shape qa-explore produces**, so `/qa-gate` blocks on them (its `blockOnAccessControl` is on by default) and the report/fix loop works unchanged.

## Engine (invoke via the Workflow tool; do not inline)
- `${CLAUDE_PLUGIN_ROOT}/skills/qa-sec/engine/qa-sec.workflow.js`
- Config: reuses the project `qa.config.json` (baseUrl, login, **roles**, allowedHosts, shotsDir, domainNotes, e2eDir, sourceHints) plus a `security` block.

## Before it runs — the two gates

1. **`security.authorized` must be `true`, with `security.scope` naming the system and who authorised it.** Without it the engine returns immediately and does nothing. This is a live system: someone owns that decision, and the config is where it is recorded.
2. **Scope is `allowedHosts`** (defaults to the `baseUrl` host). Agents may not send a request anywhere else, follow a finding off-host, or touch another machine. A third-party host that turns up is recorded as out-of-scope, not probed.

Then, as with qa-explore: **state the resolved target, the intrusiveness and the scope, and get a go-ahead** before the run — louder if it looks like production.

## Intrusiveness

| `security.intrusiveness` | What it sends | Good for |
|---|---|---|
| `passive` *(default)* | nothing beyond normal use — it logs in, browses, and reads the headers, cookies, tokens, bundles and errors the app already serves | anything, any time, including production |
| `safe-active` | the above **plus** benign markers into inputs the app exposes and calls to endpoints the app itself calls, with altered parameters | staging / pre-prod, or production with the owner's explicit say-so |

Under **both**, these are hard rules the engine writes into every agent's prompt: stop at proof; never read real data beyond the one record that proves the exposure, redacted; never modify, delete, or plant anything that persists; no load/stress/timing attacks; login attempts capped (`security.maxLoginAttempts`, default 8) and only to check that lockout exists; no credentials other than the configured ones; benign markers only — no destructive SQL, no shell payloads.

## How to run

1. **Resolve config.** Read `qa.config.json` for the target, `login`, `allowedHosts`, `shotsDir`, `domainNotes` and `e2eDir`, plus the `security` block. Check `security.authorized` and `scope`; if they are missing, **ask the user to confirm they own this system and write it into the config** rather than passing the flag yourself.

1b. **Check the evidence dir.** `node <qa-explore engine>/evidence.mjs check <shotsDir>` — the HARs this run captures hold session tokens, and `shotsDir` must be on disk, not a tmpfs.

2. **Declare a second role.** The access-control pass is *much* stronger with two accounts (one lower-privileged): most of what it hunts is one user reaching another user's data. With a single role it still runs, but it says in its notes what it could not test. If the project has no second account, offer to have one created.

3. **Run.** `Workflow({ scriptPath: "<engine>/qa-sec.workflow.js", args: <config> })`. Returns one entry per pass, each with `checked` (including the clean results) and `findings`.

4. **Synthesize.** Write `<shotsDir>/INFORME-SEGURIDAD.md`: group by **proven + confirmed** first, then severity, then the hardening list. For each finding give the impact in one sentence, the redacted repro, and the fix. Keep the `checked` lists — *"CSRF is protected, SameSite=Lax + token on every mutation"* is as useful to the reader as a finding. Call out anything `proven: false` as what it is: a suspicion that needs a deeper look.

5. **Report — carefully.** If a `tracker` is configured, file security findings as **confidential** issues (GitLab `confidential: true`; GitHub: a private security advisory, or a private repo — never a public issue). **Never attach the HAR or storageState**: they contain live session tokens. Screenshots only, and only after checking them.

6. **Prune the evidence.** Same step as qa-explore (`evidence.mjs prune`), and it matters more here: the HARs hold tokens and possibly personal data. Keep only what a confirmed finding needs.

7. **LEARN.** A finding rejected as intentional goes into `security.knownAccepted` (with the reason) so the next run does not re-raise it — the security equivalent of `domainNotes`. An accepted risk is a decision, and it belongs in writing.

## Notes
- **Cadence:** `passive` on every release (it is cheap and catches regressions in headers/cookies/bundle); `safe-active` against staging before a release, or after a change to auth, permissions, uploads or payments.
- **It does not replace a pentest.** No authenticated fuzzing at depth, no chained exploitation, no infrastructure, no social engineering. It catches the flat, common, expensive things — the ones that are embarrassing to be told about by someone else.
- **Access control is the one to care about.** Headers and cookies are worth fixing but rarely the breach; one user reading another's data is. That is why it gets its own pass and why `/qa-gate` treats it as non-negotiable.
- **Dependencies are read from the repo, not the app** (`npm audit --omit=dev`, `osv-scanner`, `trivy`), and only HIGH/CRITICAL affecting shipped code.

Files in this skill

  • SKILL.md6.9 KB
  • engine/qa-sec.workflow.js24 KB

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.