Summary
In 2016 Uber lost the data of 57 million riders and drivers, and then it lost something arguably worse: the argument that you can quietly pay a breach away. The break-in itself was routine, attackers found Amazon cloud keys hardcoded in one of Uber's private code repositories and used them to download a backup database. What made it infamous was the response. Instead of disclosing the breach, Uber paid the hackers $100,000 to delete the data and keep quiet, dressed up as a bug-bounty reward. When it came out a year later, the cover-up cost Uber a $148 million settlement and made its security chief the first executive criminally convicted over a breach response. It is two lessons in one: keep secrets out of your code, and never cover up a breach.
How it happened
The technical part was ordinary, and Uber had seen it before. Attackers scanned GitHub and found AWS access credentials hardcoded in a private Uber repository. They reached that private repo because Uber engineers were using personal GitHub accounts without enforced MFA and reusing passwords that had been exposed in earlier breaches. With the plaintext AWS key, the intruders authenticated to an Amazon S3 bucket Uber used for backups and, over roughly a month, downloaded the rider and driver datastore, about 57 million people, including some 600,000 driver's license numbers. Uber had already suffered a near-identical breach in 2014 (also an AWS key exposed on GitHub), which the FTC was actively investigating at the time.
Then came the part that made history. Rather than report the breach, Uber, under its chief security officer Joe Sullivan, paid the attackers (Brandon Glover and Vasile Mereacre, who ran the same extortion scheme against LinkedIn's Lynda.com) $100,000 in Bitcoin, in two $50,000 payments, to delete the data and stay silent. Uber disguised the payment as a bug-bounty reward and had the hackers sign non-disclosure agreements that falsely stated no data had been taken. The timing was the damning part: just ten days earlier, Sullivan had given sworn testimony to the FTC about Uber's data-security practices, part of the agency's investigation into that earlier 2014 breach. Concealing a second, identical breach while that inquiry was live is what turned non-disclosure into obstruction. The breach stayed hidden for a full year.
The damage and the cover-up
The data itself, 57 million users and 600,000 driver's licenses, was a serious breach. But the concealment is what defined the case. After it surfaced in November 2017 under a new CEO, Uber paid $148 million to settle with all 50 states and DC, then the largest multistate data-breach settlement ever, for the year-long failure to notify, and accepted an FTC order requiring a 20-year privacy program. Its former CSO Joseph Sullivan was criminally convicted in October 2022 of obstruction and misprision of a felony, the first time a security executive was convicted for mishandling and concealing a breach; he was sentenced to three years' probation, and the Ninth Circuit upheld the conviction in March 2025, settling it as precedent. It became a watershed moment for the personal legal liability of security leaders and for breach-disclosure obligations.
Why Uber 2016 still matters
It carries two lessons. First, hardcoded secrets: an AWS key in a repository is a loaded gun, because git history is permanent, scanners find it fast, and a single key reached a full backup of the company's data, the second time Uber was breached the very same way. Never hardcode credentials; load them from a secrets manager or IAM roles, add pre-commit scanning and push protection, rotate immediately on any leak (deleting the commit does nothing, since it persists in history), and scope keys to least privilege. Second, cover-ups are catastrophic and now personally criminal: concealing a breach compounds the harm and, since the Sullivan conviction was upheld on appeal, can land the security leader in the dock. Disclose promptly and honestly. It is the same hardcoded-credential-in-a-repo pattern that started the Internet Archive breach.
How to fix it
- Rotate and revoke the leaked AWS key immediately (deleting the commit does not help, since it lives in git history), and scope remaining keys to least privilege.
- Disclose the breach promptly and honestly to users and regulators; concealment compounds the harm and, since the Sullivan case, the personal legal risk.
- Scan all repositories for other hardcoded secrets and migrate to a secrets manager or IAM roles.
How to avoid it
- Never hardcode AWS keys in code; load credentials from a secrets manager or IAM roles at runtime instead of any repository.
- Add pre-commit secret scanning and enable GitHub push protection to block credential commits before they reach history.
- Rotate and revoke any leaked AWS key immediately; deleting the commit is not enough since it persists in git history.
- Scope IAM credentials to least privilege so a leaked key cannot reach backup S3 buckets or full datastores.
- Enforce SSO and mandatory MFA on source-control accounts, and forbid reusing passwords across services.
References
- https://www.justice.gov/usao-ndca/pr/former-chief-security-officer-uber-convicted-federal-charges-covering-2016-hack
- https://www.npr.org/2018/09/27/652119109/uber-pays-148-million-over-yearlong-cover-up-of-data-breach
- https://www.bakerbotts.com/thought-leadership/publications/2025/march/ninth-circuit-upholds-conviction-of-former-uber-security-chief-joseph-sullivan-in-connection-with-20
- https://www.justice.gov/usao-ndca/pr/florida-man-and-canadian-national-plead-guilty-hackingextortion-conspiracy
- https://www.ftc.gov/business-guidance/blog/2018/04/ftc-addresses-ubers-undisclosed-data-breach-new-proposed-order
Related vulnerabilities
All Secrets →- CRITICALSECRET-HARDCODED-SOURCE
Hardcoded secrets are API keys, database passwords, OAuth tokens, and private keys written directly as string literals into application source and committed to version control. Because they are plaintext constants, automated scanners (Trufflehog, Gitleaks, GitHub secret scanning) trivially recover them by pattern-matching commit contents against known token formats and high-entropy strings, so a single push to a public host exposes the credential to anyone watching the commit stream within seconds. GitGuardian's State of Secrets Sprawl reported 12.8 million new secrets leaked on public GitHub in 2023, rising about 25% to 23.8 million in 2024, with generic secrets making up 58% of detections. The problem is not limited to public code: GitGuardian found 35% of scanned private repositories also contained plaintext secrets, and AWS IAM keys appeared several times more often in private than public repos. Once committed, a leaked credential can grant direct access to production databases, cloud accounts, and third-party services.
- HIGHSECRET-TOYOTA-TCONNECT-2022
On October 10, 2022 Toyota disclosed that data for up to 296,019 customers of its T-Connect vehicle-connectivity app had been exposed for nearly five years. A development subcontractor published part of the T-Connect source code to a public GitHub repository in December 2017, and that code contained a hardcoded access key for a data server holding customer records. Because the repository was public, anyone could read the embedded key and use it to authenticate to the server storing customer email addresses and management (customer control) numbers. The exposure ran from December 2017 until the public repository was noticed and access restricted on September 15, 2022. Toyota changed the affected database keys on September 17, 2022 and warned customers of phishing risk, while stating it could not completely rule out third-party access; names, credit card data, and phone numbers were not stored in the exposed dataset. This is distinct from Toyota's separate 2023 cloud-configuration exposure.
- CRITICALSECRET-STARBUCKS-JUMPCLOUD-2019
On October 17, 2019 security researcher Vinoth Kumar reported via HackerOne that a Starbucks developer had committed a JumpCloud API key to a public GitHub repository. JumpCloud is a directory-as-a-service and identity-management platform, and the exposed key granted access to internal systems, allowing an attacker to list systems and users, run commands on internal hosts, take control of the associated AWS account, and add or remove user access. Because the key sat in a public repository, anyone scanning GitHub could retrieve it and reach Starbucks' internal directory and infrastructure. Starbucks rated the issue critical as significant information disclosure, removed the repository and revoked the key by October 21, 2019, and paid Kumar a $4,000 bounty, the maximum for critical findings.
- CRITICALSECRET-GIT-HISTORY
Git is a content-addressable store: every version of every file is saved as an immutable blob object referenced by commits, so deleting a secret in a later commit or removing the file entirely leaves the original blob intact and fully reachable in history. Anyone who clones or forks the repository receives the complete object database and can recover the credential by walking old commits (git log -p, git rev-list, or extracting the blob by its hash), which is why a secret 'removed' in HEAD is still public. Truly purging it requires rewriting history with git filter-repo or the BFG Repo-Cleaner to drop the blob and force-pushing, but GitHub warns that existing clones, forks, pull-request references, and cached commit views may still expose it. GitHub's own guidance is explicit: once a secret has been pushed, consider it compromised and rotate it, because rewriting history cannot guarantee no one already copied it. Rotation is the only reliable remediation; history rewriting is cleanup, not a fix.
- HIGHSECRET-CLIENT-EMBEDDED
Any secret shipped to code that runs on a user's device is public by definition, because the user controls the runtime and can read everything in it. API keys and cloud credentials in a JavaScript front-end sit in plaintext inside the served bundle and are visible via browser dev tools or by downloading the .js file, while keys compiled into mobile apps are recoverable by unzipping the APK/IPA and decompiling with tools like apktool, jadx, or strings to dump embedded constants. Symantec's threat-hunting team found over 1,800 mobile apps with hardcoded AWS credentials, mostly on iOS, and 77% contained valid, live AWS access tokens granting access to private cloud services, with nearly half exposing S3 buckets holding millions of files (September 2022). CloudSEK separately reported roughly one in 200 mobile apps leaking hardcoded private keys, including 40-plus apps with over 100 million combined downloads. The fix is architectural: secrets must live on a backend the client authenticates against, never in the shipped artifact.
- HIGHSECRET-CONTAINER-LAYER
A container image is a stack of immutable, content-addressed layers where each Dockerfile instruction (RUN, COPY, ADD) commits a filesystem diff, so a secret introduced in one layer persists permanently even if a later layer deletes the file. Deleting with RUN rm only writes a whiteout entry in a higher layer; the original bytes remain in the earlier layer's tarball and are recoverable by extracting the image and reading individual layer archives. Secrets passed via ARG or ENV are worse still, as their values are recorded in image metadata and surface directly through docker history, exposing them to anyone who pulls the image or has registry layer-download permissions. Once such an image is pushed to a public or shared registry, the credential leaks to every consumer. BuildKit's RUN --mount=type=secret solves this by exposing a secret to a single build step without writing it to any layer, leaving no trace in the final image.