VC007A03:2021·CWE-79

Potential Cross-Site Scripting (XSS)

Cross-site scripting (XSS) via `dangerouslySetInnerHTML`, `innerHTML`, or unescaped HTML output. The classic browser exploit, still extremely common in 2026.

What this rule detects

VC007 flags HTML sinks that bypass auto-escaping: React `dangerouslySetInnerHTML` (except JSON.stringify'd JSON-LD), `element.innerHTML` set to anything other than a plain quoted string, `document.write`, Vue `v-html`, Svelte `{@html}`, Angular `bypassSecurityTrust*` calls, and Express `res.send`/`res.write`/`res.end` of an HTML template literal containing request data. It flags these sinks whether or not the value comes from a user. It skips files that use DOMPurify or another sanitizer, unless they also call `bypassSecurityTrust*`. EJS `<%- %>` and Handlebars `{{{ }}}` output is not checked.

Vulnerable vs. safe code

Vulnerable
// User content rendered as HTML — they can inject <script> tags.
function Comment({ comment }: { comment: { body: string } }) {
  return (
    <div
      className="comment"
      dangerouslySetInnerHTML={{ __html: comment.body }}
    />
  );
}
Safe
// Option 1: just render as text. React auto-escapes.
function Comment({ comment }: { comment: { body: string } }) {
  return <div className="comment">{comment.body}</div>;
}

// Option 2: if you genuinely need HTML, sanitize first with DOMPurify.
import DOMPurify from "isomorphic-dompurify";

function Comment({ comment }: { comment: { body: string } }) {
  const clean = DOMPurify.sanitize(comment.body);
  return (
    <div
      className="comment"
      dangerouslySetInnerHTML={{ __html: clean }}
    />
  );
}

About A03:2021 — Injection

Injection happens when user input is concatenated directly into SQL queries, shell commands, HTML, or any other interpreter. Injection has appeared in every edition of the OWASP Top 10 since the first list in 2003, and ranked #1 in 2010, 2013 and 2017.

Impact: SQL injection: attacker reads or modifies your entire database. Command injection: attacker runs arbitrary shell commands on your server. XSS: attacker steals session cookies and impersonates other users. Each one is typically a critical-severity finding.

How to fix it: Always use parameterized queries (prepared statements) for SQL. Never use template literals or string concatenation with user input in queries. For HTML output, use your framework's auto-escaping. For shell commands, use APIs that take an array of arguments instead of `exec()` with a string.

Common patterns in this category:

  • SQL queries built with string concatenation or template literals
  • `child_process.exec()` called with user input concatenated into the command
  • `dangerouslySetInnerHTML` with user-controlled data
  • `eval()` or `Function()` called with user input
  • `innerHTML` assignment without sanitization

Framework mapping

Findings from this rule map to the following framework controls. This is an informational mapping, not an audit, certification, or attestation.

SOC 2
CC6.1, CC7.1
ISO 27001
A.8.25, A.8.28
OWASP Top 10
A03:2021 — Injection
CWE
CWE-79

See the full compliance coverage page for how every rule maps to OWASP Top 10 and CWE, and which rules also carry informational SOC 2 and ISO 27001 cross-references.

Scan your code for VC007

Free, no signup: paste code or upload a file, or run npx xploitscan@latest scan . The free scan runs 30 core rules; paid plans run all 223.

Scan Your Code →

Related rules in A03:2021