Audit a Laravel application's security boundaries: authorization, mass assignment, sensitive data, file/URL handling, CSRF, XSS, injection, and secrets. Use when auditing security or when asked to review security of a Laravel app.
php artisan boost:add-skill mrpunyapal/laravel-auditor
Save this content to: .claude/skills/laravel-audit-security/SKILL.md
# Laravel Security Audit
Audit the security boundaries of the Laravel application. **Do not invent vulnerabilities merely because a pattern is uncommon.** Require context and evidence.
List applicable rules first:
```bash
php artisan auditor:rules --domain=security --applicable
```
## What to look for
- Authorization gaps: routes/controllers that mutate or expose resources without a policy, gate, or middleware.
- Insecure resource access: missing ownership checks on update/delete/show.
- Missing policies/gates where the app has clear resource ownership.
- Mass assignment risks: unguarded models or over-permissive `$fillable` combined with direct request input.
- Unsafe validation assumptions: trusting `required`/client-side checks, missing server-side validation on critical fields.
- Sensitive data exposure: secrets or personal data in responses, logs, exceptions, or dumps.
- Unsafe configuration usage: `APP_DEBUG` assumptions, hardcoded credentials, env values echoed.
- Dangerous file handling: unvalidated uploads, paths from user input, unsafe file reads.
- Unsafe URL/redirect handling: open redirects from user-controlled targets.
- SSRF (AUD-SEC-014): trace untrusted URLs into Http/Guzzle/cURL, including DNS resolution and redirects; verify the effective destination restrictions before reporting.
- Insecure authentication/authorization patterns: storing secrets in plaintext, weak session config, missing rate limits on auth.
- Secrets accidentally committed or exposed where detectable (`.env` committed, keys in source).
- Weak or missing CSRF protection: `VerifyCsrfToken::except` whitelists, removed/reordered CSRF middleware, forms or post endpoints missing the token.
- Webhook authenticity (AUD-SEC-016): a CSRF-exempt webhook is not inherently unsafe; follow provider signature, secret, or equivalent authentication checks through middleware before concluding that events can be forged.
- Unescaped output / XSS risk: Blade `{!! !!}`, `->get()`, `->toHtml()` rendering user-controlled or stored data.
- Raw SQL with user-controlled input: `DB::raw`, `whereRaw`, `selectRaw`, `orderByRaw`, or `statement` interpolating request input.
- Known vulnerable dependencies. Inspect `composer_audit.advisories`, `ignored_advisories`, `abandoned`, `filter` (which may include malware lists), and `cooldown` independently. A non-empty `unreachable_repositories` list means results are incomplete, even if no advisories were reported. `dependencies.composer_audit` is **on by default**. Use it for `AUD-DEP-001` when `available` is true. If `available` is false, read `reason` or run `composer audit --format=json` yourself — do not treat an empty payload as “no advisories”. Set `laravel-auditor.context.composer_audit` to `false` only when you need to skip the shell-out.
- Command injection (AUD-SEC-015): trace request/job/file data into shell invocation sinks and establish whether it enters a shell command or a safely separated argument array.
- Known vulnerable production npm dependencies when `context.npm_audit` is enabled. Use `dependencies.npm_audit` for `AUD-DEP-007`; an unavailable scan must not be reported as clean.
- Queued jobs that serialize Eloquent models with hidden/sensitive attributes (`AUD-QUE-002`).
When these packages are installed, also apply their packs (`auditor:rules --applicable`): Livewire (`AUD-LW-*`), Filament (`AUD-FIL-*`), Inertia (`AUD-IN-*`), Sanctum (`AUD-API-*`).
## Dependency-only export
For Composer advisory findings without an AI agent, run `php artisan auditor:dependency-findings --output=storage/dependency-findings.json`, then use that file with `auditor:report` or `auditor:ci`. Add `--include-abandoned` for low-severity maintenance findings. Keep this output separate from agent-produced findings; the command replaces the output file and fails on unavailable or incomplete audits. Confirmed dependency matches do not prove application exploitability. Ignored advisories, filters, cooldown entries, and npm results still require separate investigation.
Set `context.composer_audit_locked` for exact lockfile auditing and `context.composer_audit_no_dev` for production-only scope; both default to false. Optional `context.npm_audit` also defaults to false and requires npm 7+ with an npm lockfile. Never run an install, update, or audit fix as part of gathering audit evidence.
## Evidence requirements
Every security finding needs at least:
- The specific route/controller/model file and line/range.
- The relevant middleware/policy/gate (or the absence of one).
- What the attacker-controlled input is, when applicable.
## False positives
- Do not claim exploitability without sufficient evidence.
- A missing policy is only a finding when the resource is user-accessible or sensitive.
- Uncommon patterns are not automatically vulnerabilities.
- An empty `composer_audit` payload is not evidence that there are no advisories unless the check actually ran.
## Severity guidance
- `critical`: directly exploitable, e.g. unauthenticated access to sensitive data or arbitrary code execution.
- `high`: requires a real but plausible precondition (e.g. any authenticated user).
- `medium`/`low`: defense-in-depth issues, configuration concerns, or low-exploitability risks.
- `info`: observations worth documenting without immediate risk.
Audit the security boundaries of the Laravel application. Do not invent vulnerabilities merely because a pattern is uncommon. Require context and evidence.
List applicable rules first:
php artisan auditor:rules --domain=security --applicable
$fillable combined with direct request input.required/client-side checks, missing server-side validation on critical fields.APP_DEBUG assumptions, hardcoded credentials, env values echoed..env committed, keys in source).VerifyCsrfToken::except whitelists, removed/reordered CSRF middleware, forms or post endpoints missing the token.{!! !!}, ->get(), ->toHtml() rendering user-controlled or stored data.DB::raw, whereRaw, selectRaw, orderByRaw, or statement interpolating request input.composer_audit.advisories, ignored_advisories, abandoned, filter (which may include malware lists), and cooldown independently. A non-empty unreachable_repositories list means results are incomplete, even if no advisories were reported. dependencies.composer_audit is on by default. Use it for AUD-DEP-001 when available is true. If available is false, read reason or run composer audit --format=json yourself — do not treat an empty payload as “no advisories”. Set laravel-auditor.context.composer_audit to false only when you need to skip the shell-out.context.npm_audit is enabled. Use dependencies.npm_audit for AUD-DEP-007; an unavailable scan must not be reported as clean.AUD-QUE-002).When these packages are installed, also apply their packs (auditor:rules --applicable): Livewire (AUD-LW-*), Filament (AUD-FIL-*), Inertia (AUD-IN-*), Sanctum (AUD-API-*).
For Composer advisory findings without an AI agent, run php artisan auditor:dependency-findings --output=storage/dependency-findings.json, then use that file with auditor:report or auditor:ci. Add --include-abandoned for low-severity maintenance findings. Keep this output separate from agent-produced findings; the command replaces the output file and fails on unavailable or incomplete audits. Confirmed dependency matches do not prove application exploitability. Ignored advisories, filters, cooldown entries, and npm results still require separate investigation.
Set context.composer_audit_locked for exact lockfile auditing and context.composer_audit_no_dev for production-only scope; both default to false. Optional context.npm_audit also defaults to false and requires npm 7+ with an npm lockfile. Never run an install, update, or audit fix as part of gathering audit evidence.
Every security finding needs at least:
composer_audit payload is not evidence that there are no advisories unless the check actually ran.critical: directly exploitable, e.g. unauthenticated access to sensitive data or arbitrary code execution.high: requires a real but plausible precondition (e.g. any authenticated user).medium/low: defense-in-depth issues, configuration concerns, or low-exploitability risks.info: observations worth documenting without immediate risk.How can I help you explore Laravel packages today?