---
description: "CodeWiki Security pitfalls and review checks"
globs: []
alwaysApply: false
---

# Security rules

This track covers more than one language, so no file globs are inferred. Apply these rules manually when they are relevant.

- Middleware validates an access token, so the handler treats every logged-in principal as authorized for the object named in the request.
  Source: [API security](https://codewiki.com/security/api-security/)
- Do not assume this is safe: code loads an object by the client-supplied ID and then uses an easy-to-miss owner condition; batch operations and new endpoints fail to reuse it.
  Source: [API security](https://codewiki.com/security/api-security/)
- `Object.assign(entity, request.body)` or object spread copies client fields into a domain object, while the response returns the complete database record.
  Source: [API security](https://codewiki.com/security/api-security/)
- Each process keeps an in-memory counter or keys limits directly from an unverified forwarding header, so attackers can rotate values and multi-instance deployments grant duplicate quotas.
  Source: [API security](https://codewiki.com/security/api-security/)
- Error responses and logs contain stacks, access tokens, cookies, password fields, or complete domain objects, turning a diagnostic channel into another data outlet.
  Source: [API security](https://codewiki.com/security/api-security/)
- A new version has the right controls, but an old version, shadow route, or debug endpoint still reaches the same data from the public network.
  Source: [API security](https://codewiki.com/security/api-security/)
- Do not assume this is safe: code checks only `Origin` before returning private data, assuming callers outside the allowlist cannot request the API.
  Why: A non-browser client may set or omit `Origin`, and a same-origin page may still carry attacker-controlled input.
  Source: [CORS](https://codewiki.com/security/cors/)
- Generated middleware often copies any `Origin` into `Access-Control-Allow-Origin` or uses `includes('example.com')`.
  Why: That admits attacker origins such as `https://example.com.attacker.invalid`.
  Source: [CORS](https://codewiki.com/security/cors/)
- The preflight returns `204`, but the actual response, redirect, or error response has no `Access-Control-Allow-Origin`.
  Why: The browser then collapses the real server error into what the frontend observes as a CORS failure.
  Source: [CORS](https://codewiki.com/security/cors/)
- Do not assume this is safe: the client sets `credentials: 'include'` while the server returns a wildcard origin, or the server enables `Access-Control-Allow-Credentials` and assumes that this forces the browser to send cookies.
  Source: [CORS](https://codewiki.com/security/cors/)
- The server dynamically reflects a validated origin but omits `Vary: Origin`.
  Why: A shared cache may reuse headers generated for one origin when serving another, causing an incorrect allow or denial.
  Source: [CORS](https://codewiki.com/security/cors/)
- A command-line request can read the expected response, so the configuration is considered complete.
  Why: HTTP clients generally do not run the browser CORS algorithm and therefore do not hide a response as a browser would.
  Source: [CORS](https://codewiki.com/security/cors/)
- To make a page work immediately, generated configuration sets `script-src` to `* 'unsafe-inline' 'unsafe-eval'` or admits a whole unknown third-party domain.
  Why: The header exists, but the script-execution boundary is close to ineffective.
  Source: [Security response headers](https://codewiki.com/security/security-headers/)
- The application generates one nonce at process startup and reuses it, or the CDN updates the CSP header while serving old HTML.
  Why: Once an attacker obtains a reusable value—or the header and element no longer match—the policy loses its intended protection or breaks the page outright.
  Source: [Security response headers](https://codewiki.com/security/security-headers/)
- Configuration copies a one-year lifetime, `includeSubDomains`, and `preload` before legacy subdomains, mail entry points, or recovery sites reliably support HTTPS.
  Why: Once browsers remember the policy, those hosts may be unreachable for the policy lifetime.
  Source: [Security response headers](https://codewiki.com/security/security-headers/)
- A route handler sets headers on `200` responses, but framework `404` pages, middleware `401` responses, proxy `413` errors, and upstream `502` pages use a different policy boundary.
  Source: [Security response headers](https://codewiki.com/security/security-headers/)
- Configuration uses CSP `frame-src` to stop other sites embedding the current page, or sets only `X-Frame-Options: SAMEORIGIN` when several named partners need access.
  Why: The first controls frames this page may load; the second cannot express a multi-origin allowlist.
  Source: [Security response headers](https://codewiki.com/security/security-headers/)
- Old tutorials or generated code still add `X-XSS-Protection: 1; mode=block`, `X-Frame-Options: ALLOW-FROM`, or Permissions Policy feature names that no longer exist, then treat “no error” as evidence of protection.
  Source: [Security response headers](https://codewiki.com/security/security-headers/)
- A denylist of strings such as `localhost`, `10.`, and `169.254.169.254` looks broad but operates before canonical URL and IP parsing.
  Why: Alternate textual forms, IPv6, user-info syntax, or parser disagreement can move the effective destination outside the check. Fix: minimize caller choice, parse with the client-compatible parser, compare exact normalized hostnames, parse every resolved IP, and default to rejection when any step is ambiguous.
  Source: [Server-side request forgery](https://codewiki.com/security/ssrf/)
- Code resolves a hostname, approves the answer, and then passes the original URL to a client that performs its own lookup.
  Why: The checked address and connected address are not guaranteed to match. Fix: bind an approved address to the socket through a supported lookup hook or outbound proxy, while preserving the original hostname for TLS and HTTP. Test that the resolver cannot change the connected address after approval.
  Source: [Server-side request forgery](https://codewiki.com/security/ssrf/)
- An HTTP client follows redirects automatically after only the first URL passed policy.
  Why: An approved public endpoint can then redirect to loopback, a private service, or a disallowed port. Fix: disable automatic redirects or install a hook that reruns the full policy for every hop. Resolve relative locations correctly, cap the hop count, and decide how each redirect status affects the method and body.
  Source: [Server-side request forgery](https://codewiki.com/security/ssrf/)
- A proxy route forwards the inbound header object to the outbound request.
  Why: Internal credentials, cookies, forwarding headers, and tracing data then cross into a destination selected by the caller. Fix: construct outbound headers from a small allowlist, keep service credentials bound to fixed service identities, and never let a caller choose both the destination and the credential sent there.
  Source: [Server-side request forgery](https://codewiki.com/security/ssrf/)
- Destination checks pass, so the implementation buffers the entire response and trusts its declared media type and size.
  Why: A remote endpoint can return an endless stream, compressed expansion, or content that a later parser treats as active input. Fix: enforce deadlines, byte and decompression limits, concurrency budgets, and accepted content types while streaming. Validate the decoded artifact again at the consumer boundary.
  Source: [Server-side request forgery](https://codewiki.com/security/ssrf/)
- A team treats metadata hardening or an outbound firewall as the whole SSRF fix.
  Why: Internal services on allowed routes, public attacker hosts, and expensive external APIs can remain reachable. Fix: combine application destination policy, connection binding, resource limits, egress filtering, workload identity least privilege, and cloud-specific controls. Test each layer independently so one permissive layer is visible.
  Source: [Server-side request forgery](https://codewiki.com/security/ssrf/)
- Validating data once at ingress and treating it as permanently safe.
  Why: When data enters a new interpretation context, combines with other values, or returns from storage, the earlier validation does not replace the control required at the current boundary.
  Source: [Web security fundamentals](https://codewiki.com/security/web-security-fundamentals/)
- Do not treat successful authentication as successful authorization.
  Why: Generated CRUD routes are especially prone to checking a token and then reading, updating, or deleting the object ID supplied by the client.
  Source: [Web security fundamentals](https://codewiki.com/security/web-security-fundamentals/)
- Do not treat CORS as access control or CSRF protection.
  Why: Non-browser clients do not enforce CORS, and a browser may send a request even when it refuses to expose the response to attacker code.
  Source: [Web security fundamentals](https://codewiki.com/security/web-security-fundamentals/)
- Do not treat security headers as switches that repair root; doing so causes.
  Why: A loose CSP, a fixed nonce, or headers added only to successful responses can defeat the policy. HSTS and `nosniff` do not repair injection or broken authorization either.
  Source: [Web security fundamentals](https://codewiki.com/security/web-security-fundamentals/)
- Logging complete requests, cookies, tokens, or passwords in the name of a “security audit.” Attackers and insiders may then recover otherwise protected data from the logging system.
  Source: [Web security fundamentals](https://codewiki.com/security/web-security-fundamentals/)
