
In March 2016, we launched our public bug bounty program. Thanks to the hard work of hundreds of security researchers here is what we have seen in the first 100 days:
- Total reports: 2,030
- Signal-to-noise ratio: ~1:6¹
- Security flaws found and fixed: 161
- Percentage of duplicate reports: ~20%
- Mean first response time: 23hrs, 51min
- Total payout to researchers (USD): $345,120.48
Information like this will be public at https://hackerone.com/uber. These numbers represent a healthy bug bounty program. Specifically:
- Signal to noise: Running a bounty program takes considerable time, and processing about 6 submissions before finding a legitimate issue is a ratio we are happy with. This is done through aggressive low-signal filtering through hacker1, a well-defined program scope, and working to educate researchers.
- Response time: This is how long it takes before a submission gets its first response from the Uber side. It includes weekends and holidays, and the abnormally busy first few weeks of the program becoming public.
- Payouts: We have already noticed severe issues are becoming harder to find, so we plan to raise our bounty amounts to continue to encourage research in this area.
Here’s a glimpse of some of the most interesting bugs found in the first hundred days. All these bugs were fixed and we verified they were not previously exploited.
Remote Code Execution via Jinja Template Injection: $10,000
Remote code execution (RCE) is when an attacker has the ability to run arbitrary code on a server. Server side code execution means the attacker has the freedom to browse the filesystem and execute system calls that are accessible to the currently running process.
Template injection is a class of vulnerability that involves using template framework functionality in an unexpected way. These templating frameworks often have the ability to make system calls. In the event that untrusted user input is supplied to a template framework in a dangerous way, the result can be RCE.
Orange found RCE via Jinja2 template injection in our service that sends out emails. The emails include user-controlled values, like first name, and those values could be mishandled. The service built strings from user-controlled values and passed them into the Jinja2 templating engine, which evaluated that input as Python code. The attacker could run any Python desired, like code to ping uber.com:
{{“”.__class__.__mro__[2].__subclasses__()[46](‘ping uber.com’, shell=True)}}
The solution is to use the render method with template variables instead of building template strings from user-controlled values.
Cross-Site Scripting in developer.uber.com: $3,000
Cross-site scripting (XSS) is a well-known web application vulnerability that can be summarized as user-controlled values being included in an HTTP response without proper output encoding. Without the proper encoding, it becomes impossible for the browser to distinguish between code provided by the web server and code from a potentially malicious user. The impact varies depending on a few browser-level protections (HttpOnly, CSP), but an XSS vulnerability lets an attacker perform any actions that the user currently viewing the page can.
In this instance albinowax found a clever case of XSS via Angular templates in our developer site, developer.uber.com, and you can see his writeup for more details. Angular’s goal with sandboxing is not for security but often goes a long way in making XSS more difficult, so this was a great find.
Bypass Surge Pricing: $3,000
This issue was a surge loophole. Riders could put the pin down to get an Uber ride, see surge pricing, move the pin outside surge pricing, change the address to where their initial pin dropped, and then avoid surge pricing. The bug occurred because the second, fully client-side computed fare defaulted to regular pricing to avoid potentially out-of-date surge pricing multiples. We resolved the issue but this remains a great example of the benefit of bug bounty programs exercising pathways that were not caught by other mechanisms and that good reports mustn’t always be extremely technical.
Scope Changes
The vulnerabilities with the most impact for Uber involve services within our production infrastructure that deal with user data. To ensure that researchers spend time looking at the most important services, we’ve explicitly defined a whitelist of domains for the scope of our program. The full list can be found on our HackerOne scope page.
A major effect of this scope change is that most of Uber’s WordPress instances are no longer in scope. Our WordPress sites— including this blog, www.uber.com/blog—are not hosted within Uber’s infrastructure, are on separate subdomains, and rarely contain Uber customer/employee data. Of the 2,030 submissions we have received, 16.1% have been in WordPress sites. We believe time on both sides of our bug bounty program is best spent on core uber software.
We appreciate all the work done by researchers, and any reports submitted prior to today’s scope change will be honored and awarded as we work through them.
Tools and Transparency++
Through running this bounty program we’ve developed some tooling to help generate and review statistics around our reports. HackerOneAlchemy is a Python package that interacts with HackerOne and Phabricator APIs to generate statistics on reports and identify inconsistencies (e.g., a task closed in Phabricator whose corresponding report in HackerOne is open). HackerOneAlchemy ensures visibility into reports that need extra attention while tracking things like signal-to-noise, amount awarded, spam reports, and duplicates to help us gauge the success of the program. This is now open sourced on our GitHub page, and we welcome improvements and suggestions from the security community! We’ve also recently open sourced a Go HackerOne wrapper, hackeroni, that can be used to interact with the HackerOne API.
Transparency is a key part of building a world-class bug bounty program. Shortly after our program’s launch we started tracking all scope changes in a GitHub repo so researchers would know exactly when these changes were made and why. This has since been added as a feature into HackerOne’s scope page.
Thank You
As always, we are thankful for all our researchers. We encourage everyone to keep bug hunting and strengthening Uber security!
Written by Rob Fletcher, manager of Uber’s Product Security team, with Engineering Security manager Collin Greene and Application Security software engineer Matthew Bryant. Visit our Careers page for more engineering security openings.
Photo Header Credit: “Bug on leaf” by Conor Myhrvold, Osa Peninsula, Costa Rica.
¹ Signal-to-Noise Ratio is calculated as (“resolved” + “triaged”) / (“informative” + “spam” + “NA”). “new”, “duplicate”, and “needs more info” are not considered.

Rob Fletcher, Collin Greene & Matthew Bryant
Rob Fletcher is a manager on the Uber Security Engineering team.
Posted by Rob Fletcher, Collin Greene & Matthew Bryant
Related articles
Most popular

Fixrleak: Fixing Java Resource Leaks with GenAI

Adopting Arm at Scale: Bootstrapping Infrastructure

Adopting Arm at Scale: Transitioning to a Multi-Architecture Environment
