Skip to content

False positive: google.*ads matches loadSdk — CRITICAL ATT finding on apps with no ad SDK #30

Description

@vincentborko

Summary

greenlight preflight reports a CRITICAL"§5.1.2 Tracking SDKs detected without ATT implementation — Found: Google Ads/AdMob" — on an app that contains no advertising SDK at all.

The cause is the pattern on internal/privacy/scanner.go:110:

{regexp.MustCompile(`(?i)(google.*ads|GADMobileAds|admob)`), "Google Ads/AdMob"},

google.*ads is case-insensitive and unanchored, so ads matches inside ordinary identifiersloadSdk, downloads, uploads, threads, payloads.

Reproduction

A single line of an Expo/React-Native app using Google Sign-In (no ads):

// lib/googleSignIn.ts:59
GoogleSignin: Awaited<ReturnType<typeof loadSdk>>["GoogleSignin"],

GoogleloadSdkgoogle.*ads matches on the adS in loadSdk.

Verified in the same repo:

$ grep -rniE "admob|GADMobileAds" --include="*.ts" --include="*.tsx" --include="*.json" .
(no matches)

$ ls ios/Pods | grep -i "google\|ads"
GoogleSignIn
GoogleUtilities

PrivacyInfo.xcprivacy declares NSPrivacyTracking = false, and package.json has no ad or attribution SDK.

Why this one matters more than a normal false positive

  1. It is the top severity. --exit-code trips on CRITICAL, so this fails a CI gate for an app that would pass review.
  2. The suggested fix is actively wrong. It tells the developer to add an ATT prompt. Shipping requestTrackingAuthorization() in an app that does not track is itself a review risk under §5.1.2, and it costs real conversion.
  3. The CRITICAL finding carries no file or line, while the WARN/INFO findings do — so there is nothing to check it against. The other findings in the same run were all accurate and genuinely useful, which makes this one harder to spot, not easier.

Scope

Across nine React-Native apps in one fleet: 2 real AdMob users, 5 clean, 2 false positives — one from loadSdk (Google Sign-In), one from collectPlayReferrer… in an attribution test file. So roughly half of the non-AdMob apps that touch any Google SDK trip it.

Suggested fix

Require the ad-specific token rather than any ads substring:

{regexp.MustCompile(`(?i)(google-mobile-ads|googlemobileads|GADMobileAds|GADApplicationIdentifier|\badmob\b)`), "Google Ads/AdMob"},

react-native-google-mobile-ads, GoogleMobileAds, GADApplicationIdentifier and a word-bounded admob cover the real integrations; none of them appear in loadSdk or downloads.

Two neighbouring patterns look like they have the same shape and may deserve the same treatment: (?i)(unity.*ads|UnityAds) and (?i)(mixpanel).

Also worth considering

Having the CRITICAL cite the matching file and line (as the codescan findings already do) would make a false positive self-evident instead of requiring a manual hunt.


Thanks for open-sourcing this under MIT — the rest of the run was accurate on our app and pointed out three things we did not know about (missing CFBundleDisplayName in a widget target, absent export-compliance declaration, and a competing-platform string in an admin screen).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions