For the complete documentation index, see llms.txt. This page is also available as Markdown.

Play Integrity Fix: why AppiCrypt is the better attestation anchor

There is a widely used Magisk module called Play Integrity Fix. Its stated purpose is to make modified Android devices pass Google's Play Integrity checks again.

Set aside for a moment whether it works on any given device, on any given day, against any given verdict tier. The interesting fact is structural, and it does not change with the release notes: a module installed on the device is a meaningful variable in what an attestation about that device reports. If your backend authorises a transfer because a verdict came back green, that is worth thinking carefully about.

This is not an argument that Play Integrity is broken. It is an argument against single points of failure and Play Integrity is very often deployed as one.

What Play Integrity

Google Play Integrity API allows your backend ask Google whether a request came from a genuine, unmodified instance of your app running on a genuine Android device.

The results distinguishes between levels of confidence:

  • whether the app is recognised

  • whether basic device integrity holds

  • whether stronger hardware-backed guarantees are met

Used properly, this is a good control. It gives you a signal computed largely outside your app's process, backed in the strong cases by hardware attestation, and it raises the cost of abuse considerably. Nothing below suggests turning it off.

So what's wrong?

The attestation is computed from inputs, such as:

  • device state

  • build fingerprint and properties

  • attestation keys and the trust chain behind them

These are gathered from device which (in our scenario) attacker controls. Hence attacker can also controll/change these inputs.

Publicly discussed weaknesses in this area include:

  • Device fingerprint and property spoofing Modified device presents the profile of a known-good stock one.

  • Compromised or leaked attestation keys These have historically been an ecosystem-wide problem rather than a per-device one.

  • Downgrade paths to software-backed attestation When hardware attestation is unavailable or masked, producing a weaker guarantee that a permissive backend may still accept.

  • Root hiding This removes the artefacts that would otherwise contribute to a negative assessment.

book-blank

If you want to know more about root hiding, read these articles:

The deeper issue: one control, one failure mode

Even setting aside every specific technique, there is a design problem with anchoring on a single attestation:

  • It is one verdict. One boolean-ish answer, one code path to defeat, one thing to get wrong.

  • It is not yours. Availability, semantics, tiering and policy are set by a third party and can change under you. Teams that discovered this during a Play Services outage know the feeling.

  • It answers one question. "Is this a genuine device running a genuine app?" is valuable, and it is not the same as "is this runtime currently instrumented?" A device can be entirely stock and still be running a debugger, or be a genuine device whose user has attached tooling.

  • Android only. Whatever you build around it needs a parallel story on iOS anyway

What AppiCrypt does differently

AppiCrypt is Talsec's app and device integrity attestation, and the reason it is the better anchor for consequential decisions is mainly about where the trust boundary sits.

AppiCrypt produces a cryptographic proof of app and device integrity that your own backend verifies as part of your own API calls. That gives you several properties Play Integrity alone does not:

  • You control the dependency. No third-party verdict service in the critical path of your authorisation decision, and no exposure to another vendor's availability or policy change. This is precisely the scenario the Cloudflare outage resilience piece walks through.

  • One model across platforms. The same integrity concept on Android and iOS, rather than Play Integrity on one side and App Attest on the other with different semantics to reconcile. The EUDI attestation comparison sets this out in detail.

  • It binds to your API calls which makes it a practical anti-abuse control against scripted and replayed traffic, not only a device-quality report. The API anti-abuse article is the deeper treatment.

  • It composes with runtime signals rather than competing with them.

That last point is the one to be honest about. Attestation and runtime detection answer different questions, and you want both.

freeRASP

freeRASP gives you the runtime half for free:

  • privilegedAccess

  • hooks

  • appIntegrity

  • debugger

  • emulator state etc.

RASP+

RASP+ extends it with maintained coverage of the Magisk / Zygisk / Shamiko / KernelSU environment family, configurable responsepolicy, and fleet telemetry through the Portal. Attestation tells you whether to trust the request; runtime detection tells you what is happening inside the app while it runs. Deploying one and calling it done is the mistake this whole article is about.

Edge cases and caveats

Keep using Play Integrity. Removing it makes you weaker. The recommendation is to stop treating it as an authorisation and start treating it as a weighted input.

Check your tiers and your nonce. A large share of real-world weakness is not exotic. It is backends that accept any verdict, or skip nonce validation, and would fail an internal review on their own terms before any module is involved.

No client-originated attestation is unconditionally unforgeable. AppiCrypt raises the cost and moves verification to infrastructure you control; it is not a claim of impossibility, and this article should not be read as one. Verify the specific guarantees against the product documentation for your threat model.

Attestation is not behaviour. A legitimately attested device operated by a fraudster is still a fraudster. Device integrity is one dimension of risk, next to behavioural and transactional signals.

This landscape moves. Google iterates on Play Integrity and hardware attestation policy; the module ecosystem iterates back. Any specific claim here has a shelf life - which is the argument for layering rather than for picking a different single control.

Security todo list

1

Audit your verdict handling

Do you distinguish integrity tiers? Do you validate the nonce? Do you fail closed or open when the verdict service is unavailable? Fix these before anything else.

2

Write down what a green verdict actually authorises

If the answer is "a transfer", you have a single point of failure.

3

Add the runtime layer

Integrate freeRASP and feed privilegedAccess and hooks into the same risk decision as the attestation verdict.

4

Evaluate AppiCrypt

for the decisions that must not depend on a third-party verdict service — high-value transactions, API anti-abuse, and anything with a regulatory audit trail behind it.

5

Test the outage case

Decide now what your app does when the attestation service is unreachable, because you will find out eventually either way.

Last updated

Was this helpful?