payload-security-scan
| Type | Skill |
| Plugin | awl-web · v0.0.6 |
| Invoke | /awl-web:payload-security-scan |
| Source | plugins/awl-web/skills/payload-security-scan/SKILL.md |
When Claude uses it
Abschnitt betitelt „When Claude uses it“Scans a Payload CMS project for broken access control — missing or permissive collection/field/global access functions, unprotected endpoints, hooks that leak data. Use when asked to “review payload security”, “check access control”, “audit payload collections”, “security scan”, or before releasing a Payload project. Not for general code review (use awl-general review).
Trigger phrases: review payload security · check access control · audit payload collections · security scan
Definition
Abschnitt betitelt „Definition“Scan a Payload CMS project for access control vulnerabilities. Based on OWASP Top 1: Broken Access Control.
Trigger
Abschnitt betitelt „Trigger“Use when asked to “security scan”, “audit endpoints”, “scan payload project”, “check access controls”, or “audit permissions”.
Phase 1: Collection & Global Access Controls
Abschnitt betitelt „Phase 1: Collection & Global Access Controls“Check all collection and global configs in src/collections/**/*.ts and src/globals/**/*.ts:
-
Access config audit — For each collection/global, document the
accessproperty:create,read,update,delete— who has each permission?- Flag collections where
readorupdateis open to all authenticated users (especially if signup is open) - Flag collections with no access config (defaults to admin-only, but verify)
-
Field-level permissions — Check for sensitive fields without field-level access control:
- Permission fields on user models:
isAdmin,role,roles,permissions,userType - A user MUST NOT be able to increase their own permissions (privilege escalation)
- Sensitive data fields: API keys, secrets, 2FA secrets, tokens
- Granting
readorupdateon a collection grants access to ALL fields unless field-level access is set - Check if
@awl/payload-access-policiesis in use, recommend to use it if not
- Permission fields on user models:
-
Auth configuration — Check
src/collections/Users.ts(or equivalent):- Is
auth: trueset? - Can anyone sign up, or is it invite/admin-only? If not clear, ask the user.
- If open signup + broad collection access = anyone can read/write data
- Is
Phase 2: Custom Endpoint Discovery & Audit
Abschnitt betitelt „Phase 2: Custom Endpoint Discovery & Audit“Search three locations for custom API endpoints (relative to payload dir):
-
Collection config endpoints —
src/collections/**/*.ts- Grep for
endpointsproperty in collection configs - These register as
/api/{collection-slug}/{endpoint-path}
- Grep for
-
Next.js route handlers —
src/app/**/api/**/route.ts- Exclude auto-generated Payload routes:
[...slug]/route.ts(REST catch-all)graphql/route.tsgraphql-playground/route.ts
- Each
route.tsexports HTTP method handlers (GET, POST, etc.)
- Exclude auto-generated Payload routes:
-
Payload endpoint files —
src/endpoints/**/*.ts- Custom endpoints registered in
payload.config.tsviaendpoints: [...] - Check
payload.config.tsto confirm which are active
- Custom endpoints registered in
Custom endpoints are publicly available by default — you MUST check each one for:
| Control | What to look for |
|---|---|
| Authentication | payload.auth(), req.user check, bearer token validation, API key check |
| Authorization | Role checks (hasRole, isAdmin), ownership verification, overrideAccess usage |
| Input validation | Zod/Valibot schemas, manual param checks |
Classify each endpoint:
admin— requires admin/specific roleauthenticated— requires login but no role checkpublic— no authenticationsecret— API key or secret param
Phase 3: Generate Report
Abschnitt betitelt „Phase 3: Generate Report“Output a markdown report:
# Security Scan: {project-name}
## Auth Configuration- Signup: open / invite-only / admin-only- Auth method: session / JWT / external IdP- Access policy package: yes/no
## Collection Access Controls
| Collection | Create | Read | Update | Delete | Sensitive Fields | Issues ||-----------|--------|------|--------|--------|-----------------|--------|
## Custom Endpoints ({count})
| Method | Path | Auth | Validation | File ||--------|------|------|------------|------|
## Findings
### Critical| Location | Issue ||----------|-------|
### High| Location | Issue ||----------|-------|
### Medium| Location | Issue ||----------|-------|Common Mistakes (check for all of these)
Abschnitt betitelt „Common Mistakes (check for all of these)“- Making data available publicly when it shouldn’t be
- Making data available/writeable for all authenticated users when anyone can sign up
- Privilege escalation: user can change their own
role/isAdmin/permissionsfield - Exposing sensitive data (API keys, secrets, tokens) via collection read access
- Custom endpoints without any auth check (they default to public)
overrideAccess: truewithout proper upstream auth gating- Hardcoded secrets or fallback keys in endpoint auth
Severity Classification
Abschnitt betitelt „Severity Classification“- Critical: No auth on destructive/data-exposing endpoints; privilege escalation possible; hardcoded secrets; SSRF/injection vectors
- High: Auth without RBAC on admin operations; missing ownership checks; sensitive fields without field-level access; open signup + broad collection access
- Medium: Public endpoints triggering external API calls; missing input validation on write endpoints
- Use sub-agents for Phase 1 + Phase 2 when scanning large projects
- Auto-generated Payload routes (
[...slug],graphql) use Payload’s built-in access control — focus audit on collection access configs instead - Always check WHO can authenticate before evaluating access controls
- Check for
@awl/payload-access-policiespackage (by Mich) — projects using it likely have better defaults

