Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Encode output for its exact sink context
Apply the encoding that matches the destination context (HTML body, attribute, JS, URL, CSS); a single generic escape is not safe across all sinks.
Bad example
| 1 | function escapeHtml(s: string) { |
| 2 | return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); |
| 3 | } |
| 4 |
|
| 5 | // Reused everywhere, including inside a URL/JS context: |
| 6 | const link = `<a href="${escapeHtml(userUrl)}">profile</a>`; |
| 7 | const inline = `<button onclick="select('${escapeHtml(userId)}')">go</button>`; |
Explanation (EN)
HTML-entity escaping only neutralizes the HTML body context. In the href, escapeHtml does nothing against javascript:alert(1). In the onclick (JS context), a value like ');alert(1)// breaks out of the string because '/) are not handled. Using one escaper for every context leaves multiple sinks exploitable.
Objašnjenje (HR)
HTML-entity escaping neutralizira samo HTML body kontekst. U href-u escapeHtml ne radi nista protiv javascript:alert(1). U onclick (JS kontekst) vrijednost poput ');alert(1)// izlazi iz stringa jer '/) nisu obradeni. Koristenje jednog escapera za svaki kontekst ostavlja vise sinkova ranjivima.
Good example
| 1 | // HTML body / attribute: let the framework encode (React {value}) or use a context-specific encoder. |
| 2 | // URL context: validate scheme, then encodeURIComponent each dynamic segment. |
| 3 | function safeUrl(raw: string): string | null { |
| 4 | const url = new URL(raw, window.location.origin); |
| 5 | return ['http:', 'https:'].includes(url.protocol) ? url.toString() : null; |
| 6 | } |
| 7 |
|
| 8 | // JS context: don't interpolate into inline handlers at all — bind via the DOM/JSX. |
| 9 | <button onClick={() => select(userId)}>go</button> |
| 10 |
|
| 11 | // If you must emit JS data, serialize as JSON in a data attribute and read it, never string-concatenate. |
| 12 | <div data-user-id={userId} /> |
Explanation (EN)
Each context gets its matching defense: framework auto-encoding or HTML encoder for markup, scheme validation + encodeURIComponent for URLs, and structural binding (props/data attributes) instead of string interpolation for JS. The rule of thumb: stop building executable contexts by concatenation; let the platform encode, or pass data structurally.
Objašnjenje (HR)
Svaki kontekst dobiva odgovarajucu obranu: auto-encoding frameworka ili HTML encoder za markup, validacija sheme + encodeURIComponent za URL-ove, te strukturno povezivanje (props/data atributi) umjesto string interpolacije za JS. Pravilo: prestani graditi izvrsne kontekste konkatenacijom; pusti platformu da encodira ili proslijedi podatke strukturno.
Notes (EN)
OWASP XSS Prevention Cheat Sheet defines the canonical encoding rules per context; ASVS V5 requires context-aware output encoding at the sink.
Bilješke (HR)
OWASP XSS Prevention Cheat Sheet definira kanonska pravila enkodiranja po kontekstu; ASVS V5 zahtijeva kontekstualno enkodiranje izlaza na sinku.
Exceptions / Tradeoffs (EN)
Trusted, fully static literals need no encoding. Frameworks with built-in contextual auto-escaping (React JSX text, Angular interpolation) handle the HTML body context for you — the rule still applies to attributes, URLs, and JS where they don't.
Iznimke / Tradeoffi (HR)
Pouzdani, potpuno staticki literali ne trebaju encoding. Frameworci s ugradenim kontekstualnim auto-escapingom (React JSX tekst, Angular interpolacija) rjesavaju HTML body kontekst — pravilo i dalje vrijedi za atribute, URL-ove i JS gdje to ne rade.