No PII is sent to analytics
Why it matters
Passing email addresses or full names as analytics user identifiers or event properties violates GDPR Art. 5(1)(c) (data minimisation) and OWASP A02 (Cryptographic Failures / data exposure). Most analytics platforms (GA4, Mixpanel) explicitly prohibit PII in their terms of service and will terminate accounts that send it. Beyond compliance, PII in analytics creates a data breach vector: analytics dashboards are typically accessible to more people than your production database, and data export APIs make the PII recoverable by anyone with dashboard access.
Severity rationale
Critical because PII in analytics events is both a GDPR Art. 5(1)(c) violation and a breach of analytics platform ToS — CWE-359 exposure that creates an additional data breach surface outside your production security controls.
Remediation
Replace every analytics.identify(user.email, ...) call with an opaque database ID. Audit all identify(), posthog.identify(), and gtag('set', 'user_properties', ...) calls in lib/analytics.ts and any component that wraps them:
// Wrong — sends PII to analytics platform:
analytics.identify(user.email, { plan: user.plan })
// Correct — opaque ID only:
analytics.identify(user.id, { plan: user.plan })
If your analytics workflow requires looking users up by email, do that mapping inside your own database — never pass the email to the analytics SDK. Scrub any existing event schemas that include email, name, phone, or address as properties.
Detection
-
ID:
no-pii-in-analytics -
Severity:
critical -
What to look for: Analytics events must not include personally identifiable information. Scan analytics event calls for PII patterns:
- Email addresses passed as event properties or user identifiers (look for variables named
email,userEmail,emailAddress, or@in string concatenation near analytics calls) - Full names (
name,fullName,firstName,lastName) used as user IDs or event properties - Phone numbers, addresses, or government IDs in event properties
- IP addresses explicitly logged (most SDKs handle this server-side, but check for manual IP logging)
- Auth tokens, API keys, or session tokens in analytics calls
- Passwords or password hashes (should never appear near analytics code, but check)
Note: Using an opaque database ID (UUID, numeric ID) as the analytics user ID is correct and not PII. The check is specifically for human-readable identifiers.
- Email addresses passed as event properties or user identifiers (look for variables named
-
Pass criteria: Enumerate all
analytics.identify(),posthog.identify(),mixpanel.identify(), andgtag('set', 'user_properties', ...)calls — at least 0 PII violations found across all calls. No analytics event calls include email addresses, full names, phone numbers, or other PII as event properties or user identifiers. Database IDs used as user identifiers are acceptable. Quote the actual identifier variable name used in each identify call. -
Fail criteria: Any analytics event call includes what appears to be an email, full name, phone number, or other PII. OR
analytics.identify()is called with the user's email as the user ID. Do not pass if the variable passed to identify is namedemail,userEmail, or contains@in a hardcoded string. -
Skip (N/A) when: No analytics is present. Skip if no
analytics.identify()or user property calls exist (purely anonymous tracking). -
Detail on fail:
"analytics.identify() called with user.email as the user ID in lib/analytics.ts. Email addresses are PII — using them as analytics identifiers violates GDPR and most analytics platforms' terms of service." -
Remediation: Never use email addresses as analytics user identifiers. Use an opaque database ID:
// Wrong: analytics.identify(user.email, { plan: user.plan }) // Correct: analytics.identify(user.id, { plan: user.plan })If you need to look up users by email in your analytics tool, use the email as a trait (property) only — not as the primary identifier. Even then, consider whether this is necessary. For a broader review of PII handling in your application, the AI Data Privacy audit examines data exposure patterns across your entire codebase.
External references
- cwe · CWE-359 — Exposure of Private Personal Information to an Unauthorized Actor
- owasp:2021 · A02 — Cryptographic Failures (sensitive data exposure)
- gdpr · Art. 5(1)(c) — Data minimisation principle
Taxons
History
- 2026-04-18·v1.0.0·Initial import from marketing-analytics·automated