Org Skills

Frontend security

Always-on browser-security rules for client-side code in any frontend stack — bundle secrets, XSS sinks, URL and redirect handling, postMessage, CSP, CSRF with cookie sessions, token storage and third-party scripts.

Raw Source
What it isAlways-on coding rules. GitHub Copilot applies them to files matching **/*.ts,**/*.tsx,**/*.js,**/*.jsx,**/*.mjs,**/*.vue,**/*.svelte,**/src/**/*.html; the Claude Code version is a path-scoped rule generated from the same file. Why use instructions →

Install

This repository (recommended)

Adds .github/instructions/frontend-security.instructions.md — commit it so everyone's Copilot follows the same rules.

npx -y github:AGCO-Global/org-skills add instructions frontend-security

Just for me, every repository

Save it in your user profile instead.

npx -y github:AGCO-Global/org-skills add instructions frontend-security --user

Use it

Nothing to invoke — edit a matching file and Copilot picks the rules up. Adjust applyTo if your repository layout differs.

This repository (recommended)

Adds .claude/rules/frontend-security.md — commit it. Claude loads it when it reads a matching file.

npx -y github:AGCO-Global/org-skills add instructions frontend-security --tool claude

Just for me, every repository

Save it in your user profile instead.

npx -y github:AGCO-Global/org-skills add instructions frontend-security --tool claude --user

Use it

Nothing to invoke. Adjust the paths globs if your repository layout differs.

Commands run in your repository folder and need Node.js 20+. They use your normal git sign-in to GitHub, so they work while the repository is private. Run npx -y github:AGCO-Global/org-skills list to see everything available.

Settings

name: "Frontend security"
description: "Always-on browser-security rules for client-side code in any frontend stack — bundle secrets, XSS sinks, URL and redirect handling, postMessage, CSP, CSRF with cookie sessions, token storage and third-party scripts."
applyTo: "**/*.ts,**/*.tsx,**/*.js,**/*.jsx,**/*.mjs,**/*.vue,**/*.svelte,**/src/**/*.html"

Instructions Copilot follows

Frontend security rules

Everything in a browser bundle is public, and every value that reaches the DOM is attacker-influenced until proven otherwise. These are the browser-specific rules; secure-coding.instructions.md holds the stack-agnostic ones and is not repeated here.

Secrets and configuration

  • A browser bundle cannot hold a secret. API keys, client secrets, signing keys and connection strings belong behind your own backend; if the browser needs the capability, proxy the call.
  • A key that a vendor calls "publishable" is still only safe if it is scoped and rate-limited server side. Check what it can do before treating it as public.
  • Do not ship internal hostnames, private endpoints or tenant identifiers in client code, comments or source maps published to the public.

Rendering untrusted values

  • Never pass user- or API-supplied strings to an HTML sink: dangerouslySetInnerHTML, [innerHTML], innerHTML, insertAdjacentHTML, outerHTML, document.write, v-html, lwc:dom="manual". Render text, or render structured data as elements.
  • Never call a sanitizer bypass on data you did not author: Angular's bypassSecurityTrustHtml/Url/ResourceUrl/Script/Style disable the framework's only XSS protection.
  • If formatted user content genuinely must render, sanitise it server side with a maintained library and store the sanitised form — client-side sanitisation is a second line of defence, not the first.
  • Never eval, new Function, setTimeout('string'), or inject a <script> built from data.
  • Validate any URL that reaches href, src, action, formaction or window.open against a scheme allow-list of https: (and mailto:/tel: where needed). javascript: and data: URLs execute.
  • Build redirects from an allow-list of known paths, never from a raw query parameter — an open redirect on your own domain is a working phishing page.
  • Put rel="noopener noreferrer" on target="_blank" links to third-party sites. Modern browsers imply noopener; noreferrer is what stops your internal URLs leaking in the referrer.

Cross-origin messaging and embedding

  • In every message listener, check event.origin against an exact expected origin before reading event.data, and treat the payload as untrusted input after that.
  • Never call postMessage(data, '*') with anything sensitive; name the target origin.
  • Sandbox embedded third-party content (<iframe sandbox="...">) and grant only the capabilities it needs.

Sessions, tokens and authorisation

  • With cookie sessions, cookies must be set server side with HttpOnly; Secure; SameSite=Lax (or Strict), and every state-changing request must carry the framework's CSRF token.
  • Prefer keeping access tokens in memory over localStorage, which any injected script can read and which survives the tab. If a refresh flow is needed, the refresh token belongs in an HttpOnly cookie.
  • Client-side permission checks are user experience only. Hiding a button is not access control; the server must enforce every rule the UI implies.
  • Use crypto.randomUUID() or crypto.getRandomValues() for anything id- or nonce-like. Math.random() is predictable.

Headers and third-party code

  • Ship a Content-Security-Policy and keep it strict: no unsafe-inline, no unsafe-eval, explicit origins for scripts, connections and frames. Enable Trusted Types where the browsers you support allow it.
  • Adding a third-party script is a security decision: check what it loads at runtime, give it Subresource Integrity where the URL is versioned, add its origins to the CSP, and record what data it collects.
  • Do not disable CSP, CORS checks or certificate validation to make something work locally; use a local proxy or a development-only configuration that cannot ship.

Data handling in the client

  • Keep personal data out of console output, analytics events, error reports, breadcrumbs and URL query strings — all four leave the browser and are retained by someone.
  • Do not persist personal or financial data in localStorage, sessionStorage or IndexedDB unless the feature requires it, and clear it on sign-out.
  • Scrub tokens, cookies and request bodies before sending an error to monitoring.

Go deeper: frontend-code-review for the review checklist, and the stack's development skill for the framework-specific form of each rule.