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:
parent
ead5da4ab3
commit
9171cb1129
2 changed files with 13 additions and 2 deletions
|
|
@ -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/,
|
||||
|
|
|
|||
|
|
@ -389,7 +389,10 @@ describe('monorepo: username accounts without email, plugins in apps/native/node
|
|||
'const RE = /^[^\\s@]+@[^\\s@]+$/', "fetch('/api/auth/forgot-password')", 'auth.createUserWithEmailAndPassword(a, b)', 'Auth.auth().createUser(withEmail: e, password: p)',
|
||||
'keyboardType="email-address"', 'request.requestedScopes = [.fullName, .email]'];
|
||||
const no = ["const ROUTES = { register: '/register', usernameCheck: '/username/check' }", "contactEmail: 'support@example.com'", "email: 'privacy@example.com'",
|
||||
"labels = { email: 'E-mail' }", 'register(username)', "fetch('/api/v1/session')"];
|
||||
"labels = { email: 'E-mail' }", 'register(username)', "fetch('/api/v1/session')",
|
||||
// server / config identities, not user data (a game apps/server/src/config.ts)
|
||||
' rtdn: { audience: string | null; email: string | null; token: string | null };', ' email: process.env.RTDN_EMAIL ?? null,',
|
||||
' pubsub: { email: cfg.serviceAccount },', ' smtp: { host, email: env.SMTP_USER },'];
|
||||
for (const s of yes) expect({ s, hit: SIGNALS.email.test(s) }).toEqual({ s, hit: true });
|
||||
for (const s of no) expect({ s, hit: SIGNALS.email.test(s) }).toEqual({ s, hit: false });
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue