Uncovering a Bug in Cloudflare's Minification Service


A bug in Cloudflare’s Auto Minify service parsed // and /* ... */ within ES6 `template literals` as comments, causing it to truncate lines or entire blocks of code, leading to unpredictable behavior or in rare cases, a code injection vulnerability.

HackerOne report: https://hackerone.com/reports/302289


Cloudflare’s Auto Minify service can automatically minify a website’s resources, including this one’s. I don’t want to plug Cloudflare too much [I swear I don’t work for them! But if you work there and want to change that, shoot me an email ;)], but if you’re already using them and don’t minify your code yourself, consider ticking that box for some (almost) free performance!

The Bug

I’d been experimenting with mining Monero, and while the pool I joined had a website to check how much I’d earned so far, I didn’t feel like visiting it every time and manually converting my balance to USD. I reverse engineered their API (read: popped open the debug console) and wrote up some quick javascript to automate the conversion. Here’s the general idea:

const address = 'XXXXXXXXXXXXXX';
const poolUrl = `https://example.com/api?address=${address}`;

// send some requests and show the results

This worked fine in development, whether through file://, python -m http.server, or even the development mode on Cloudflare, which disables caching and minification. But as soon as I switched it off, my little app broke! After reviewing the code that Cloudflare was serving me, I discovered that instead of giving me the code above, it was instead giving me something like this:

const address='XXXXXXXXXXXXXX';const poolUrl=`https:

Yes! It stripped out everything on that line after the //! Was the service parsing that as a comment and removing it? Well, let’s try /* ... */ style comments and find out! I put together this semi-realistic contrived example:

var domain = 'hackerone';
var url = `www.${domain}.com/*`;
var other_url = `www.${domain}.com/*/`;

If our hypothesis is true, we should expect the crossed out section to disappear upon minification. Hosted on Cloudflare, it looked like this:

var domain='hackerone';var url=`www.${domain}.com`;

We’re on to something!

Does this happen with regular strings as well?

var a = '// single quote double slash';
var b = "// double quote double slash";
var c = '/* single quote C style */';
var d = "/* double quote C style */";


var a='// single quote double slash';var b="// double quote double slash";var c='/* single quote C style */';var d="/* double quote C style */";

That looks normal to me! We’ve isolated the bug to `template literals`, part of ES2015. This makes sense, since the current iteration of Auto Minify launched in 2011. Perhaps there are other similar features that we can exploit?


Outside of some really unfortunate edge cases, this bug really isn’t exploitable. Worst case, the javascript does something that it shouldn’t. Common case, the javascript just breaks from a syntax error.

Here’s the best/most realistic scenario I could come up with, and it’s still super contrived:

var subreddit = 'cloudflare';
var url = `https://www.reddit.com/r/${subreddit}`;
`;console.log('what is up'); // this shouldn't run! `;

Minified, it becomes:

var subreddit='cloudflare';var url=`https:`;console.log('what is up');

which doesn’t break, but instead prints ‘what is up’ to console. I’m sure there’s some more creative way to exploit it, but it’s good enough for a PoC.


Due to the nature of the bug existing in the actual parser, there’s no way to get around this other than avoiding the use of // or /* ... */ in template strings, or turning off Auto Minify entirely. Luckily, Cloudflare fixed it, so it’s no longer an issue.


The folks at Cloudflare were courteous and responded reasonably quickly.

HackerOne report: https://hackerone.com/reports/302289

Jan 03: Bug submitted on HackerOne

Jan 04: Acknowledged by staff

Jan 22: Triaged

Feb 15: Resolved, swag awarded (but I have not received the t-shirt yet, over a month later)

Mar 17: Publicly disclosed

May 21: Swag delivered!