Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff renders user-controlled content as HTML, builds links or redirects, changes CSP or CORS, adds a cookie-authenticated state change, a postMessage handler, a markdown renderer or an Electron/Tauri window
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Modern template engines and UI frameworks escape by default. XSS comes back through the doors that switch escaping off, through the wrong escaper for the context, and through URLs. CSRF comes back whenever cookies authenticate a state change.
Core principle: find the escape hatch, then trace what flows into it. {value} in JSX is the control working — not a finding.
| Framework / engine | Escape hatches to trace |
|---|---|
| React / Preact / Solid | dangerouslySetInnerHTML, innerHTML props, refs writing el.innerHTML |
| Vue | v-html, render functions setting innerHTML |
| Angular | bypassSecurityTrustHtml/Url/ResourceUrl/Script/Style ([innerHTML] alone is sanitised) |
| Svelte | {@html …} |
| DOM / jQuery | innerHTML, outerHTML, insertAdjacentHTML, document.write, .html(), $(userString), iframe.srcdoc |
| Jinja2 / Django | ` |
| Go | template.HTML(userValue), text/template used to render HTML |
| JVM | Thymeleaf th:utext, JSP <%= %> or escapeXml="false", FreeMarker ?no_esc |
| Node templates | Handlebars {{{ }}}, EJS <%- %>, Pug != |
| .NET | @Html.Raw, MarkupString |
// ❌ user-authored bio rendered as HTML
<div dangerouslySetInnerHTML={{ __html: user.bio }} />
// ✅ sanitised with an allowlist sanitiser, or rendered as text
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(user.bio) }} />
Markdown renderers count as HTML sinks when raw HTML is enabled: marked without a sanitiser, markdown-it with html: true, react-markdown with rehype-raw and no rehype-sanitize.
URLs are sinks too. href, src, formaction, location.href = …, window.open(…) with user data accept javascript: (and data: for some sinks). Validate the scheme (https:, mailto:) rather than relying on the framework's version-dependent handling.
<!-- ❌ profile website link -->
<a :href="user.website">site</a>
<!-- ✅ -->
<a :href="safeHttpUrl(user.website)">site</a> <!-- returns "#" unless new URL(v).protocol is http: or https: -->
Wrong escaper for the context: HTML-escaping a value placed inside a <script> block, an event-handler attribute or a CSS value does not make it safe. Data embedded into an inline script needs JSON serialisation that escapes < (</script> breaks out).
Stored XSS (one user's content shown to another) → HIGH. Reflected → MEDIUM to HIGH by reach. Self-XSS → not a finding.
A finding when all hold: the endpoint changes state, the browser authenticates it automatically (cookies, HTTP auth), and nothing ties the request to the app's own pages (CSRF token, SameSite=Lax/Strict on the session cookie with no state-changing GET, an Origin/Sec-Fetch-Site check, a custom-header requirement the CORS policy enforces).
Authorization: Bearer header are not CSRF-able.GET route is CSRF-able even with SameSite=Lax.csrf_exempt, ignoringRequestMatchers) is a removed guard.// ❌ any site can read authenticated responses: the request's Origin is reflected with credentials
res.setHeader("Access-Control-Allow-Origin", req.headers.origin);
res.setHeader("Access-Control-Allow-Credentials", "true");
// ✅ exact allowlist
if (ALLOWED_ORIGINS.has(req.headers.origin)) res.setHeader("Access-Control-Allow-Origin", req.headers.origin);
Access-Control-Allow-Origin: * without credentials is fine for public data; browsers refuse * with credentials. Watch for null origin allowed and suffix-matched origins (ssrf-and-url-allowlists has the matching pitfalls).
// ❌ any window can send a "token" message
window.addEventListener("message", (e) => { localStorage.setItem("token", e.data.token); });
// ✅
window.addEventListener("message", (e) => { if (e.origin !== "https://auth.example.com") return; … });
Also target.postMessage(secret, "*") — any framing or opening page can receive it.
A missing CSP is not reported. Adding 'unsafe-inline', 'unsafe-eval', a wildcard source or a JSONP-capable CDN to an existing policy is a weakened control: a note, or part of the finding when the same diff adds an injection sink.
Report only with a concrete chain: a post-login ?next= that can point off-site in an OAuth or SSO flow (code or token leakage), or a redirect used to pass an SSRF allowlist. A bare redirect on a marketing page is dropped.
In a desktop shell, renderer XSS can become code execution.
nodeIntegration: true, contextIsolation: false, sandbox: false, webSecurity: false; a preload exposing ipcRenderer or require wholesale through contextBridge; shell.openExternal(url) with an unvalidated scheme; IPC handlers that run commands or read paths from renderer arguments without validation; remote content loaded into a privileged window.allowlist/capabilities (shell open, fs scopes of **), dangerousRemoteDomainIpcAccess.{user.name} in JSX, {{ name }} in Vue/Jinja, or [innerHTML] in Angular.X-Frame-Options or HSTS as a vulnerability.DOMPurify imported but the sink fed the unsanitised variable.Access-Control-Allow-Credentials: true next to a reflected origin.addEventListener("message" with no origin comparison.BrowserWindow created with nodeIntegration: true or loading remote URLs.OWASP Top 10:2025 A05 Injection, A01 Broken Access Control · ASVS 5.0 V3 Web Frontend Security · CWE-79, 346, 352, 601, 942 · Electron security checklist
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
日本語の概要は準備中です。原文の説明を表示しています。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
日本語の概要は準備中です。原文の説明を表示しています。
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
日本語の概要は準備中です。原文の説明を表示しています。
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
日本語の概要は準備中です。原文の説明を表示しています。
Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation
日本語の概要は準備中です。原文の説明を表示しています。