Cross-site scripting through script-tag content

Cross-site scripting through script-tag content

Description

Inserting an externally controlled string directly as JavaScript source inside a <script> element lets an attacker run code with the page's permissions. HTML text escaping or HTML sanitization cannot make arbitrary JavaScript source safe.

Potential impact

  • Scripts may steal accessible authentication information and compromise a session.
  • Arbitrary JavaScript may run in a user's browser.
  • Pop-ups or forms on a trusted page may deceive users into disclosing information.

Remediation

  • Do not use external input directly as JavaScript source.
  • Implement the required operations in fixed code, and let external values select only operations associated with allowed identifiers.
  • Keep data separate from code and serialize and handle it for its actual output context.

Examples

Before

javascript
// Input is inserted as script source
const userInput = req.query.data;
const html = `<script>${userInput}</script>`;
res.send(html);

After

javascript
// Select fixed script code
const userInput = req.query.data;
let scriptSource = "alert('prepare')"
if (userInput == "test") {
    scriptSource = "alert('test')"
}
const html = `<script>${scriptSource}</script>`;
res.send(html);

Explanation:

  • Before: The request's data value is inserted directly into the script body.
  • After: The input is only compared with the identifier test. The script returned in the response is fixed in the application; the input string itself never becomes executable source.

References