
Security News
Anthropic Identifies Biased Reasoning and Recklessness as Drivers of Claude’s PyPI Attack
Anthropic found biased reasoning and recklessness drove Claude Mythos 5 to publish malware on PyPI and compromise a security vendor.
@capgo/capacitor-app-attest
Advanced tools
App Attest on iOS, Play Integrity on Android, and optional device fraud signals for Capacitor
Cross-platform device attestation for Capacitor:
DeviceCheck) and optional DeviceCheck tokensThis plugin gives you one JavaScript API for both platforms while using only the native attestation systems:
platform, format, token, keyId).Use it to harden login, account recovery, payments, promo abuse checks, and other high-risk endpoints.
Attestation only adds value when validated on your backend.
Recommended JS API:
prepare()createAttestation()createAssertion()Optional fraud-signal methods:
getCapabilities()getWidevineFingerprint() (Android only, optional)getDeviceCheckToken() (iOS only)Legacy aliases are still available for compatibility:
generateKey() => prepare()attestKey() => createAttestation()generateAssertion() => createAssertion()On both iOS and Android, results include:
platform: ios or androidformat: apple-app-attest or google-play-integrity-standardtoken: normalized token field for backend verificationThe most complete doc is available here: https://capgo.app/docs/plugins/app-attest/
| Plugin version | Capacitor compatibility | Maintained |
|---|---|---|
| v8.. | v8.. | ✅ |
| v7.. | v7.. | On demand |
| v6.. | v6.. | ❌ |
| v5.. | v5.. | ❌ |
Note: The major version of this plugin follows the major version of Capacitor. Use the version that matches your Capacitor installation (for example, plugin v8 for Capacitor 8).
You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command:
npx skills add https://github.com/cap-go/capacitor-skills --skill capacitor-plugins
Then use the following prompt:
Use the `capacitor-plugins` skill from `cap-go/capacitor-skills` to install the `@capgo/capacitor-app-attest` plugin in my project.
If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:
npm install @capgo/capacitor-app-attest
npx cap sync
App Attest capability (under Signing & Capabilities).cloudProjectNumber in Capacitor config:// capacitor.config.ts
plugins: {
AppAttest: {
cloudProjectNumber: '123456789012'
}
}
You can also pass cloudProjectNumber directly in method options.
This plugin uses the Standard Integrity API flow on Android (prepareIntegrityToken + request).
On Android, prepare() prepares the native Standard Integrity provider and returns a handle (keyId) for subsequent calls.
Widevine fingerprinting is optional. It does not require extra Android permissions or extra setup, and it is not used by prepare(), createAttestation(), or createAssertion(). Only call getWidevineFingerprint() if your app needs that signal.
import { AppAttest } from '@capgo/capacitor-app-attest';
const support = await AppAttest.isSupported();
if (!support.isSupported) {
return;
}
const prepared = await AppAttest.prepare();
const keyId = prepared.keyId;
const registration = await AppAttest.createAttestation({
keyId,
challenge: 'server-registration-challenge',
});
const assertion = await AppAttest.createAssertion({
keyId,
payload: 'request-payload-or-nonce-from-backend',
});
// registration.token and assertion.token are verified server-side.
console.log(registration, assertion);
const capabilities = await AppAttest.getCapabilities();
if (capabilities.platform === 'android' && capabilities.widevine.supported) {
const widevine = await AppAttest.getWidevineFingerprint();
await api.storeWidevineFingerprint(widevine.widevineIdSha256);
}
if (capabilities.platform === 'ios' && capabilities.deviceCheck.supported) {
const deviceCheck = await AppAttest.getDeviceCheckToken();
await api.verifyDeviceCheckToken(deviceCheck.token);
}
Your backend must branch by platform/format and run the native verification flow for that platform.
Registration (createAttestation):
prepare() once, then createAttestation({ keyId, challenge }).clientDataHash corresponds to SHA256(challenge).keyId, public key, counter metadata from your verifier).Request protection (createAssertion):
createAssertion({ keyId, payload }).DeviceCheck (getDeviceCheckToken):
getDeviceCheckToken().Registration (createAttestation):
createAttestation({ keyId, challenge }).decodeIntegrityToken).requestDetails.requestHash equals base64url(SHA256(challenge)).appIntegrity.packageName matches your app id.appIntegrity.certificateSha256Digest contains your release signing cert digest.appIntegrity.appRecognitionVerdict meets your policy (commonly PLAY_RECOGNIZED).deviceIntegrity.deviceRecognitionVerdict meets your policy (for example includes MEETS_DEVICE_INTEGRITY).Request protection (createAssertion):
createAssertion({ keyId, payload }).requestHash === base64url(SHA256(payload)).Widevine (getWidevineFingerprint):
widevineIdSha256 by default.widevineIdBase64 only with includeRawId: true when you explicitly need the raw identifier.flowchart TD
A[Backend creates one-time challenge/payload] --> B[App calls AppAttest plugin]
B --> C{platform}
C -->|iOS| D[Apple App Attest]
C -->|Android| E[Play Integrity Standard]
D --> F[token + format + platform + keyId]
E --> F
F --> G[App sends token + context to backend]
G --> H{backend verification by format}
H -->|apple-app-attest| I[App Attest verification]
H -->|google-play-integrity-standard| J[Play Integrity decode + policy checks]
I --> K[allow or deny]
J --> K
sequenceDiagram
participant App as Mobile App (iOS)
participant Plugin as @capgo/capacitor-app-attest
participant Apple as Apple App Attest
participant BE as Backend
BE->>App: registrationChallenge
App->>Plugin: prepare()
Plugin->>Apple: generateKey()
Apple-->>Plugin: keyId
Plugin-->>App: keyId
App->>Plugin: createAttestation(keyId, challenge)
Plugin->>Apple: attestKey(keyId, SHA256(challenge))
Apple-->>Plugin: attestationObject
Plugin-->>App: token + platform + format + keyId + challenge
App->>BE: token + keyId + challenge
BE->>BE: verify cert chain + app identity + clientDataHash
BE-->>App: registration accepted/rejected
BE->>App: requestPayload/nonce
App->>Plugin: createAssertion(keyId, payload)
Plugin->>Apple: generateAssertion(keyId, SHA256(payload))
Apple-->>Plugin: assertion
Plugin-->>App: token + platform + format + keyId + payload
App->>BE: token + keyId + payload
BE->>BE: verify signature + counter + replay policy
BE-->>App: request allowed/denied
sequenceDiagram
participant App as Mobile App (Android)
participant Plugin as @capgo/capacitor-app-attest
participant PlaySDK as Play Integrity SDK
participant BE as Backend
participant Google as Google decodeIntegrityToken API
Note over App,BE: One-time provider preparation
App->>Plugin: prepare({ cloudProjectNumber })
Plugin->>PlaySDK: prepareIntegrityToken(...)
PlaySDK-->>Plugin: tokenProvider handle (keyId)
Plugin-->>App: keyId
BE->>App: registrationChallenge
App->>Plugin: createAttestation(keyId, challenge)
Plugin->>PlaySDK: request(requestHash=base64url(SHA256(challenge)))
PlaySDK-->>Plugin: integrityToken
Plugin-->>App: token + platform + format + keyId + challenge
App->>BE: token + keyId + challenge
BE->>Google: decodeIntegrityToken(token)
Google-->>BE: decoded integrity payload
BE->>BE: verify requestHash + packageName + cert digest + verdict policy
BE-->>App: registration accepted/rejected
BE->>App: requestPayload/nonce
App->>Plugin: createAssertion(keyId, payload)
Plugin->>PlaySDK: request(requestHash=base64url(SHA256(payload)))
PlaySDK-->>Plugin: integrityToken
Plugin-->>App: token + platform + format + keyId + payload
App->>BE: token + keyId + payload
BE->>Google: decodeIntegrityToken(token)
Google-->>BE: decoded integrity payload
BE->>BE: verify requestHash + replay/ttl + verdict policy
BE-->>App: request allowed/denied
Registration payload from app to backend:
{
"platform": "ios | android",
"format": "apple-app-attest | google-play-integrity-standard",
"keyId": "string",
"challenge": "string",
"token": "string"
}
Assertion payload from app to backend:
{
"platform": "ios | android",
"format": "apple-app-attest | google-play-integrity-standard",
"keyId": "string",
"payload": "string",
"token": "string"
}
isSupported()getCapabilities()prepare(...)createAttestation(...)createAssertion(...)getWidevineFingerprint(...)getDeviceCheckToken()storeKeyId(...)getStoredKeyId()clearStoredKeyId()generateKey(...)attestKey(...)generateAssertion(...)Unified cross-platform attestation plugin for Capacitor.
Recommended methods:
prepare()createAttestation()createAssertion()Legacy aliases are still available for compatibility:
generateKey()attestKey()generateAssertion()isSupported() => Promise<IsSupportedResult>
Checks whether native attestation is available on this device.
Returns: Promise<IsSupportedResult>
getCapabilities() => Promise<AppAttestCapabilities>
Returns attestation and optional fraud-signal capabilities available on the current platform.
Widevine is Android-only and optional. Apps that do not call Widevine methods do not need any Widevine-specific setup.
Returns: Promise<AppAttestCapabilities>
prepare(options?: PrepareOptions | undefined) => Promise<PrepareResult>
Prepares attestation state and returns the key handle used for later calls.
iOS: generates a real App Attest key identifier. Android: prepares a Play Integrity Standard token provider handle.
| Param | Type |
|---|---|
options | PrepareOptions |
Returns: Promise<PrepareResult>
createAttestation(options: CreateAttestationOptions) => Promise<CreateAttestationResult>
Creates a registration attestation token bound to a backend-issued challenge.
iOS: returns App Attest attestationObject.
Android: returns Play Integrity Standard token.
| Param | Type |
|---|---|
options | CreateAttestationOptions |
Returns: Promise<CreateAttestationResult>
createAssertion(options: CreateAssertionOptions) => Promise<CreateAssertionResult>
Creates a request assertion token bound to a request payload.
iOS: returns App Attest assertion. Android: returns Play Integrity Standard token.
| Param | Type |
|---|---|
options | CreateAssertionOptions |
Returns: Promise<CreateAssertionResult>
getWidevineFingerprint(options?: WidevineFingerprintOptions | undefined) => Promise<WidevineFingerprintResult>
Returns an optional Android Widevine-derived fingerprint.
This method is Android-only and is not part of the normal attestation flow. Call it only when your app needs a DRM-backed fraud signal and your privacy policy covers that use.
The default fingerprint is SHA-256 over the Widevine device unique ID and a salt.
If hashSalt is not provided, Android uses the app package name as the salt.
The raw Widevine ID is sensitive and is only returned as base64 when includeRawId is true.
| Param | Type |
|---|---|
options | WidevineFingerprintOptions |
Returns: Promise<WidevineFingerprintResult>
getDeviceCheckToken() => Promise<DeviceCheckTokenResult>
Creates an iOS DeviceCheck token for server-side fraud-state lookups.
Returns: Promise<DeviceCheckTokenResult>
storeKeyId(options: StoreKeyIdOptions) => Promise<OperationResult>
Stores/prepares a key identifier for reuse.
iOS: persists in UserDefaults. Android: prepares a native Play Integrity provider for this key id in memory (process lifetime).
| Param | Type |
|---|---|
options | StoreKeyIdOptions |
Returns: Promise<OperationResult>
getStoredKeyId() => Promise<GetStoredKeyIdResult>
Returns the currently stored/prepared key identifier.
Android value is only available while the process is alive.
Returns: Promise<GetStoredKeyIdResult>
clearStoredKeyId() => Promise<OperationResult>
Clears stored/prepared key identifiers.
Returns: Promise<OperationResult>
generateKey(options?: PrepareOptions | undefined) => Promise<GenerateKeyResult>
Legacy alias for prepare().
| Param | Type |
|---|---|
options | PrepareOptions |
Returns: Promise<PrepareResult>
attestKey(options: AttestKeyOptions) => Promise<AttestKeyResult>
Legacy alias for createAttestation().
| Param | Type |
|---|---|
options | CreateAttestationOptions |
Returns: Promise<AttestKeyResult>
generateAssertion(options: GenerateAssertionOptions) => Promise<GenerateAssertionResult>
Legacy alias for createAssertion().
| Param | Type |
|---|---|
options | CreateAssertionOptions |
Returns: Promise<GenerateAssertionResult>
| Prop | Type |
|---|---|
isSupported | boolean |
platform | AttestationPlatform |
format | AttestationFormat |
| Prop | Type | Description |
|---|---|---|
platform | AttestationPlatform | Platform currently executing the plugin. |
appAttest | SupportStatus | Apple App Attest support. |
playIntegrity | SupportStatus | Android Play Integrity support. |
deviceCheck | SupportStatus | iOS DeviceCheck support. |
widevine | WidevineCapabilities | Optional Android Widevine DRM support. |
| Prop | Type | Description |
|---|---|---|
supported | boolean | Whether the capability is available on the current device. |
| Prop | Type | Description |
|---|---|---|
supported | boolean | Whether the Widevine DRM scheme is supported by the device. |
fingerprintAvailable | boolean | Whether a Widevine fingerprint can be attempted. Actual access is confirmed when calling getWidevineFingerprint(). |
securityLevelScanSupported | boolean | Whether the Widevine security level property can be read. |
| Prop | Type |
|---|---|
keyId | string |
platform | AttestationPlatform |
format | AttestationFormat |
| Prop | Type | Description |
|---|---|---|
cloudProjectNumber | string | Android only. Google Cloud project number for Play Integrity. Can be set globally in Capacitor config via plugins.AppAttest.cloudProjectNumber. |
| Prop | Type | Description |
|---|---|---|
token | string | Unified attestation token value. iOS: base64 App Attest attestation. Android: Play Integrity token. |
keyId | string | |
challenge | string | |
platform | AttestationPlatform | |
format | AttestationFormat |
| Prop | Type |
|---|---|
keyId | string |
challenge | string |
cloudProjectNumber | string |
| Prop | Type | Description |
|---|---|---|
token | string | Unified assertion token value. iOS: base64 App Attest assertion. Android: Play Integrity token. |
keyId | string | |
payload | string | |
platform | AttestationPlatform | |
format | AttestationFormat |
| Prop | Type |
|---|---|
keyId | string |
payload | string |
cloudProjectNumber | string |
| Prop | Type | Description |
|---|---|---|
platform | 'android' | Always android. |
source | 'widevine' | Always widevine. |
fingerprint | string | Salted SHA-256 fingerprint for storing alongside a user record. |
widevineIdSha256 | string | Unsalted SHA-256 hash of the Widevine device unique ID. |
widevineIdBase64 | string | Raw Widevine device unique ID encoded as base64. Returned only when includeRawId is true. |
securityLevel | string | Widevine security level when available, for example L1 or L3. |
vendor | string | DRM vendor when available. |
version | string | DRM plugin version when available. |
description | string | DRM plugin description when available. |
| Prop | Type | Description |
|---|---|---|
includeRawId | boolean | Return the raw Widevine device unique ID as base64. Defaults to false. |
hashSalt | string | Optional salt used to derive fingerprint. Android uses the app package name when omitted. |
| Prop | Type | Description |
|---|---|---|
token | string | iOS DeviceCheck token encoded as base64. |
| Prop | Type |
|---|---|
success | boolean |
| Prop | Type |
|---|---|
keyId | string |
cloudProjectNumber | string |
| Prop | Type |
|---|---|
keyId | string | null |
hasStoredKey | boolean |
| Prop | Type | Description |
|---|---|---|
attestation | string | Legacy field equal to token. |
| Prop | Type | Description |
|---|---|---|
assertion | string | Legacy field equal to token. |
'ios' | 'android' | 'web'
'apple-app-attest' | 'google-play-integrity-standard' | 'web-fallback'
iOS App Attest flow is inspired by the original plugin from ludufre/capacitor-app-attest.
Android support in this plugin is implemented with Google Play Integrity to provide equivalent attestation coverage.
FAQs
App Attest on iOS, Play Integrity on Android, and optional device fraud signals for Capacitor
The npm package @capgo/capacitor-app-attest receives a total of 13,088 weekly downloads. As such, @capgo/capacitor-app-attest popularity was classified as popular.
We found that @capgo/capacitor-app-attest demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.

Security News
Anthropic found biased reasoning and recklessness drove Claude Mythos 5 to publish malware on PyPI and compromise a security vendor.

Research
/Security News
Malicious Chrome and Firefox extensions target Axiom Trade and Padre users, stealing session tokens and wallet data.

Security News
GPT-6 Astra hits 100% on ExploitBench and finds zero-days autonomously, while independent tests reveal scope violations and monitoring gaps.