Technical guide

Runtime threat signals best practices: implementation guide

Design the runtime signal contract, bind client signals to Play Integrity or App Attest on the server, and keep telemetry lean and reviewable.

  • Define the observation

    Give every signal a meaning, scope and version before any dashboard, rule or alert depends on it.

  • Bind it to attestation

    A signal sent by the app is a claim. Accept it on the server only alongside a verified Play Integrity token or App Attest assertion.

  • Minimise retained data

    Keep the evidence needed for review without turning security telemetry into a record of user content.

Treat runtime threat signals as a versioned evidence contract. Define what each signal means, which platform produces it and what it cannot prove. On the server, accept a signal only when it arrives with platform evidence you verify yourself: a Play Integrity token on Android or an App Attest assertion on iOS, bound to the same payload. Keep raw observations, unique observations and confirmed incidents as separate counts, and retain only what review needs. Otukan provides runtime threat signals from protected mobile apps. This page covers the contract, server-side trust, data handling and analytics.

For the in-app response, lifecycle handling and server enforcement of a single request, see how to handle runtime threat signals.

Define the event contract

Start from the product’s signal specification. For every observation, record what was seen, which control produced it, its platform scope and what it cannot establish. A general risk label is not an explanation.

Contract itemQuestion to settleValidation at the collector
Observation typeWhich behaviour does it describe?Accept only documented types and versions
ProducerWhich app build, platform and control produced it?Match against the release record
Observation timeWhen did the device report it?Keep as reported; never the only clock
Receipt timeWhen did the collector accept it?Set by the server
CorrelationWhich session or request does it concern?Scoped, non-secret reference
Confidence and severityHow reliable, and how serious?Two separate fields, never merged

Map these to the actual schema and mark what is absent. An absent observation is unknown, not clean.

Time and versions

OWASP separates event time from logging time, which matters when a device is often offline. Sort and expire records by receipt time, keep the device time for context, and write down how long a signal stays relevant to a sensitive action.

Decide before rollout what happens to an unknown signal type or contract version: keep it for review, reject it, or record it as unsupported. Keep validation failures visible without copying a malformed payload into logs.

Bind client signals to attestation on the server

A signal sent by the app crosses a trust boundary. OWASP advises treating data from another trust zone as untrusted: it may be missing, altered, forged or replayed. A modified client can send a perfect-looking “clean” report.

Bind the signal to platform evidence the server verifies itself:

  • Android. Compute a SHA-256 digest of the signal payload together with the request it accompanies, and pass it as the requestHash of a Play Integrity standard request. On the server, decode the token through Google’s API, recompute the digest from the payload you received and require a match. Then read appRecognitionVerdict and deviceRecognitionVerdict.
  • iOS. Include the signal payload and a fresh server challenge in the client data for an App Attest assertion. The server verifies the assertion with the stored App Attest key, checks the challenge and requires the counter to increase.

A signal that arrives without valid evidence is still useful for analytics, but it carries less weight in an authorisation decision. Mark it as unattested rather than dropping it or trusting it. The full verification steps are in how to verify mobile app attestation.

Connect collection to decisions

Otukan supports application response policies informed by runtime threat signals. Keep three decisions apart: the user’s current operation, backend authorisation and analyst escalation. A repeated observation must never repeat a destructive action.

  1. Validate the payload shape at the collector. Bound field sizes and escape log output to prevent log injection.
  2. Map accepted observations to a state in your policy, with explicit unknown and unavailable states.
  3. Deduplicate by a scoped observation reference, so one signal delivered twice counts once.
  4. Record the observation, the rule revision, the action and the outcome as separate entries.
  5. Send analysts the context they need, not the full payload by default.

Build a replay suite with a valid record, a duplicate, a delayed record, a missing field, an unsupported version and a collection outage. These fixtures test your pipeline, not the detector. Then run an authorised lab stimulus, with independent proof that the behaviour happened, alongside a legitimate device following the same journey. Do this on each supported Android and iOS configuration and record each separately.

Triage

Agree what warrants observation only, a user warning, a restricted action or escalation. Severity is not certainty: a serious condition can rest on weak evidence. Give one owner the job of interpreting uncertainty and reviewing the impact on legitimate users. Record who can change a rule and how the change reaches releases already installed.

Handle data and analytics

Observations are not incidents

A detected condition is an observation. An incident is a conclusion reached through review. Keep the distinction in reports, alerts and dashboards.

MetricDefinition
Raw observationsEvery accepted record, duplicates included
Unique observationsDeduplicated by observation reference
Attested observationsUnique observations bound to verified platform evidence
Confirmed incidentsCases closed as malicious after review

Report the four separately. Twenty deliveries of one observation are not twenty compromises, and a rising unattested share may itself point to a modified client.

Data inventory and retention

Build an inventory from the real schema and every downstream copy: collector, warehouse, alerting, support exports and backups. For each field, record purpose, recipient, access and deletion rule. OWASP advises excluding access tokens, passwords, sensitive personal data and secrets from logs, or protecting them. Keep user content out of diagnostics unless a separate, approved need exists.

Set retention from purpose and legal obligations. OWASP notes that logs and their copies should be kept for the required period and no longer. Apply the same rule to local queues on the device and to temporary diagnostics.

  • Raw, unique, attested and confirmed counts have written definitions.
  • Collector and analyst access match their responsibilities.
  • Exports and support records follow the primary store’s rules.
  • Retention covers device queues, temporary diagnostics and backups.
  • Deletion is tested, not inferred from a policy document.
  • A collection outage is visible without exposing payloads.

For the product view, see runtime threat signals, threat analytics and integration overview.

Further reading

Common questions

  • Should the server trust a runtime threat signal sent by the app?

    Not on its own. A signal crosses a trust boundary and may be missing, altered, forged or replayed, and a modified client can send a perfect-looking clean report. Give it weight in authorisation only with platform evidence the server verifies itself: a Play Integrity token on Android or an App Attest assertion on iOS.

  • How do I bind a signal to Play Integrity on Android?

    Compute a SHA-256 digest of the signal payload together with the request it accompanies and pass it as the requestHash of a Play Integrity standard request. The server decodes the token through Google's API, recomputes the digest from the received payload, requires a match, then reads appRecognitionVerdict and deviceRecognitionVerdict.

  • What should happen to a signal that arrives without valid evidence?

    Mark it as unattested rather than dropping it or trusting it. It is still useful for analytics but carries less weight in an authorisation decision. Report attested observations as their own count, because a rising unattested share may itself point to a modified client.

  • Why keep raw observations apart from confirmed incidents?

    Because a detected condition is an observation, while an incident is a conclusion reached through review. Report raw, unique, attested and confirmed counts separately. Twenty deliveries of one observation are not twenty compromises, and a repeated observation must never repeat a destructive action.

  • What does a missing observation mean?

    It means unknown, not clean. Map accepted observations to a state in your policy with explicit unknown and unavailable states, and decide before rollout whether an unknown signal type or contract version is kept for review, rejected or recorded as unsupported.

Make runtime signals operational

Tell us your platforms, framework, sensitive flows and signal-handling requirement. We do not ask for binaries, signing keys, credentials or production data.

Or request a technical demo