I've recently tested a web application and found out that it was vulnerable to Stored XSS attacks. However, a peculiar behavior left me a bit puzzled. When I inserted John <script>alert(1)</script>Doe, my browser showed that the script tag was indeed injected correctly, but the alert did not pop up.

When inserting John <img src=x onerror=alert(1)>Doe, the alert popped up immediately upon load.

What I ruled out so far

  • Escaping: I thought perhaps the <script> tags were escaped, and yet for some reason not rendered, but my proxy confirmed that the tags were not escaped.
  • CSP: It occurred to me that a CSP might be in place, but there was none, and also if it had blocked an injected <script> tag, it would also have blocked an injected <img> tag as well.
  • 1
    My first thought was CSP also, but I agree that this seems unlikely in light of 'if it had blocked an injected <script> tag, it would also have blocked an injected <img> tag as well.'. But, just to be sure - did you check that there is no CSP directive in either the response headers for the page, or the meta tags of the page?
    – mti2935
    Nov 2, 2020 at 13:50
  • @mti2935 I checked the headers, but I did not check the meta tags. I keep forgetting that this can be the case too. Let me check
    – user163495
    Nov 2, 2020 at 14:10
  • Is the user content being inserted into the web page client-side using javascript? This happens if the data is sent to the browser as a json file (or something) and then inserted by javascript into an element's innerHTML attribute?
    – nobody
    Nov 2, 2020 at 14:13
  • @nobody How would that make <script> not work, but <img> work? Also I don't know how it is inserted, the js part is heavily obfuscated and I don't have the time to deobfuscate it
    – user163495
    Nov 2, 2020 at 14:18
  • 1
    @nobody may be onto something. I used to dynamically load and insert a lot of HTML with jquery (via $('elem').html(content)) but had issues with script tags not executing when inserted like that. As a result I had to adjust my javascript to pre-parse the HTML, pull out the script tags, inject the "normal" HTML into the element like usual, but then append the script tags to the page with a document.write(). If I have time this afternoon I'll see if I can verify/make an MVP Nov 2, 2020 at 15:20

1 Answer 1


A few possible explanations:

  • CSP: Check headers and meta tags. I agree that the onerror executing makes it unlikely, but I am not sure it would be impossible.

  • Browser XSS filter: Only an issue if you are doing reflected XSS. Turn them off, or use a browser without an XSS filter.

  • Malformed HTML: Are you sure the script tag is actually being interpreted as a tag? Encoding issues, escaping or malformed HTML somewhere else in the document can stop this from happening. To check if this is the case, use the developer tool to see if there actually is a script tag in the DOM.

  • innerHTML: How does the script tag end up in your DOM? Is it done on the client using JavaScript and the innerHTML, insertAdjacentHTML or similar? If so, the following note on MDN explains the problem:

    HTML5 specifies that a <script> tag inserted with innerHTML should not execute.

    Note that there may be a framework between you and setting the innerHTML. To execute the script, you have to create the script element via createElement and append it to the DOM explicitly.

  • 5
    Since you've got a reference to the actual doc I'll skip the process of building a PoC, but the latter is my suspicion. I've encountered that issue as a developer when my scripts weren't loading, and eventually fell back on separating scripts and using document.write for them directly. Nov 2, 2020 at 16:09
  • 4
    I'm actually doing stored XSS, not reflected. So the browser XSS filter would not be able to help. I think the most probable cause is the innerHTML property, since I did not get any CSP messages in my console either (violation would cause a console message)
    – user163495
    Nov 2, 2020 at 16:25

You must log in to answer this question.