1---2name: codeprobe-security3description: Scans code for security vulnerabilities — injection flaws, authentication gaps, XSS vectors, mass assignment, CSRF, insecure deserialization, sensitive data exposure, broken access control, and misconfigurations. Generates severity-scored findings with copy-pasteable fix prompts. Trigger phrases: "security scan", "security audit", "vulnerability check", "find security issues".4---56## Standalone Mode78If invoked directly (not via the orchestrator), you must first:91. Read `../codeprobe/shared-preamble.md` (resolve relative to this SKILL.md's location — the sibling `codeprobe` skill directory — not the user's project) for the output contract, execution modes, and constraints.102. Load applicable reference files from `../codeprobe/references/` (same resolution) based on the project's tech stack.113. Default to `full` mode unless the user specifies otherwise.1213# Security Vulnerability Scanner1415## Domain Scope1617This sub-skill detects security vulnerabilities across these categories:18191. **Injection** — SQL injection, command injection, LDAP/NoSQL injection202. **Authentication & Authorization** — Missing auth, weak credentials, hardcoded secrets, JWT issues213. **Cross-Site Scripting (XSS)** — Unescaped output, dangerous HTML rendering224. **Mass Assignment** — Unprotected model attribute assignment235. **Cross-Site Request Forgery (CSRF)** — Missing tokens, unprotected state-changing routes246. **Insecure Deserialization** — Unsafe deserialization of untrusted data257. **Sensitive Data Exposure** — Secrets in logs, committed .env files, leaked stack traces268. **Broken Access Control** — IDOR, missing policy/gate checks279. **Security Misconfiguration** — Debug mode in production, permissive CORS, default credentials2829---3031## What It Does NOT Flag3233- **Internal admin tools** with IP-restricted access — these have a different threat model and the restriction may be intentional.34- **Test files** using hardcoded values — test fixtures with fake credentials, tokens, and API keys are expected and appropriate.35- **Development-only configuration files** clearly marked as such (e.g., `.env.example`, `docker-compose.dev.yml`, files in `tests/fixtures/`).36- **Dependencies with known CVEs** — this sub-skill analyzes source code, not dependency manifests. Use dedicated tools (e.g., `npm audit`, `composer audit`) for dependency scanning.3738---3940## Detection Instructions4142### Injection4344| ID Prefix | What to Detect | How to Detect | Severity |45|-----------|---------------|---------------|----------|46| `SEC` | Raw SQL with string concatenation/interpolation | Search for SQL keywords (`SELECT`, `INSERT`, `UPDATE`, `DELETE`, `WHERE`) combined with string concatenation (`.`, `+`, `f"`, `${}`, `"${`), template literals, or variable interpolation. Check that user input flows into the query string without parameterization. | Critical |47| `SEC` | `DB::raw()` / raw queries with user input | Search for `DB::raw()`, `DB::select(DB::raw(`, `knex.raw()`, `sequelize.literal()`, `cursor.execute(f"` and similar raw query methods. Flag when the argument contains variables that could originate from user input (request params, form data, query strings). | Critical |48| `SEC` | Shell command construction with unsanitized input | Search for `exec()`, `system()`, `shell_exec()`, `popen()`, `subprocess.call()`, `subprocess.run()`, `child_process.exec()`, backtick operators. Flag when the command string includes variables from user input without escaping or allowlist validation. | Critical |49| `SEC` | LDAP/NoSQL injection vectors | Search for LDAP filter construction with string concatenation, MongoDB query construction with user input in `$where`, `$regex`, or other operators that accept arbitrary expressions. | Critical |5051### Authentication & Authorization5253| ID Prefix | What to Detect | How to Detect | Severity |54|-----------|---------------|---------------|----------|55| `SEC` | Missing auth middleware on routes that modify data | Scan route definitions (e.g., `Route::post()`, `router.post()`, `@app.post()`) for POST/PUT/PATCH/DELETE endpoints. Check whether auth middleware is applied. Flag routes that modify data without any authentication layer. | Critical |56| `SEC` | Role checks done in view/frontend but not backend | Search for role/permission checks in frontend templates or JavaScript (e.g., `v-if="user.isAdmin"`, `{user.role === 'admin' && ...}`) and verify that the corresponding backend endpoint also enforces the check. If backend lacks it, flag. | Major |57| `SEC` | Hardcoded secrets/API keys in source code | Search for patterns: `api_key = "..."`, `secret = '...'`, `password = "..."`, `token = '...'`, `AWS_SECRET`, `STRIPE_KEY`, bearer tokens, and similar. Exclude `.env.example` files and test fixtures. Check for high-entropy strings assigned to variables with secret-like names. | Critical |58| `SEC` | Weak password policy | Look for user registration/password-change logic. Check whether password validation enforces minimum length (8+ chars), complexity, or uses a validation library. Flag if passwords are accepted without any validation rules. | Major |59| `SEC` | JWT without expiration | Search for JWT creation/signing code. Check whether the payload includes an `exp` (expiration) claim. Flag JWTs created without expiration or with excessively long expiration (> 24 hours for access tokens). | Major |6061### Cross-Site Scripting (XSS)6263| ID Prefix | What to Detect | How to Detect | Severity |64|-----------|---------------|---------------|----------|65| `SEC` | `{!! !!}` (unescaped output) in Laravel Blade with user data | Search for `{!! ... !!}` in `.blade.php` files. Check whether the content inside originates from user input, database fields that store user-provided HTML, or request data. Exclude static content and trusted admin-only fields. | Major |66| `SEC` | `dangerouslySetInnerHTML` in React with untrusted data | Search for `dangerouslySetInnerHTML` in `.jsx`/`.tsx` files. Check whether the `__html` value comes from user input, API responses without sanitization, or any source not explicitly sanitized with DOMPurify or equivalent. | Major |67| `SEC` | `v-html` in Vue with untrusted data | Search for `v-html` directives in `.vue` files. Same analysis as above — flag when the bound value could contain unsanitized user input. | Major |68| `SEC` | Missing Content-Security-Policy | Check for CSP headers in middleware, web server config, or meta tags. If no CSP is configured anywhere in the project, flag as a defense-in-depth gap. | Minor |6970### Mass Assignment7172| ID Prefix | What to Detect | How to Detect | Severity |73|-----------|---------------|---------------|----------|74| `SEC` | Laravel model without `$fillable` or `$guarded` | Search for Eloquent model classes (extending `Model`). Check whether each model defines either `$fillable` (allowlist) or `$guarded` (blocklist) property. Flag models that define neither. | Major |75| `SEC` | Accepting `$request->all()` into create/update | Search for `$request->all()`, `request.body` (without destructuring), `**request.data` passed directly into `Model::create()`, `Model::update()`, `Model::fill()`, or ORM create/update methods. Flag as mass assignment vector. | Critical |7677### Cross-Site Request Forgery (CSRF)7879| ID Prefix | What to Detect | How to Detect | Severity |80|-----------|---------------|---------------|----------|81| `SEC` | Forms without CSRF tokens | Search for `<form` tags with `method="POST"` (or PUT/PATCH/DELETE). Check whether the form includes a CSRF token field (`@csrf`, `csrf_token()`, `csrfmiddlewaretoken`, `_token`). Flag forms missing tokens. | Major |82| `SEC` | API routes without proper auth that modify state | Check API routes (POST/PUT/PATCH/DELETE) that lack both CSRF protection AND authentication middleware. Stateless APIs with token auth are fine; session-based APIs without CSRF tokens are not. | Major |8384### Insecure Deserialization8586| ID Prefix | What to Detect | How to Detect | Severity |87|-----------|---------------|---------------|----------|88| `SEC` | `unserialize()` on user input | Search for `unserialize()` (PHP), `pickle.loads()` (Python), `ObjectInputStream` (Java), `Marshal.load` (Ruby). Flag when the input source is user-controlled (request body, cookies, query params, uploaded files). | Critical |89| `SEC` | `JSON.parse()` without validation used in eval-like context | Search for `JSON.parse()` of external data where the parsed result is passed to `eval()`, `Function()`, `setTimeout(string)`, or used to construct code dynamically. Flag the eval-like usage, not JSON.parse itself. | Major |9091### Sensitive Data Exposure9293| ID Prefix | What to Detect | How to Detect | Severity |94|-----------|---------------|---------------|----------|95| `SEC` | Passwords/tokens in log statements | Search for logging calls (`Log::`, `logger.`, `console.log`, `print`, `logging.`) that include variables named `password`, `token`, `secret`, `key`, `credential`, `auth`, or similar. Flag when sensitive data is written to logs. | Critical |96| `SEC` | `.env` committed to git | Check whether `.gitignore` includes `.env`. If `.env` exists in the repository and is not gitignored, flag as critical. Also check for `.env.production`, `.env.staging` committed. | Critical |97| `SEC` | Secrets in config files vs environment variables | Search config files for hardcoded credentials, API keys, database passwords. Flag values that should come from environment variables but are instead hardcoded in tracked config files. | Major |98| `SEC` | Error messages leaking stack traces in production config | Check error/exception handling configuration. Look for `APP_DEBUG=true`, `DEBUG=True`, `display_errors=On`, or custom error handlers that expose stack traces, file paths, or SQL queries in responses. Flag when this is in production config. | Major |99100### Broken Access Control101102| ID Prefix | What to Detect | How to Detect | Severity |103|-----------|---------------|---------------|----------|104| `SEC` | IDOR — using user-supplied ID without ownership check | Search for route parameters or request params (e.g., `$request->id`, `params.id`, `request.args.get('id')`) used to fetch resources without verifying the authenticated user owns the resource. Look for `Model::find($id)` without a `where('user_id', auth()->id())` or policy check. | Critical |105| `SEC` | Missing policy/gate checks on resource access | In frameworks with authorization systems (Laravel policies, Django permissions, Express middleware), check whether CRUD operations on user-owned resources include authorization checks. Flag controller actions that read/modify resources without policy or permission verification. | Major |106107### Security Misconfiguration108109| ID Prefix | What to Detect | How to Detect | Severity |110|-----------|---------------|---------------|----------|111| `SEC` | `APP_DEBUG=true` in production configs | Search for `APP_DEBUG=true`, `DEBUG=True`, `debug: true` in configuration files that appear to be production configs (not `.env.example` or `.env.local`). | Major |112| `SEC` | Permissive CORS | Search for CORS configuration. Flag `Access-Control-Allow-Origin: *` or `allowed_origins: ['*']` in non-public-API contexts. Also flag `Access-Control-Allow-Credentials: true` combined with wildcard origins. | Major |113| `SEC` | Default credentials in configuration | Search for usernames like `admin`, `root`, `test` paired with passwords like `password`, `123456`, `admin`, `secret`, `changeme` in config files, seeders, or initialization code. Exclude test fixtures. | Critical |114115---116117## ID Prefix & Fix Prompt Examples118119All findings use the `SEC-` prefix, numbered sequentially: `SEC-001`, `SEC-002`, etc.120121### Fix Prompt Examples122123- "In `UserController@update` (line 34), replace `$request->all()` with `$request->only(['name', 'email'])` to prevent mass assignment on the `is_admin` field. Also add `$fillable = ['name', 'email']` to the `User` model if not already present."124- "Wrap the user input at line 55 of `app/Services/SearchService.php` in a parameterized query: change `DB::select(\"SELECT * FROM products WHERE name LIKE '%$search%'\")` to `DB::select('SELECT * FROM products WHERE name LIKE ?', [\"%{$search}%\"])`."125- "In `routes/api.php`, add auth middleware to the `POST /api/orders` route at line 22: change `Route::post('/orders', [OrderController::class, 'store'])` to `Route::post('/orders', [OrderController::class, 'store'])->middleware('auth:sanctum')`."126- "Move the hardcoded API key at line 15 of `config/services.php` to an environment variable: replace `'key' => 'sk-live-abc123...'` with `'key' => env('STRIPE_SECRET_KEY')` and add `STRIPE_SECRET_KEY=` to `.env.example`."