JavaScript

JavaScript

By DeepSource

Audit: insecure assignment to innerHTML property JS-S1012

Security

The innerHTML property is capable of directly changing the DOM structure, thereby opening up possibilities for XSS attacks. If you only want to change the text inside an HTML element, consider using the innerText or textContent property instead. Avoid assigning values that are fetched from 3rd party sources to HTMLElement#innerHTML without proper sanitization. If you must do so, validate and sanitize the data before assignment.

NOTE: If this issue was raised on a code snippet that you're sure was sanitized, consider adding a skipcq comment explaining the reason for the snippet's safety. Alternatively, you could disable this issue for your project in settings.

Assigning values to innerHTML without proper sanitization can open us up to XSS attacks. For example, consider this snippet:

const res = await axios.get("www.website.com/api/resource/id")
const myDiv = document.getElementById("#my-div")
myDiv.innerHTML = "<p>" + res.data +  "</p>"

This snippet is harmless so long as website's API is not malicious, or compromised. However, an attacker may change the response to that endpoint to '<a href="www.other-website.com">Click me!</a>'. This would alter the DOM structure to contain a link that might lead to the attacker's website.

This can be avoided with proper sanitization prior to the assignment to the innerHTML property.

Bad Practice

// Scenario 1:
fetch("www.website.com").then((res) => {
  const myDiv = document.querySelector("#foo")
  myDiv.innerHTML = res.data.html
})

// Scenario 2:
const res = await axios.get("fubar.com")
document.getElementById("my-div").innerHTML = `<span class="important"> ${res.data.markup} </span>`

Recommended

fetch("www.website.com").then((res) => {
  const myDiv = document.querySelector("#foo")
  myDiv.innerText = res.data.html
})


const res = await axios.get("fubar.com")
const secureMarkup = sanitize(res.data.markup)
document.getElementById("my-div").innerHTML = `<span class="important"> ${secureMarkup} </span>`

References