# Pathrule Pattern: Web Security (OWASP) (1.0.0)
# ::pathrule:package:web-security

### [RULE] Enforce access control on the server, deny by default  (path: /src)
<!-- scope: folder | priority: high | strict -->

Broken Access Control is the #1 risk on the OWASP Top 10:2025 because it is so easy to get wrong: the UI hides an action, but the endpoint behind it never checks who is calling.

- Authorize on the server for every request, checking the authenticated identity against the specific resource and action. Client-side checks are UX, not security; an attacker calls your API directly.
- Deny by default: a route with no explicit authorization should reject, not allow. Make "forbidden unless permitted" the framework default, not a check each handler must remember to add.
- Enforce object-level authorization (does THIS user own THIS record), not just "is logged in". Most access-control bugs are reading or mutating someone else's id (IDOR), so never trust an id from the request as proof of ownership.
- Check authorization on the server even for actions the UI does not expose. Hidden is not protected.

---

### [RULE] Treat all input as hostile; parameterize and escape  (path: /src)
<!-- scope: folder | priority: high | strict -->

Injection stays near the top of the OWASP list because untrusted input keeps reaching an interpreter, whether SQL, a shell, or a template.

- Validate and normalize input at the boundary against an explicit schema (allow-list what is valid; reject the rest). Validate type, length, format, and range, not just presence.
- Use parameterized queries / prepared statements or a query builder for every database call. Never build SQL (or NoSQL filters, shell commands, LDAP queries) by concatenating user input. An ORM does not save you if you drop to a raw string with interpolation.
- Escape output for the context it lands in (HTML, attribute, URL, JS, SQL). The same string is dangerous in one context and harmless in another.
- Never pass user input to a shell, `eval`, dynamic `require`, or a file path without strict validation; treat path and command construction as injection surfaces too.

---

### [RULE] Defend against XSS and CSRF  (path: /app)
<!-- scope: folder | priority: high | strict -->

Cross-site scripting and cross-site request forgery are the two ways the browser itself becomes the attacker's tool against your authenticated user.

- Render user-supplied content as text by default; let the framework escape it. Reach for a raw-HTML escape hatch (`dangerouslySetInnerHTML`, `v-html`, `innerHTML`) only with input sanitized by a vetted sanitizer, never with raw user input.
- Set a Content-Security-Policy that restricts script sources; it is the backstop that limits damage when an XSS slips through.
- Protect state-changing requests against CSRF: set session cookies `SameSite=Lax` or `Strict`, `HttpOnly`, and `Secure`, and add anti-CSRF tokens or strict origin/referer checks for unsafe methods. A token-in-header API (not cookie-auth) is less exposed but still validate the origin.
- Store session tokens in `HttpOnly` cookies so script cannot read them; do not stash auth tokens in `localStorage` where an XSS can exfiltrate them.

---

### [MEMORY] Secure-by-default configuration and headers  (path: /src)

Security Misconfiguration jumped to #2 on the OWASP Top 10:2025. The fix is boring and high-leverage: a hardened default config the whole app inherits.

- Send the core security headers: `Content-Security-Policy`, `Strict-Transport-Security` (HSTS), `X-Content-Type-Options: nosniff`, a sane `Referrer-Policy`, and `X-Frame-Options`/`frame-ancestors`. A helmet-style middleware sets these in one place.
- Do not leak internals to clients: return generic error messages, never stack traces, framework versions, or raw exception text in a response. Log the detail server-side, behind the API.
- Disable what you do not use: debug endpoints, directory listing, default accounts and sample routes, permissive CORS (`*` with credentials), and verbose modes in production.
- Keep secrets and PII out of logs and error payloads, and default new config to the least-privilege, most-restrictive setting rather than the most convenient one.

See /src for the access-control and input-validation rules; see /app for the XSS/CSRF rule. For credentials, see the secrets-env-management and auth-sessions-jwt-oauth patterns; for dependency risk, supply-chain-security.

---

### [MEMORY] Threat-model the request: where to check what  (path: /src)

Most web vulnerabilities are a missing check at a boundary the request crossed. Knowing the boundaries makes the checks systematic instead of ad hoc.

- At the edge: TLS/HSTS, rate limiting and abuse protection, request size limits, and CORS scoping. This is where you reject obviously hostile or excessive traffic.
- At authentication: establish who the caller is (see the auth pattern for sessions/JWT/OAuth). Authentication answers "who", not "may they".
- At authorization: for every resource and action, check that THIS identity may do THIS thing to THIS object. This is the layer most often missing and the OWASP #1.
- At the data boundary: validate and normalize input before it reaches a query, an interpreter, or storage; escape on the way out. Trust nothing that came from the client, including ids, headers, and hidden fields.
- Assume any single layer can fail and add defense in depth, so one missing check is not a full compromise.

See /src for the access-control and input rules and /src for the secure-config memory.

---

### [SKILL] web-security-review  (path: /)

---
name: web-security-review
description: OWASP-oriented security review checklist. Run before merging any endpoint, view, or config change that handles authentication, authorization, user input, or output.
---

# Web security review (OWASP Top 10:2025)

## Access control (A01)
- [ ] Every endpoint authorizes on the server against the authenticated identity; no UI-only checks.
- [ ] Object-level ownership is verified; an id from the request is never trusted as proof of access (no IDOR).
- [ ] Routes deny by default; a missing authorization check rejects rather than allows.

## Injection & input (A05)
- [ ] Input validated/normalized against a schema at the boundary (allow-list).
- [ ] All DB access is parameterized; no SQL/NoSQL/shell/LDAP built by string concatenation.
- [ ] No user input reaches a shell, eval, dynamic require, or unvalidated file path.

## XSS / CSRF
- [ ] User content rendered as text; raw-HTML sinks only with a vetted sanitizer.
- [ ] CSP restricts script sources; state-changing requests protected by SameSite cookies + tokens/origin checks.
- [ ] Session tokens in HttpOnly+Secure cookies; no auth tokens in localStorage.

## Configuration (A02)
- [ ] Security headers set (CSP, HSTS, nosniff, Referrer-Policy, frame-ancestors).
- [ ] No stack traces / versions / internal errors returned to clients; secrets and PII kept out of logs.
- [ ] Debug endpoints, default accounts, permissive CORS, and verbose modes disabled in production.
