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
datavalue 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.