scan: the email detector skips server / config identities (a service account or OIDC email of a Pub/Sub push, SMTP / sender / admin addresses, values from the environment); a game's rtdn: { audience; email; token } in apps/server/src/config.ts was flagged as App Privacy Email Address

This commit is contained in:
CRTkafa 2026-10-15 22:49:35 +08:00
parent ead5da4ab3
commit 9171cb1129
2 changed files with 13 additions and 2 deletions

View file

@ -100,6 +100,14 @@ export const PLAY_TARGET_SDK_SINCE = '2026-08-31';
export function codeLine(re: RegExp): RegExp {
return new RegExp(`^(?!\\s*import[\\s{*'"])(?!.*\\b(?:require|import)\\s*\\(\\s*['"\`])(?!.*\\bfrom\\s*['"\`]).*?(?:${re.source})`, `${re.flags.replace('m', '')}m`);
}
/** codeLine, minus server / config identities on the line: a service account or OIDC email of a Pub/Sub push, SMTP /
* sender / admin addresses and values read from the environment are the operator's, never data collected from users
* (a game: `rtdn: { audience: ...; email: ...; token: ... }` in apps/server/src/config.ts was flagged). */
export function userLine(re: RegExp): RegExp {
const skip = '(?!.*(?:audience|[Oo][Ii][Dd][Cc]|[Pp]ub[Ss]ub|pubsub|[Ss]ervice[_ -]?[Aa]ccount|client_email|rtdn|RTDN|[Ss][Mm][Tt][Pp]|reply[_-]?[Tt]o|[Ss]ender|admin[_A-Za-z]*[Ee]mail|[Ee]mail[_A-Za-z]*[Ff]rom|process\\.env|Bun\\.env|import\\.meta\\.env|Deno\\.env|getenv|ENV\\[))';
const c = codeLine(re);
return new RegExp(c.source.replace(/^\^/, `^${skip}`), c.flags);
}
export const SIGNALS = {
appleSignIn: /ASAuthorizationAppleIDProvider|SignInWithAppleButton|AppleAuthenticationButton|AppleAuthentication\.signInAsync|appleAuth\.performRequest|SignInWithApple|OAuthProvider\(\s*['"]apple\.com|AppleAuthProvider|signInWithApple|AppleAuthManager/,
thirdPartyLogin: /GIDSignIn|GoogleSignin\.signIn|GoogleSignIn\(|GoogleAuthProvider|signInWithGoogle|FacebookAuthProvider|LoginManager\(\)\.logIn|LoginManager\.logInWithPermissions|signInWithFacebook|FacebookLogin|TwitterAuthProvider|GithubAuthProvider|OAuthProvider\(\s*['"](microsoft\.com|yahoo\.com|twitter\.com|github\.com)/,
@ -111,7 +119,7 @@ export const SIGNALS = {
// real evidence that the app collects an email address: an email input or keyboard, an `email` property in a request
// body / schema / type (not a quoted constant or label), an email validation, an email endpoint or an email sign-in
// call. Accounts alone never mean email (a username with a device token has none).
email: /type\s*[:=]\s*["'{]*email["'}]|inputMode=["']email["']|keyboardType=["']?email-address|autoComplete=["']email|textContentType=["']?(emailAddress|\.emailAddress)|UITextContentType\.emailAddress|\.keyboardType\(\.emailAddress\)|keyboardType\s*=\s*\.emailAddress|TextInputType\.emailAddress|TYPE_TEXT_VARIATION_EMAIL_ADDRESS|KeyboardType\.Email\b|(?<![\w.$-])["']?email["']?\s*\??:\s*(?![\s"'`]|$)|z\.string\(\)(\.\w+\([^)]*\))*\.email\(|\bisEmail\(|\[\^\\s@\]\+@|\[a-zA-Z0-9._%+-\]\+@|\/(api\/)?(auth\/)?(email|verify-email|forgot-password|reset-password|magic-link)\b['"`]|signInWithEmailAndPassword|createUserWithEmailAndPassword|sendSignInLinkToEmail|createUser\(withEmail:|signIn\(withEmail:|sendSignInLink\(toEmail:|signInWithOtp\(\s*\{\s*email|ASAuthorization\.Scope\.email|requestedScopes[^\n]{0,40}\.email\b/,
email: userLine(/type\s*[:=]\s*["'{]*email["'}]|inputMode=["']email["']|keyboardType=["']?email-address|autoComplete=["']email|textContentType=["']?(emailAddress|\.emailAddress)|UITextContentType\.emailAddress|\.keyboardType\(\.emailAddress\)|keyboardType\s*=\s*\.emailAddress|TextInputType\.emailAddress|TYPE_TEXT_VARIATION_EMAIL_ADDRESS|KeyboardType\.Email\b|(?<![\w.$-])["']?email["']?\s*\??:\s*(?![\s"'`]|$)|z\.string\(\)(\.\w+\([^)]*\))*\.email\(|\bisEmail\(|\[\^\\s@\]\+@|\[a-zA-Z0-9._%+-\]\+@|\/(api\/)?(auth\/)?(email|verify-email|forgot-password|reset-password|magic-link)\b['"`]|signInWithEmailAndPassword|createUserWithEmailAndPassword|sendSignInLinkToEmail|createUser\(withEmail:|signIn\(withEmail:|sendSignInLink\(toEmail:|signInWithOtp\(\s*\{\s*email|ASAuthorization\.Scope\.email|requestedScopes[^\n]{0,40}\.email\b/),
deleteAccount: codeLine(/deleteUser\b|\buser\.delete\(|currentUser\??\.delete\(|\bdeleteAccount\b|delete_account|DeleteAccount|delete-account|["'>]Delete (my |your )?account|\brevokeToken\b|auth\.admin\.deleteUser|Hesab(ı|ımı) sil/i),
restore: /restoreCompletedTransactions|AppStore\.sync\(|restorePurchases|restoreTransactions|RestoreTransactions|getAvailablePurchases|\brestorePurchase\b|\.restore\(\)|Restore Purchases|syncPurchases|Purchases\.shared\.restore|store\.restore\b|queryPurchasesAsync/i,
subscriptionCode: /subscriptionPeriod|Product\.SubscriptionInfo|\.autoRenewable\b|entitlements\.active|SubscriptionStoreView|ProductType\.Subscription|ProductType\.SUBS|BillingClient\.ProductType\.SUBS/,