Webapp pentest checklist
Skill Dolphinllc/claude-security-skills/skills/offensive/web/webapp-pentest-checklist
Defensive security skills for Claude Code and the Claude Agent SDK — web applications and generative AI systems.
npx -y skills add Dolphinllc/claude-security-skills --skill webapp-pentest-checklistAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Authorized self-pentest checklist for web applications you own. Walks the OWASP Web/API Top 10 against a locally-running target, discovering the base URL via env or entrypoint files (never hardcoded). Use when the user asks to "pentest", "attack", "probe", or "test the security of" their own running web app and the framework is unknown or mixed. For framework-specific deeper checks, use express/django/spring-boot/nextjs/nestjs/fastapi attack-probe skills.
SKILL.md
4.7 KB, as published. Nobody here has run it
Web App Self-Pentest Checklist
Authorized, rate-limited probe of a web app running on the user's own machine. Follow the shared probing conventions for authorization, target discovery, and output schema.
Procedure
- Authorization preflight. Default to
localhost/127.0.0.1. If a non-loopback host is named, require explicit user confirmation in chat. - Discover base URL per
PROBING.md(env → entrypoint → ask). Recordtarget.base_urlandtarget.discovered_via. - Confirm liveness.
GET /andGET /healthz//health(if any). If unreachable, returnPREFLIGHT-BLOCKED. - Enumerate routes from the app's source if you can read it; otherwise crawl from
/to depth 2 (max 50 URLs) and stop. - Run the rule pack below. Stop at the first request budget hit (default 200 requests).
Rules
| ID | Severity (if confirmed) | Probe | Confirmed when |
|---|---|---|---|
| WEB-INFO-001 | low | Fetch /.env, /.env.local, /.git/config, /.git/HEAD, /package.json, /composer.json | Body is a non-404 file containing expected markers (DB_, API_KEY, [core]) |
| WEB-INFO-002 | medium | Fetch /server-status, /.well-known/security.txt, /robots.txt, /sitemap.xml, /api-docs, /swagger, /openapi.json, /graphql | Returns a populated body that exposes routes/internals |
| WEB-AUTH-001 | high | For each mutating route discovered, send the request with no auth header / cookie | 2xx response identical to authenticated response |
| WEB-AUTH-002 | high | Replay an authenticated request from user A's session against /users/{B}/... | 2xx instead of 403 = IDOR |
| WEB-AUTH-003 | medium | Send Authorization: Bearer eyJhbGciOiJub25lIn0.<base64-mod-payload>. (alg=none JWT) | 2xx accepted = JWT alg confusion |
| WEB-XSS-001 | high | Submit "><svg/onload=__probe('xss')> to each text input; render-back endpoints reflect it un-encoded | <svg/onload appears verbatim in HTML response (not entity-encoded) |
| WEB-SQLI-001 | high | Append ' and ' OR '1'='1 to each numeric/string param; compare against baseline | Different status code OR DB error string in response |
| WEB-SSRF-001 | high | If app fetches URLs (preview, image proxy, webhook), submit http://127.0.0.1:1, http://169.254.169.254/latest/meta-data/ | Connection succeeds / metadata returns |
| WEB-OR-001 | medium | Submit redirect param values like //evil.test, https://evil.test to login/return URLs | 30x with Location: outside same-origin |
| WEB-CORS-001 | high | Send Origin: https://evil.test with credentials to authenticated endpoint | Access-Control-Allow-Origin reflects origin AND Allow-Credentials: true |
| WEB-CSRF-001 | high | State-changing endpoint reachable via cross-origin form POST without CSRF token | 2xx on a request lacking the CSRF header/token |
| WEB-UPLOAD-001 | high | Upload file with double-extension shell.php.jpg / wrong MIME / SVG with embedded script | Stored and served with executable type / Content-Type: image/svg+xml rendered |
| WEB-MASS-001 | medium | Submit extra fields to update endpoints (role: "admin", is_staff: true) | Field accepted and persisted = mass-assignment |
| WEB-ERR-001 | low | Trigger errors via /?id[]=1, malformed JSON, type confusion | Stack trace in 500 response = info disclosure |
| WEB-RATE-001 | medium | Send 10 rapid POST /login with random passwords | All accepted without 429 / lockout = no rate limiting |
Workflow notes
- Reserve mutation probes (
WEB-MASS-001,WEB-UPLOAD-001,WEB-CSRF-001) for endpoints clearly safe to write to (or skip if uncertain). - For
WEB-AUTH-002(IDOR), require the user to provide two test accounts; otherwise mark asinfo: not-tested. - Render IDs from the running app's data, never inject random UUIDs that match nothing.
Wrong-target safety
If the resolved base_url host is not in {localhost, 127.0.0.1, ::1, *.localhost} AND was not explicitly confirmed by the user this session — return a single PREFLIGHT-BLOCKED finding and stop.
References
- OWASP Web Security Testing Guide: https://owasp.org/www-project-web-security-testing-guide/
- OWASP API Security Top 10: https://owasp.org/API-Security/
- PortSwigger Web Security Academy: https://portswigger.net/web-security