Frontend Security
SkillWeb & browsingBrowser-side hardening: XSS and safe text binding, per-sink URL policy, DOM clobbering, nonce-based CSP, Trusted Types, subresource integrity, iframe capability minimization, postMessage validation, and where client state may live. Use when generating HTML, JSX, Vue, or Svelte templates, setting response headers in a web app, embedding third-party scripts or frames, or storing anything client-side.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Frontend Security skill
What this skill tells your AI
The instructions your AI receives, as published by shieldnet-360/secure-vibe in skills/frontend-security/SKILL.md and read by ahel’s review.
Rules (for AI agents)
ALWAYS
- Render untrusted data through the framework's ordinary text interpolation, which escapes for the output context. Do not reach for a raw-HTML API merely to display user data. Where rich HTML genuinely must be rendered, put it through a maintained sanitizer (DOMPurify) with an explicit allowlist first.
- Validate URL-bearing attributes per sink, not against one global scheme list. A
navigation target (
href,action,formaction, an<iframe src>) and an image source do not share a trust model:javascript:is never acceptable anywhere, while a narrowly constraineddata:image/…orblob:may be exactly what an image sink requires. Decide the permitted schemes for each sink and check against that list. - Read security-sensitive configuration and control-flow values from lexical variables
or an object you own — never from a named
window/documentproperty (window.config,document.redirectTo, an implicit global). The browser exposes elements byidandnameas named properties, so injected markup can shadow the value your code expected. An explicitgetElementById()lookup is not the problem; trusting an ambient global is. Type-check what you read before using it in a privileged way. - Build the
Content-Security-Policyaround a nonce or hash as the trust root:script-src 'nonce-{value}' 'strict-dynamic'; object-src 'none'; base-uri 'none'. Keeping'self'beside the nonce means every same-origin script is still trusted — that is a host-allowlist policy wearing a nonce, which may be the right trade-off but is not a strict CSP, so do not call it one. Generate the nonce from a CSPRNG afresh for every HTML response, and apply it only to scripts the server itself authorizes. - Where you deploy Trusted Types, enforce
require-trusted-types-for 'script'and restrict which policies may exist with thetrusted-typesdirective. The first makes DOM sinks demand a typed value; without the second, any code can mint a pass-through policy (createHTML: s => s) and the guarantee is gone. Keep policies few, named, and centrally reviewed. - Load third-party scripts and stylesheets from version-pinned, immutable URLs
with
integrity="sha384-…"andcrossorigin="anonymous". A hash pinned against a mutable URL breaks the page the first time the provider ships a legitimate update, which is how integrity checks come to be quietly deleted. If a provider cannot offer stable bytes with CORS, self-host rather than drop SRI. - Sandbox every
<iframe>, starting from no capability tokens and adding only what the embedded content needs. Do not combineallow-scriptswithallow-same-origin: together they let the framed document reach the parent and remove its ownsandboxattribute, so the sandbox stops meaning anything. If the content genuinely needs both, isolate it on a separate origin instead. - On
postMessage, name an explicittargetOriginwhen sending — never*— and on receipt verifyevent.originagainst an allowlist, validate the message's shape before reading any field, and where the channel expects one particular frame, checkevent.sourceas well. Origin, schema and sender are three separate checks. - Set
X-Content-Type-Options: nosniff,Referrer-Policy: strict-origin-when-cross-originor stricter,Permissions-Policydropping unused features, andCross-Origin-Opener-Policy: same-originto sever the opener relationship at the document level. Remove framework version banners here too (X-Powered-By, a detailedServer). Note thatno-referrer-when-downgradeis weaker than the current browser default — configuring it is a step backwards. - Send HSTS on production HTTPS. Add
includeSubDomainsonly after confirming every subdomain serves HTTPS, andpreloadonly as a deliberate, hard-to-reverse commitment for the registrable domain: the token makes a domain eligible for the preload list, it does not enrol it, and reversing it is slow. - Keep authentication secrets out of JavaScript-readable storage — no access tokens,
refresh tokens, JWTs, or sensitive personal or business data in
localStorageorsessionStorage, where a single XSS reads all of it — and clear authenticated client-side state on logout. Server-issued session cookies are the alternative:Secure,HttpOnly, an application-appropriateSameSite, and the__Host-prefix for host-only cookies atPath=/.auth-securityowns issuing them; this rule exists so a frontend review recognises an auth value that has escaped into JavaScript's reach.
NEVER
- Use
dangerouslySetInnerHTML,v-html,{@html …},innerHTML =, ordocument.writewith untrusted input. - Use
eval,new Function,setTimeout(string), orsetInterval(string). - Read or write
document.cookiefrom JavaScript for an auth cookie — it should beHttpOnly, which means JavaScript cannot see it and code that does is reaching for a cookie that was never hardened. - Treat tightening the HTML sanitizer as the fix when the exploit rides on content
the sanitizer allows by design — a valid link, an
<img src>, a permitted attribute. The sanitizer is working. The vulnerable behaviour is downstream, where some sink turns that allowed value into a navigation, a command, or a native capability. Fix the sink and reduce its authority.
KNOWN FALSE POSITIVES
- Internal admin tools rendering Markdown or rich text from trusted authors may use a raw-HTML API after a sanitizer pass; document the sanitizer call inline.
- A deliberately sandboxed browser-extension page may use a more permissive CSP
for code that needs eval-like behaviour, provided it stays isolated from the
extension APIs. That is not a licence to add
'unsafe-eval'to MV3extension_pages— Chrome rejects that policy outright, and WebAssembly has its own'wasm-unsafe-eval'token. - A WebSocket to a non-same-origin endpoint where the server validates
Origin. - A native or WASM decoder that is merely registered or configured is not yet an attack surface. Before flagging one, establish a reachable runtime path from untrusted input to that decoder — including an implementation fetched lazily at runtime, which does not have to be in the shipped bundle to be reachable.
Context (for humans)
Escaping is still the base layer and CSP is still what turns one missed escape into a report instead of a stolen session. What has changed is where the browser now draws its boundaries: opener isolation, cross-origin isolation, and Trusted Types are document-level controls that a per-element attribute cannot replace.
Two failure shapes account for most of what goes wrong in review. The first is a
control that is present but hollow — a nonce alongside 'self', a sandbox with
allow-scripts allow-same-origin, Trusted Types enforced without restricting who may
create a policy. Each looks like the hardened version and grants what it appears to
withhold. The second is a defence recommended against an old default: browsers have
moved, and a Referrer-Policy copied from a 2019 guide now configures something
weaker than doing nothing at all.
The corollary for anything written here: prefer the browser's current default to a remembered value, and when a rule names a header value or a token, check it against the platform rather than against an example.
References
references/verifying-findings.md— confirm or refute a finding, then lock itreferences/browser-controls.md— per-framework text binding, strict versus allowlist CSP, the response-header matrix, when COOP / COEP / CORP each apply, and extension-CSP specificsrules/csp_defaults.jsonrules/xss_sinks.json- OWASP XSS Prevention Cheat Sheet.
- OWASP CSP Cheat Sheet.
- OWASP DOM Clobbering Prevention.
- Trusted Types specification (W3C).
- CWE-79 · CWE-346.
Signals
- GitHub stars
- 22
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
frontend-security- Source
- github.com/shieldnet-360/secure-vibe