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 identifiers — loadSdk, 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"],
Google … loadSdk → google.*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
- It is the top severity.
--exit-code trips on CRITICAL, so this fails a CI gate for an app that would pass review.
- 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.
- 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).
Summary
greenlight preflightreports 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.*adsis case-insensitive and unanchored, soadsmatches inside ordinary identifiers —loadSdk,downloads,uploads,threads,payloads.Reproduction
A single line of an Expo/React-Native app using Google Sign-In (no ads):
Google…loadSdk→google.*adsmatches on theadSinloadSdk.Verified in the same repo:
PrivacyInfo.xcprivacydeclaresNSPrivacyTracking = false, andpackage.jsonhas no ad or attribution SDK.Why this one matters more than a normal false positive
--exit-codetrips on CRITICAL, so this fails a CI gate for an app that would pass review.requestTrackingAuthorization()in an app that does not track is itself a review risk under §5.1.2, and it costs real conversion.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 fromcollectPlayReferrer…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
adssubstring:{regexp.MustCompile(`(?i)(google-mobile-ads|googlemobileads|GADMobileAds|GADApplicationIdentifier|\badmob\b)`), "Google Ads/AdMob"},react-native-google-mobile-ads,GoogleMobileAds,GADApplicationIdentifierand a word-boundedadmobcover the real integrations; none of them appear inloadSdkordownloads.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
CFBundleDisplayNamein a widget target, absent export-compliance declaration, and a competing-platform string in an admin screen).