Home > Blockchain >  `setAttribute` escaping input?
`setAttribute` escaping input?

Time:01-08

I have a bit of trouble correctly understanding whether or not setAttribute escapes the input.

Let's assume we have the following invalid HTML:

<iframe srcdoc="<div style=\"margin: 10px\">aA Name</div>"></iframe>

This will not do anything in the browser. But as soon as I transform this into HTML and JavaScript via the setAttribute method, it works magically:

<iframe></iframe>
const iFrame = document.querySelector("iframe")
iFrame.setAttribute("srcdoc", "<div style=\"margin: 10px\">aA Name</div>")
console.log(iFrame.getAttribute("srcdoc"))

Two observations here:

  1. I get a valid iFrame that shows aA Name in the browser
  2. The console logs: "<div style=&quot;margin: 10px&quot;>aA Name</div>"

That looks escaped to me (even though getAttribute could have done that).

If I try this very same example with the first provided iframe (the invalid iframe HTML code) I get this: "&lt;div style=\"

Do I miss something fundamental here?

CodePudding user response:

It's not setAttribute "escaping" things. There are two things going on:

  1. The main thing is that in the HTML, the srcdoc attribute ends at the " after style=\. Backslashes are not escape characters in HTML. If you want to put a " in an attribute you're delimiting with ", use the named character entity &quot;. Attribute text in HTML source code is HTML, you need to use character entities in some cases. (Alternatively you could use ' to delimit the attribute, then use " literally.)

  2. You're not using the same text in both cases, because of (1) and also because backslashes are escape characters in JavaScript string literals.

If you use the same text, by properly encoding character entities in the HTML and only doing necessary escapes in the JavaScript, it works in the HTML and the JavaScript code:

const iFrame = document.getElementById("x");
iFrame.setAttribute("srcdoc", "<div style=\"margin: 10px\">aA Name</div>")

for (const frame of document.querySelectorAll("iframe")) {
    console.log(frame.getAttribute("srcdoc"));
}
<iframe srcdoc="<div style=&quot;margin: 10px&quot;>aA Name</div>"></iframe>

<iframe id="x"></iframe>

But getting back to setAttribute: It doesn't "escape" things, it uses the text you provide as the attribute value on the element object. "Escaping" is a text concept, but when you're using setAttribute, you're dealing with the DOM directly, not indirectly via text as you would when specifying the attribute in HTML source code.

  • Related