Bug Bounty Guest Post: Local File Read via Stored XSS in The Opera Browser

Opera manages a Bug Bounty program where researchers can report vulnerabilities in Opera’s software and be rewarded for it. For high-quality reports, we like to invite researchers to write about their findings.

In this post, Opera’s Security Team has invited Bug Bounty Hunter Renwa to write about a recent vulnerability that he reported, which was subsequently fixed and a $4,000 USD reward given. What follows is his write-up and experience.

I like testing the security of browsers. So when I found out that Opera offers bounties for finding vulnerabilities in its browser, I started looking. This post outlines one of the vulnerabilities I found: the potential for a webpage to retrieve screenshots of local files from users.

A pin on my Opera Pinboard.

Given that Opera is Chromium-based, the first thing I did was download a fresh version of the Opera Browser, and look at the new features they had added. One of those features is called Opera Pinboards. It’s basically a note/bookmark saver which can be shared with other users, to which you can add text, images, and links.

The URI for this service is When opening this page in Opera, however, I was redirected to opera:pinboards. The opera: scheme is a special location in Opera, similar to Chrome’s chrome:, and has special permissions which normal pages don’t have. By using a web proxy, I found that when adding a new link as a pin to my pinboard, a request is made to as so:

POST /v1/items HTTP/2
Content-Type: application/json

{“items”:[{“pos”:{“x”:6,”y”:1},”title”:{“v”:”Hello”},”desc”:{“v”:”Check my cool website”},”video”:false,”link”:{“href”:””,”title”:”it’s me”}}]}

The URI inside the tag is parsed by the browser, and sent to the pinboard API, before being added to the local version in opera:pinboards.

My idea was that, if I could add a pin to opera:pinboards that link to a javascript URI, I could perform cross-site scripting (XSS) from within the privileged scheme. After performing many tests, I found that pinning the URI was possible, and it showed up in my pinboard as a clickable link! Thus, we have XSS!

After many more tries, I eventually came up with the payload javascript:’’;alert(1), which, upon clicking within my pinboard, caused a popup. However, there was a small problem: the tag within the pinboard interface used the attribute target=_blank, which meant that any link clicked on the page would open in a new window, and wouldn’t execute javascript within the page. Luckily, there’s a small trick for that: if you Command (Ctrl) + Click or Middle-Click the link, the code runs successfully.

With simple XSS on the opera:pinboards page, I wanted to show a greater impact than just simply causing a popup when clicking on a link — because who cares about that?

As mentioned, the opera: scheme has more permissions than normal webpages: it also has access to some native function calls, and allows for the viewing of other tabs, bypassing the browser’s same-origin policy (SOP). It also allows for the loading of the file: scheme, which can be used to view local files. However, it didn’t allow all native functions to be used, which would allow complete control and access to other tabs (e.g. injecting javascript which would copy the whole page’s contents and send it to my server).

Putting all of this information together, I made a script that would do the following:

  1. Create a new tab using the native function chrome.tabs.create. In this case, the new tab opened file:///etc/passwd.
  2. Create a screenshot of the opened tab using the same function which Opera Pinboards uses to create thumbnails for pins, opr.pinboardPrivate.getThumbnail.
  3. Send the screenshot, in a base64-encoded PNG, to my server, which I could then view.

Creating a new pinboard that imported the script to execute all of these steps, I added a new pin which, when clicked, sent a screenshot of my stolen /etc/passwd file. I sent video proof of concept to Opera via their BugCrowd page.

After reporting the bug, I received a great response from the Opera Bug Bounty Council, and the bug was fixed within one day, with a reward paid out about one month later.

Thanks For Reading!

Bounty: $4,000 USD.

User comments


You deserve a better browser

Opera's free VPN, Ad blocker, and Flow file sharing. Just a few of the must-have features built into Opera for faster, smoother and distraction-free browsing designed to improve your online experience.

Download now