Help us improve
Share bugs, ideas, or general feedback.
From cybersecurity-skills
Audits REST, GraphQL, and RPC APIs against OWASP API Security Top 10, focusing on BOLA, authentication, and access control.
npx claudepluginhub briiirussell/cybersecurity-skills --plugin cybersecurity-skillsHow this skill is triggered — by the user, by Claude, or both
Slash command
/cybersecurity-skills:api-auditThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Perform a systematic security audit of API endpoints against the OWASP API Security Top 10 (2023). Distinct from `owasp-audit` — that's category-driven over a whole codebase, this is surface-driven over the API contract.
Identifies OWASP API Security Top 10 (2023) vulnerabilities like BOLA in REST, GraphQL, gRPC APIs during audits, with code examples and detection patterns for Express, Flask, Spring Boot, Go.
<!-- AUTO-GENERATED by export-plugins.py — DO NOT EDIT -->
Assesses REST, GraphQL, and gRPC API endpoints against OWASP API Security Top 10 risks using automated and manual testing techniques.
Share bugs, ideas, or general feedback.
Perform a systematic security audit of API endpoints against the OWASP API Security Top 10 (2023). Distinct from owasp-audit — that's category-driven over a whole codebase, this is surface-driven over the API contract.
Use owasp-audit for the codebase as a whole. Use this when you need a focused pass over every endpoint with API-specific bypass patterns. They cross-reference each other where categories overlap.
The #1 API vulnerability by exploitation frequency. Every endpoint that accepts an object ID needs an explicit ownership check before reading or mutating.
/users/:id, /orders/:id, /projects/:id), verify a query like findFirst({ where: { id, userId } }) runs before any data access — not findById(id) then a separate checkposts.find(id).user.creditCard returns another tenant's card if the relation isn't guarded. Audit every .include, .with, includes, eager-loaded relationparams.id, req.params.<id>, formData.get("<id>"), ORM .findById( / .find( without a where clause, GraphQL resolvers that take an id arg and call .findUniquealg: none accepted by the verifiercrypto.timingSafeEqual / equivalentprocess.env.X without a presence check — when X is unset, "Bearer ${undefined}" is a valid literaljwt.verify, jsonwebtoken, Bearer ${process.env, jwt.decode (without verify), verify.*algres.json(user) leaks password_hash, stripe_customer_id, internal flagsmutation UpdateUser($id, $role) succeeds because the resolver only checks "is the user logged in"res.json(<entity>) without explicit field projection, Object.assign(record, req.body), Mongoose findByIdAndUpdate(id, req.body), Drizzle .update().set(req.body), Sequelize update(req.body), GraphQL resolvers without role checks?limit=10000000 returns 10M rowsuser { posts { user { posts { ... } } } } runs foreverPOST /api/v1/users/me to POST /api/v1/users/<other_id>DELETE /admin/users/123 blocked, but POST /admin/users/123/delete succeedsreq.user.role === "admin" where role is set from a header the client controlsPUT /:id is guarded but POST /:id/send writes the same row without the guard. Run sister-route audit (see owasp-audit)owasp-audit A10 for the full bypass matrix (9+ patterns including IPv4-mapped IPv6, trailing-dot, cloud metadata, encoded IPs)redirect: "follow" (default) on fetches with user-controlled URLs lets an attacker bounce through a 302 into the metadata serviceAccess-Control-Allow-Origin: * combined with Allow-Credentials: true (browsers refuse this; servers shouldn't ship it)Origin header without an allow-list — any origin gets allowedowasp-audit A05 for the full baseline values/v1/) still live and unpatched alongside /v2/ — attackers prefer the version with fewer checks*-staging.fly.dev left open)/__debug, /__db, /.well-known/internal/, framework-default routesapp.get, router.get, pages/api/, app/api/ directory contents; reconcile against the published API contractprovider.user.profile_url, XSS via provider.user.bio rendered un-escaped__schema, __type queries return the full schema)GET accepted on state-changing endpoints (CSRF risk + cache poisoning)application/json but accepts application/x-www-form-urlencoded and parses inconsistently/files/../../etc/passwdowasp-audit A02 type-coercion + A04 multi-tenant signature N-way matching)/webhooks/stripe) without IP allow-list or signatureOrigin: https://evil.com; observe the browser blocks, not the servertsc --noEmit + build success ≠ fix verified. See also owasp-audit's Verify Fixes at Runtime + Second-Opinion Pass — same playbook applies.
Findings have three dispositions (Fixed / Deferred / Accepted Risk) per the owasp-audit convention. For every finding:
#### [SEVERITY] APIN: [Title]
**Endpoint:** `METHOD /path/to/endpoint`
**Handler:** `path/to/handler.ts:42`
**CWE:** CWE-XXX
**Description:** [What the vulnerability is]
**Proof of concept:**
[curl / request showing the bypass]
**Vulnerable Code:**
[snippet]
**Remediation:**
[fixed snippet]
**Verification:** [Concrete adversarial input and the observed response that proves the fix holds]
Produce an executive summary grouped by API category, plus an inventory of every endpoint with one of: