← Back to all reports

Enumerable Lead ID Exposes Millions of Car-Buyer Records and Lets Anyone Overwrite Their Contact Details

Reported Jun 30, 2026
Severity Critical
Platform Web / API
Vulnerability Class Broken Access Control / IDOR (CWE-639)
Target Type Automotive Lead-Generation Platform
Impact Anonymous read of millions of leads plus unauth contact overwrite

The Risk

Anyone on the internet could pull the personal records of several million people who had asked for help buying a car, with no login and no account. Each record included the person's full name, email, phone number, and for many, their home street address. Getting the next person's record was as simple as adding one to a number in a web address, so all of them could be copied in a single automated sweep. On top of that, the same open door let an attacker silently change a person's saved phone number, meaning the buyer's own contact details could be corrupted or redirected without anyone noticing.

The Vulnerability

Every shopping-assistant lead on the platform was tied to a small sequential lead ID. That number ran densely from the low numbers up into the several millions, and a new one was minted for every consumer who used the tool. Because it was a plain incrementing integer, guessing the next valid record was trivial: add one.

The platform had a correctly-built read control. A lead-info API keyed by that same ID checked for a valid bearer token and refused anonymous callers outright:

curl 'https://www.example-auto.com/api/leads/info?leadId=1'
# => {"errorMessage":"Unauthorized call, pass proper bearer token","success":false}

The problem was that several other endpoints and pages exposed the exact same lead data (and the ability to modify it) over the exact same enumerable key, but skipped that authorization check entirely. Three separate paths were broken:

  • A funding/offer read endpoint returned the full lead record to anonymous callers.
  • The public server-rendered survey pages embedded the protected lead object, including its internal lead ID, directly into the page.
  • Two write endpoints accepted anonymous callers and let anyone overwrite a consumer's phone number and tamper with their decision state.

The same data the bearer-gated API guarded was served, and modified, with no credentials at all through these other routes.

The Attack

Unauthenticated Read of Full PII

A single anonymous GET to the funding/offer endpoint returned a real consumer's complete record. The endpoint returned the record's fields base64-encoded inside an offer URL, so the raw response only needed to be URL-decoded and base64-decoded to recover the plaintext:

curl 'https://www.example-auto.com/api/leads/funding-offer?deviceType=non-mobile&leadId=100000&src=email'

Decoded, one request yielded a full identity and contact record (placeholder values shown; real records were unredacted):

  firstName  : Jane
  lastName   : Sampleton
  email      : [email protected]
  phoneNumber: 5550000000
  address1   : 123 Placeholder Ave
  zip        : 00000
  state      : XX
  residence  : rent

Every valid record disclosed full name, email, phone, ZIP, state, and home-ownership status. About a third of records additionally disclosed the full residential street address. An out-of-range ID returned no offer, so valid records were trivially distinguishable from invalid ones, giving a clean enumeration oracle.

Server-Rendered Page Auth Bypass

The protected lead API refused anonymous reads, yet the public server-rendered survey pages returned the same record. When one of these pages was requested for a given lead ID, the server fetched the protected lead object using its own bearer token and embedded the result directly into the page's data payload. Scraping that payload leaked the consumer email and, critically, the internal lead ID:

curl 'https://www.example-auto.com/survey-pages/survey?leadId=1' \
  | grep -oE '(customerEmail|internalLeadId)[^,]{0,30}'

A second survey route additionally leaked full name and phone number when the customer object was populated. This server-side rendering bypass mattered for two reasons. It was a bulk PII exposure in its own right, and it handed the attacker the internal lead ID that the phone-overwrite endpoint required.

Unauthenticated Write and Decision Tampering

The write endpoints accepted anonymous callers with no token, cookie, or session. The phone-update endpoint executed a write with no credentials at all. Pointed at a deliberately non-existent ID (well beyond the real id space) with a placeholder number, to avoid touching a real consumer, it still returned success:

curl 'https://www.example-auto.com/api/leads/save-phone?leadId=999999999&phoneNumber=0000000000'
# => {"success":true,"validationError":false}

The decision-update endpoint, called with no parameters, returned a parameter-validation error rather than an authorization error, confirming it processed anonymous callers and only checked that required fields were present:

curl 'https://www.example-auto.com/api/leads/update-decision'
# => {"errorMessage":"The following required parameters were missing: ...","validationError":true}

To prove the write actually persisted, without altering any consumer-visible field, the current decision value was written back to itself unchanged. The decision value stayed identical, but the server's stored decision timestamp advanced to the exact moment of the anonymous call. That advancing timestamp proved the unauthenticated write reached the backing store rather than being silently dropped.

Enumeration and Scale

Consecutive lead IDs returned distinct live records, so both the read and the supply of write targets were bulk-harvestable rather than a single stale URL. Sampling across the range returned a live lead every time, and there was no rate limiting on any of the endpoints. The read directly enabled the write: the survey pages leaked the internal lead ID for any sequential ID, and that ID was exactly the key the phone-overwrite endpoint consumed.

The Impact

Two consumer harms stacked on the same broken key.

ExposureDataScale
Anonymous read (funding/offer + survey pages)Full name, email, phone, ZIP, state, home-ownership status; about a third also home street addressRoughly two million records with full contact data; on the order of several million enumerable leads overall
Anonymous write (phone + decision)Overwrite of stored phone number; tampering of decision state and historyAny of the several million leads, addressable directly by sequential ID

The read exposure was mass, contactable, identity-grade PII tied to real automotive purchase-intent leads, including physical home addresses. Harvested at scale with no account, it enables targeted phishing, voice-call scams, text-message fraud, and physical-address-based fraud or doxxing against people actively in the process of buying a car.

The write exposure was an integrity attack on the dealer-lead pipeline. Contact data could be corrupted or redirected and decision history tampered with, sabotaging real dealer workflows and the consumers attached to them. Because the read handed over the internal lead ID needed for the phone overwrite, the two findings combined into a single weaponizable chain: harvest the record, then silently rewrite the consumer's contact details. No authentication, no victim interaction, and no special tooling were required at any step.

For accuracy: the leaked schema was fixed and did not include financial, credit, government-ID, or date-of-birth fields. The severity rested on the combination of zero authentication, mass enumerable scale, residential-address-level PII, and unauthenticated modification, not on financial-grade data.

Remediation

  • Enforce the same bearer-token authorization on the funding/offer read endpoint, the write endpoints, and the server-rendered survey pages that the lead-info API already enforces. The correct control already exists on one endpoint; apply it consistently to every path that touches a lead.
  • Never embed a server-fetched protected object into a publicly reachable rendered page. The server-side render should not expose data the caller could not fetch directly with their own credentials.
  • Add an authorization check on the write endpoints so a caller can only modify a lead they own or are explicitly permitted to touch. Parameter validation is not access control.
  • Replace the sequential integer lead ID with an unguessable, non-enumerable identifier so records cannot be walked one by one, and treat the old sequential values as sensitive.
  • Apply rate limiting and anomaly detection on all lead endpoints to catch bulk enumeration and mass modification.
  • Assess breach-notification obligations for the exposed records and audit access logs for prior bulk enumeration of the affected identifiers.