neobotnet / blog / company-of-the-week
company of the week·8 min read

company of the week: bolt

Bolt is the European mobility super-app — rides, food delivery, e-scooters, car rental — that rebranded from Taxify in 2019. It runs a public bug bounty on Bugcrowd, which puts its public web surface in scope for outside research. neobotnet's full index is in /urls.

The scope is two roots. bolt.eu runs the live product. taxify.eu, the name Bolt retired, still publishes the org chart.

2
in-scope roots
659
dns resolved
113
live web servers
181
on the retired brand
118,311
urls indexed

read from dns: two names, two jobs

Public DNS hands you the shape of the company first. Bolt's scope is two apex domains, and they split the work cleanly — one runs the product, the other is a map of everything behind it:

bolt  ·  2 in-scope roots  ·  one live brand, one retired one still talking
│
├─ bolt.eu ......... 478 hostnames, 98 live ....... the product
│                    ride · food · scooters · Drive · business · cards
│
└─ taxify.eu ....... 181 hostnames, only 15 live .. the org chart (retired 2019)
   resolve, serve    │
   almost nothing    ├─ 17 world regions, each an "-admin" back office + a "-company" portal
                     │    africa · britain · kazakhstan · nigeria · tallinn · ukraine · …
                     │    every region mirrored as a ".prelive." staging twin
                     │
                     └─ the platform itself, named in the hostnames
                          pki · ocsp · crl · node-cert  ← Bolt's own certificate authority
                          debrepo · fe-envoy-mtls · zt · nlb · opsmonitor

Of taxify.eu's 181 resolving names, only 15 serve a real page — the other ~92% resolve and show nothing. On a live product you'd read the pages; here the value is the names. Read as a list they're an org chart: 17 world regions, each with an -admin back office and a -company portal, each mirrored as a .prelive. staging copy. Underneath sits the platform itself — Bolt runs its own PKI (the private certificate authority a company uses to issue its own internal TLS certs, visible as pki, ocsp, crl, node-cert), a debrepo package repository, an Envoy service mesh, and a zt zero-trust gateway. None of it has to serve a page to be useful: the name alone tells an outsider which internal systems exist and what each one does.

read from http: the whole super-app, one host per service

bolt.eu's live hosts read like a product catalog. neobotnet pulls the page title off every host that answers HTTP 200 — here is the estate, each service named with the host that serves it:

bolt.eu live surface  ·  113 hosts answer 200  ·  the super-app, host by host
│
├─ consumer ... ride.bolt.eu ......... "Bolt - View ride status"
│               food.bolt.eu ......... "Bolt Food: Food Delivery and Takeaway"
│               mm-web.bolt.eu ....... "Bolt Micromobility"          (the e-scooters)
│               drive-owner.bolt.eu .. "Bolt Drive | Owner"          (the car-rental arm)
│               business.bolt.eu ..... "Bolt for Business"
│               cardprogram.bolt.eu .. "Bolt Business"               (+ balance, paytobolt)
│
├─ supply ..... driver.bolt.eu ....... "Driver portal"
│               fleets.bolt.eu ....... "Sign in | Bolt Fleet Portal"
│               courier.bolt.eu ...... "Courier Portal"
│
└─ internal ... iam.bolt.eu .......... "React App - IAM"             (the identity console)
                atlas.bolt.eu ........ "Atlas Map Tools"
                city.bolt.eu ......... "Bolt City Mobility Dashboard"
                pass.bolt.eu ......... "Yopass: Share Secrets Securely"
                admin.bolt.eu ........ "Admin Panel | 400"           (answers, then rejects)

Two things carry over from DNS. The internal consoles are reachable but gated — admin and beehive answer Admin Panel | 400, loading the gate without opening it; iam fronts identity; pass is a Yopass one-time-secret box. And nearly every host above has a staging twin: 252 non-production hostnames.prelive., test, sandbox — resolve publicly, about 38% of the estate, 33 of them answering 200. A staging host that resolves on the open internet is the softer copy of production, reachable by an outsider.

read from the urls: read what's served, not what's named

Every parameter on every crawled URL is classified against a signal taxonomy — tokens, credentials, cloud keys, emails. Across 118,311 URLs the loud stuff is clean: no cloud keys, no credentials, no emails or phone numbers in parameters. The disclosures are one level down, in what the URLs serve, and you find them by content type rather than by file name. Filter Bolt's index for a .pdf ending and you get 3 files. Filter for what actually returns application/pdf and you get 744. The gap is every document served by an endpoint instead of a static file — which is exactly where the interesting ones are.

1 — customer invoices, reachable by link. invoice.taxify.eu and invoice.bolt.eu return a PDF invoice to anyone who holds the URL: invoice.taxify.eu/?s=<uuid>, where the uuid is the only thing between a visitor and the document. There's no login — the link is the credential. neobotnet holds 711 of these, all answering 200, and 668 sit on the retired taxify.eu host. The id isn't guessable — it's a random uuid — so this isn't proof the whole invoice store is walkable. It's proof of something narrower and still bad: a link that doubles as a credential doesn't stay secret. It rides into CDN logs, browser history, the Referer header, and, as these 711 show, the crawl archives anyone can pull from. A URL that unlocks a document, sitting in a public archive, is a document one search away from the wrong person. This is a signal, not a confirmed vulnerability — and the kind that belongs in a disclosure report to Bolt's program, not spelled out here. neobotnet keeps no invoice and no id.

see the invoice endpoints in /urls →

invoice pdf endpoints keyed by a uuid in the url, ids redacted, in /urls

2 — "download all my data," in 39 languages. Bolt publishes its GDPR data-export flow as a plain URL: bolt.eu/<locale>/privacy/rider-data-export/download, and the matching driver-data-export. neobotnet indexed 48 across 39 localesen-at, el-gr, ar-lb, and on. A "download everything we hold on you" endpoint is the highest-value target in any app: get its ownership check wrong and it returns one person's full history to another. The landing page is public by design; the export behind it is the door a researcher tests. Enumerated this cleanly, the flow is pre-mapped.

see the data-export endpoints in /urls →

bolt's rider/driver gdpr data-export download endpoints, one per locale, in /urls

3 — a download link that carries its own expiry. bolt.eu/api/public-documents/download/<file-id>?sig=<signature> serves documents behind a signed URL — 30 in the index. The signature is readable: base64(an expiry timestamp) then a hash, so the URL announces when it dies (every one here expired in early May 2026), and the file ids are Google Drive's own format, so Bolt is fronting Drive-hosted documents. Worth testing: whether the signature actually binds the file id, or a swapped id rides the same one.

see the signed document links in /urls →

signed /api/public-documents/download links with a base64 expiry in the sig parameter, in /urls

4 — verification tokens that name the account. Eight URLs carry a JSON Web Token in a token= parameter — signed, not encrypted, so anyone holding the URL reads the payload. neobotnet decodes each: three email-verification links whose payload holds the account's user id and the customer's email, two support links carrying a case id. All expired between 2020 and 2023; nothing live, no value leaves the index. The pattern outlives them: a private one-time link put its token in the URL, so the URL — and the account it names — went everywhere URLs go.

see the jwt tokens in /urls →

email-verification and support jwts in token= parameters, token and payload redacted, in /urls

The same content-type lens walks a scare back: those 744 PDFs also include ~90 public terms-and-conditions and Bolt-for-Business tutorials (T_and_C_Services.pdf, add_users_en.pdf) — documents meant to be downloaded. Same signal, opposite meaning; reading what's served is what tells them apart.

what it adds up to

Bolt's core is tight: internal consoles gated, and 118,311 URLs with no keys and no credentials in parameters. What's exposed is served one layer down, and it ranks like this for anyone working the program:

  1. the invoice links — 711 customer-invoice PDFs reachable by a ?s=<uuid> URL with no login, 668 of them on the retired taxify.eu host. Capability URLs that leaked into public archives; this is the one that belongs in a disclosure report first.
  2. the data-export endpoint — the "download my personal data" flow, enumerable across 39 locales; test the ownership check on the export itself.
  3. the retired brand is still servingtaxify.eu isn't only leaking names; it hosts the invoice endpoint and the region-by-region org chart, and 252 non-production hosts resolve on the open internet.
  4. signed links and tokens that travel — the document signatures and the verification JWTs; dead now, but the pattern outlives the ones that prove it.

Two things stated plainly, the way this series always closes. Every item above is a signal, not a confirmed vulnerability — neobotnet surfaces the shape; confirming exploitability is the researcher's job. And the right destination for anything live is Bolt's Bugcrowd program, not a blog post.

next week

neobotnet runs the same pass on a different in-scope program every week. Subscribe via RSS or browse the company of the week archive.