NO NETWORK · NO TELEMETRY · FAILS CLOSED · v0.3.0

iOS

Team ID mismatchApp tamper

Reads the app's signing Team ID via a keychain access group and compares it to your expected value. Opt-in.

tamper_team_id_mismatchCompromising by default

At a glance

Platform
iOS
Category
App tamper
Source
DITamperChecks.m · currentTeamIdCouldNotRun / teamId:matchesExpected:
Default status
Makes status compromised
Seen firing
Not yet seen firing in a validated run. Based on validated scenarios whose observed result includes this signal; see below.
OWASP MASTG
MASTG-TEST-0081

How it works

What the code inspects.

Adds (if needed) a throwaway kSecClassGenericPassword keychain item, then reads back its kSecAttrAccessGroup. The access group is of the form "TEAMID.<bundle-id>", so the prefix before the first dot is the Apple Team ID. The temporary item is deleted afterward.

Uses only public Security.framework APIs — no private symbols, no required-reason-API concerns — and compares the extracted Team ID case-sensitively against the expectedTeamIds you pass in. A mismatch emits the signal; an inability to read it marks the run incomplete (→ unknown), never clean.

Opt-in: it does nothing unless you provide ios.expectedTeamIds. Skipped on the Simulator.

The exploit it addresses

Why this matters.The threat.

To patch and redistribute your app, an attacker must re-sign it with their own Apple developer certificate, which changes the Team ID. Pinning the expected Team ID catches resigned / cloned builds distributed via sideloading, enterprise certs, or fake 'modded' versions.

How it can be bypassed

No single check is sufficient.Known evasions.

An attacker who knows your real Team ID still cannot sign as you without your private key — but on a jailbroken device they can hook the keychain query or the comparison and fake a match.

This is a client-side check: only server-side App Attest proves the app identity to your backend.