bb-pii
Hunt PII exposure and data leaks — API responses oversharing personal data, unauthenticated data endpoints, leaked documents and exports, ID enumeration leaking PII, cached personal responses, and thi
SKILL.mdskills/bb-pii/SKILL.md
GitHubPII Exposure Hunter
PII bugs = programs' #1 paid scenario ("data exfiltration of customer or seller data"). The bug isn't a vuln class — it's a RESPONSE containing data the requester shouldn't see. 1,122 corpus records; top payouts $12.5k–$50k.
Real-bug anchors (what actually paid — query bb-disclosures for more)
- $50,000 GitHub access token exposure — a credential IS the PII jackpot when it has reach.
- $25,000
/reports/:id.jsondisclosed sensitive user attributes — a JSON detail endpoint over-serving fields. - $12,500 Internal attachments exportable via "Export as .zip" — export features skipping entitlement checks.
- $12,500 View any user's email via a collaborators mutation (GraphQL).
- $7,500 Private program disclosed any user's email via invited-username lookup.
Delta lesson: email/attribute disclosure through invite/collaborate lookups, fat
.jsondetail endpoints, and export features are the paid patterns. Names+addresses of other users via any of these = instant High.
What counts (impact ladder)
- Other users' PII (names, addresses, emails, phones, DOB, orders) — High/Critical
- Own PII over-shared to third parties (trackers, referrer leaks) — Medium, chain-dependent
- Aggregate/statistical leaks enabling deanonymization — Low/Medium
- Internal identifiers without personal data — Low (usually informative)
The six overshare patterns
- Fat objects: endpoint returns the full user object where the UI shows one field (GET profile returns password hash, internal notes, isFraudFlag, geo). Compare response fields vs what the page renders.
- Unauthenticated access: personal endpoints answering without session (test every
/api/me,/account, session-status, logged-in-widget endpoint cookieless). Includes "anonymous-allowed" lookup endpoints the signup form uses — judge whether they serve only public registry data (by-design) or account data (bug). - Enumeration oracles: sequential/timestamp IDs where responses differ between existing/absent users (pairs with V10 in bb-authz).
- Documents by URL: invoices, labels, tickets as
/files/{id}.pdf, presigned S3 URLs without expiry, cacheable (Cache-Control: public) personal responses — check headers on every personal response. - Third-party exfil: personal data in URL params to analytics (CSP/connect-src lists the collectors), PII in page title/referrer crossing origins.
- Error/debug leaks: stack traces with SQL, emails in verbose errors, debug endpoints (
/actuator,/debug) revealing user stores.
Method
- Inventory personal endpoints from JS (js-recon): profile, addresses, orders, messages, tickets, documents.
- For each: response with session (baseline) → response WITHOUT session → response with OTHER own session. The three-way diff is the whole skill.
- Field-level audit of baseline: list every field; mark which the UI displays; the invisible ones (internal flags, IDs, hashes) are candidates for "unnecessary data exposure".
- Check response headers:
Cache-Control,Vary: Cookie, CDN cache status on authenticated responses (a cached/accounton a shared CDN = cross-user leak). - Documents: request your own invoice/label URL; then vary the ID by ±1/other-format — combine with bb-authz V1/V10.
Verdict rules
- Only claim PII exposure for data of accounts you own or can prove exists (e.g., field returns another account's email). Never enumerate real customers for proof — one own-account PoC suffices ("endpoint returns the full object for any sequential ID" + your ID as PoC).
- Internal-only identifiers without personal data → group as Low per most programs.
- GDPR framing helps European programs: name the lawful-basis violation in impact.
Evidence format
Three-way diff table (with/without/other-session responses, redacted), the exact request, and the field inventory marking displayed vs leaked fields.