Skip to main content

Mobile app security

How to treat mobile and desktop apps: as untrusted clients. What attestation gives us, what must never ship in a binary, and which rules must live on the server. Read it before you add a sensitive call or a client-side rule.

How it works​

Anything in the app can be read, changed or replayed by the person holding the device. Attestation raises the cost of using a modified app or a script, but it is a speed bump, not a lock. The server decides.

How to build it​

Attestation​

PlatformProviderNotes
AndroidPlay IntegrityWorks only for builds installed from Play. Sideloaded release builds fail it
iOSApp AttestPlan it in; skipping it leaves iOS as the easiest client to imitate
WebA bot challenge such as TurnstileFor public sign-up and lead forms
All, through FirebaseApp CheckDecide enforcement per environment on purpose. Enforcing in dev but not in prod is backwards

What never ships in an app​

  • API secrets, internal keys, signing keys, admin credentials.
  • A fixed one-time code or a reviewer bypass that works in production.
  • Feature rules that decide money, grades, deadlines or permissions.

Server-side rules for apps that run exams or tests​

Desktop and mobile exam apps can lock the screen and run a timer, but a determined student controls the device. Deadlines, time limits, scoring, answer keys and "who submitted for whom" are enforced on the server. If the app runs or uploads student code, the code runs only in an isolated sandbox on the server side with no network access to internal systems.

  • Tokens in the platform's secure storage (Keychain, Keystore), not plain preferences.
  • Deep links are validated like any other input; a link never performs an action without a signed-in check.
  • Certificate pinning is optional and costly to maintain. Decide it per app; most of our apps do not pin and rely on TLS plus attestation.

Rules​

Rule

A store-review sign-in bypass never works in production, and its code is never committed. Use a review backend with a dedicated account. See Getting through review.

Rule

Client-side flags (exam mode, AI on or off, paid features) are display hints. The server checks the same rule on every request.

Mistakes we made​

  • A fixed review code was committed and also shipped in the app binary, and it worked in production. It was switched off in production and rotated elsewhere.
  • App Check enforcement was on in dev and off in prod, the reverse of what protects users.
  • iOS attestation was deferred, leaving one client without it.

Checklist​

  • Attestation on sensitive calls for each platform, enforced in prod.
  • No secrets or bypass codes in the binary.
  • Every rule that matters enforced on the server.
  • Student or user code runs only in an isolated server sandbox.
  • Tokens in secure storage; deep links validated.