Skip to content

Releases: AfanasievN/react-native-device-risk-signals

v0.8.1 — correctness and privacy-manifest fixes

Choose a tag to compare

@AfanasievN AfanasievN released this 27 Jul 14:55
44d5c06

v0.8.1 - correctness and privacy-manifest fixes

A patch release fixing two defects introduced with the v0.8.0 signal batch. No new signals, no API
additions, and no change to how collection is configured.

Fixed

Unreadable /proc sources no longer report as "clean" (Android)

magiskAbstractSocketFound, magicMountModulesFound, fridaThreadNamesFound,
fridaInjectorPipeFound, fridaListenerPortFound and suOnPath are derived from reads that SELinux
routinely denies to third-party apps on stock devices — /proc/net/unix, /proc/net/tcp(6),
/proc/self/fd, /proc/self/task, and executing which. In v0.8.0 a denied read was collapsed to
false, so a locked-down (or genuinely compromised but unreadable) device was reported as clean.

These fields are now omitted when their source cannot be read, preserving the SDK's
missing-versus-false contract: "could not read" is a different observation from "read it and found
nothing". Backends must treat an absent field as unknown and must not default it to false.

iOS Lockdown Mode removed - Apple Required-Reason API

lockdownModeEnabled (added in v0.8.0) read the undocumented NSUserDefaults key
LDMGlobalEnabled. NSUserDefaults belongs to an Apple Required-Reason API category, while this
module ships a PrivacyInfo.xcprivacy that deliberately declares an empty
NSPrivacyAccessedAPITypes. Keeping the field would have made the privacy manifest untrue or forced
a CA92.1 declaration, breaking the "declares no Required-Reason API" guarantee that integrators
rely on.

The field is removed from the public contract, the probe catalog, and the iOS provider. This is a
source-compatible removal of an optional field: TypeScript consumers reading it get undefined
(it was optional), and no other field changed.

Compatibility and privacy

  • No new signals, dependencies, permissions, JNI/NDK, persistent identifiers, network requests, or
    Apple Required-Reason API declarations. The privacy manifest remains empty by design.
  • Backends should re-check any rule that treated the six Android fields above as booleans - they can
    now be absent on perfectly ordinary devices.

Upgrade

npm install react-native-device-risk-signals@0.8.1

For iOS applications, refresh CocoaPods after updating:

cd ios && bundle exec pod install

Anyone on 0.8.0 should upgrade: the omit-instead-of-false fix changes signal semantics in a way that
affects scoring, and the Lockdown Mode removal clears an App Store review risk.

v0.8.0 — native-library-informed integrity signals

Choose a tag to compare

@AfanasievN AfanasievN released this 24 Jul 08:55
c73ffaa

v0.8.0 - native-library-informed integrity signals

This backward-compatible feature release adds raw Magisk-hide, Frida, emulator, and iOS
reverse-engineering observations to os_integrity (and one to device_security_posture), sourced
from native open-source security libraries and reimplemented in pure Kotlin / Objective-C. The SDK
continues to return raw evidence only: no score, no verdict, no network calls, no persistent id.

Highlights

Magisk-hide-resistant tells (Android)

  • magiskAbstractSocketFound/proc/net/unix contains an abstract socket (name starting with
    @) that is 32+ chars and free of /, ., or spaces, matching Magisk's randomized control socket.
  • magicMountModulesFound — a file mapped from /system, /vendor, /product, or /system_ext
    shares the device number of the /data mount, i.e. a Magisk "magic mount" bind-mount. This is
    observable from the app process even when the module path/name is hidden.

Broader Frida evidence (Android)

  • fridaThreadNamesFound — Frida worker threads (gum-js-loop, pool-frida, frida-gum) seen in
    /proc/self/task/*/comm.
  • fridaInjectorPipeFound — a /proc/self/fd entry whose target contains Frida's linjector pipe.
  • fridaListenerPortFound — a LISTEN socket on 27042/27043 in /proc/net/tcp(6), catching
    frida-server before any client connects.
  • fridaHandshakeReject (on os_integrity_frida_scan) — the D-Bus/Frida AUTH handshake on port
    27042 answers REJECT, confirming genuine frida-server rather than any other service on that port.

Wider emulator coverage (Android)

More Andy/Nox/VirtualBox/x86 artifact files, a BlueStacks shared-folder path, and /proc/tty/drivers
folded into the goldfish CPU-token scan; more Magisk artifact paths.

iOS reverse-engineering and posture

  • parentPidUnexpectedgetppid() != 1 (not launchd), a debugger/debugserver-spawned tell.
  • jailbreakBypassDetected — the "Shadow" anti-anti-jailbreak tweak is loaded (ShadowRuleset).
  • mainExecutableEncrypted — the main Mach-O's LC_ENCRYPTION_INFO cryptid; false on a device
    binary indicates it was decrypted/cracked (repackaging/piracy tell).
  • openReverseEngineeringPorts — open loopback ports among 27042 (Frida), 4444 (Needle), 22
    (OpenSSH), 44 (checkra1n).
  • lockdownModeEnabled (on device_security_posture, iOS 16+) — Lockdown Mode state.

Backend contract guidance

  • Every new field is optional and attacker-influenced; preserve missing versus false.
  • The new Android fields are Android-only; the new iOS fields are iOS-only.
  • mainExecutableEncrypted is false for development/simulator builds by design — interpret it only
    for production distributions.
  • No existing field is removed or renamed.

Verification

  • Root Jest suite passed; TypeScript, TurboModule contract, package, and GitHub Pages verification
    passed.
  • Pure-Kotlin unit tests cover the new Magisk-socket, Frida-listener, magic-mount device cross-check,
    and Frida-thread-name parsers.

The implementation adds no npm runtime, Gradle runtime, CocoaPods, or bundled binary dependencies;
no JNI/NDK, network requests, persistent identifiers, QUERY_ALL_PACKAGES, runtime permission
prompts, or Apple Required-Reason API declarations were added.

Deferred

An isolated-process re-check (the strongest Magisk DenyList/Shamiko bypass) and the pointer-heavy iOS
hook/breakpoint/Mach-O-hash checks are intentionally not in this release; they require dedicated
design and on-device verification.

Upgrade

npm install react-native-device-risk-signals@0.8.0

For iOS applications, refresh CocoaPods after updating:

cd ios && bundle exec pod install

No existing field is removed or renamed; existing integrations retain their previous behavior.

v0.6.0 - install provenance and transaction-time Android observations

Choose a tag to compare

@AfanasievN AfanasievN released this 22 Jul 14:43

This backward-compatible feature release adds inspectable Android install-source context and direct
transaction-time screen/touch observations. The SDK continues to return raw evidence only: it does
not calculate a score, emit a trusted/untrusted verdict, contact Google Play, or upload data.

Highlights

Richer own-package install provenance

The application probe preserves installerPackage for compatibility and adds:

  • installingPackageName on supported Android versions, matching the installer of record;
  • initiatingPackageName and initiatingPackageSigningCertificateSha256 on Android 11+;
  • installPackageSource on Android 13+ as unspecified, store, local_file,
    downloaded_file, or other;
  • updateOwnerPackageName on Android 14+;
  • isSystemApp and isUpdatedSystemApp from the host package's ApplicationInfo flags.

Every read is limited to the host application's own package. Installer values remain
attacker-influenced local observations and must not be treated as Google Play recognition,
licensing, or device-integrity verdicts. Unavailable values are omitted.

originatingPackageName is deliberately not exposed because ordinary applications cannot receive
it without the privileged INSTALL_PACKAGES permission.

Direct transaction-time UI observations

The disabled-by-default transaction_safety probe now supports:

  • Android 15+ isVisibleInScreenRecording; isScreenCaptured aliases this state on Android for
    cross-platform compatibility;
  • Android 14+ screenshot callback availability, whether a screenshot was observed after the
    observation window began, and its latest monotonic timestamp;
  • direct MotionEvent.FLAG_WINDOW_IS_OBSCURED and
    MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED observations;
  • the monotonic observation-window start, observed ACTION_DOWN count, and latest obscured-touch
    timestamps.

Observation starts lazily only when transaction_safety is actually collected. A protected flow
should collect once when its UI opens, then collect again immediately before the protected action:

const transactionConfig = {
  probes: {transaction_safety: {enabled: true, timeoutMs: 900}},
};

await deviceIntel.collect({config: transactionConfig});
// User reviews and confirms the protected action.
const actionContext = await deviceIntel.collect({config: transactionConfig});

Before a real ACTION_DOWN is observed, obscured-touch booleans are omitted rather than reported as
false. Screenshot fields are omitted unless the callback was successfully registered. Android 15
recording state is omitted on older systems or when unavailable.

Host-controlled capture permissions

The package's Android manifest still declares no permissions. Applications that intentionally use
capture observations can opt in through their own manifest:

<uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" />
<uses-permission android:name="android.permission.DETECT_SCREEN_RECORDING" />

These are install-time detection permissions and the SDK never opens a permission prompt. Android
shows its standard user notice when the screenshot callback detects a capture. Declare only the
permission required by the application's documented protected flow.

Backend contract guidance

  • Treat every new field as optional and attacker-influenced.
  • Preserve missing versus false: they describe different observation states.
  • Treat *ElapsedMs values as Android SystemClock.elapsedRealtime timestamps, not Unix epoch time.
  • Use install-source and UI observations as explainable context alongside authenticated server data
    and platform attestation, never as a single-signal block.
  • Continue accepting installerPackage; migrate to installingPackageName only when convenient.

The complete selectable field inventory is available in the hosted
Signal Catalog and its
machine-readable JSON.

Verification

  • Root Jest suite: 105 tests passed.
  • TypeScript, TurboModule contract, package, and GitHub Pages verification passed.
  • Android native unit tests, example debug assembly, and Android lint passed.
  • Example Jest, ESLint, and TypeScript checks passed.
  • npm pack --dry-run passed and includes the new native sources and declarations.

The implementation adds no npm runtime, Gradle runtime, CocoaPods, or bundled binary dependencies;
no network requests, persistent identifiers, QUERY_ALL_PACKAGES, runtime permission prompts, or
Apple Required-Reason API declarations were added.

Upgrade

npm install react-native-device-risk-signals@0.6.0

For iOS applications, refresh CocoaPods after updating:

cd ios && bundle exec pod install

No existing field is removed or renamed. Applications that do not enable transaction_safety
retain the previous runtime behavior.

v0.5.1 — easier evaluation and community feedback

Choose a tag to compare

@AfanasievN AfanasievN released this 21 Jul 18:10

v0.5.1 — easier evaluation and community feedback

This patch release improves how React Native teams discover, evaluate, and contribute to the
package. It does not change the public signal API, event schema, or default probe behavior.

Highlights

A clearer evaluation path

  • The documentation site is now the canonical npm and GitHub homepage.
  • The README leads with the library's product boundary and differentiators instead of maintainer
    services: zero runtime dependencies, no vendor backend, no persistent device identifier, and no
    client-side risk score.
  • Evaluation links now lead directly to installation, the signal catalog, integration Q&A, adoption
    stories, and sanitized physical-device reporting.
  • The documentation landing page adds explicit GitHub and community actions while keeping local
    collection and the Signal Bench screenshot as the primary evidence.

Honest physical-device compatibility

The new compatibility matrix distinguishes three levels:

  • automated build verification;
  • a reproducible community report from physical hardware;
  • a result reproduced by a maintainer on comparable hardware.

Simulator compilation is not presented as physical-device validation. The initial matrix remains
empty until real sanitized reports are contributed.

Better contributor entry points

  • A dedicated device form captures package, React Native, platform, OS, device class, build type,
    and probe outcomes while warning contributors not to publish sensitive event data.
  • A dedicated raw-signal proposal form requires platform API provenance, privacy impact, omission
    semantics, and confirmation that the proposal is not a score, verdict, identifier, or vendor call.
  • Contributor documentation links to scoped starter issues and GitHub Discussions.

Android lint compatibility

The Android network provider now structures permission-gated reads so Android lint can prove that
ACCESS_NETWORK_STATE is checked before protected APIs are called. The package still declares no
permission, and missing host permission still causes affected optional values to be omitted.

Compatibility and privacy

  • Compatible with React Native 0.76+ and the New Architecture.
  • No public TypeScript or native signal contract changes.
  • No npm runtime, Gradle runtime, CocoaPods, or bundled native-binary dependencies added.
  • No Android permissions, permission prompts, network requests, adoption telemetry, persistent
    identifiers, QUERY_ALL_PACKAGES, or Apple Required-Reason API declarations added.

Upgrade

npm install react-native-device-risk-signals@0.5.1

For iOS applications, refresh CocoaPods after updating the package:

cd ios && bundle exec pod install

No configuration or data-contract migration is required.

See the complete changelog,
device compatibility matrix,
and documentation.

v0.5.0 — Richer raw device context, clearer semantics

Choose a tag to compare

@AfanasievN AfanasievN released this 21 Jul 11:53

v0.5.0 — richer raw device context, clearer semantics

This release adds 23 new raw observations implemented with Android and Apple system APIs. The SDK
still performs no network request and returns no score, trust verdict, or blocking decision.

Highlights

Detailed Android battery, power, and NFC context

  • batteryHealth, batteryVoltageMv, batteryTechnology, and batteryPresent expose the values
    available from the system battery broadcast.
  • batteryLow reports Android's own low-battery classification; powerSource distinguishes battery,
    AC, USB, wireless, and dock power where the platform provides it.
  • Android 14+ may report batteryCycleCount, while Android 9+ may report
    chargeTimeRemainingMs. Unsupported values and platform sentinels are omitted.
  • nfcAvailable and nfcEnabled report feature/adapter state without scanning a tag, opening an NFC
    flow, requesting a permission, or displaying a prompt.

Active-network context without network traffic

When the host application already declares ACCESS_NETWORK_STATE, Android may now return:

  • networkTransportTypes
  • dnsServerAddresses
  • isPrivateDnsActive and privateDnsServerName
  • activeNetworkMtu
  • isInternetValidated
  • hasCaptivePortal

These observations come from the active link's system metadata. Collection performs no DNS lookup,
socket connection, IP-reputation request, or vendor call. Missing permission and failed reads omit
the affected values. An offline result is returned only after a successful observation found no
active network.

Build, provisioning, and display topology

  • Android androidBuild.buildTimeMs exposes public Build.TIME; it is a platform-build timestamp,
    not an app installation timestamp.
  • iOS embeddedProvisioningProfilePresent reports only whether the host bundle contains
    embedded.mobileprovision; the profile is not parsed.
  • Android adds displayCount and presentationDisplayCount.
  • iOS adds connectedScreenCount and mirroredScreenCount; the connected count includes the main
    screen.

More honest unavailable-state behavior

  • iOS isScreenMirrored now checks UIScreen.mirroredScreen. A second display used for extended
    content is not automatically classified as mirroring.
  • Android no longer manufactures usbDebuggingEnabled: false from a setting ordinary modern apps
    cannot read reliably. The compatibility field is omitted.
  • getTaskAllowEntitlement is reserved as an optional field but not populated: the current public
    iPhoneOS SDK headers do not expose a supported entitlement lookup API. The package does not
    hand-declare unsupported symbols or replace an unavailable read with false.

Compatibility and privacy

  • Backward-compatible additive API for React Native 0.76+ with the New Architecture enabled.
  • Every new field is optional and preserves the distinction between unavailable and an observed
    negative value.
  • No npm, Gradle, CocoaPods, or bundled native-binary dependencies were added.
  • No new Android permissions, permission prompts, network requests, persistent identifiers,
    QUERY_ALL_PACKAGES, or Apple Required-Reason API declarations were added.
  • Focused TypeScript and Kotlin regressions cover field/catalog parity, platform omissions,
    connectivity policy, battery enum/sentinel handling, dependency boundaries, and privacy manifests.

Upgrade

npm install react-native-device-risk-signals@0.5.0

For iOS applications, refresh CocoaPods after updating the package:

cd ios && bundle exec pod install

No configuration migration is required. Hosts that already grant ACCESS_NETWORK_STATE can receive
the new Android link observations; the SDK itself still declares no permission.

See the complete changelog
and Data Dictionary
for field-level detail.

v0.4.0 — More explainable raw device signals

Choose a tag to compare

@AfanasievN AfanasievN released this 21 Jul 10:51

v0.4.0 — more explainable raw device signals

This release adds compact, independently implemented observations using only Android and Apple
system APIs. The SDK still returns raw evidence only: applications remain responsible for
interpretation, transport, retention, and policy.

Highlights

Better location-source context

  • locationServicesEnabled separates the system-wide service state from app authorization on both
    platforms.
  • iOS 15+ can report isSimulatedBySoftware and isProducedByAccessory when a cached location and
    CLLocationSourceInformation are available.
  • Missing cached locations and older iOS versions omit source fields; they are never reported as
    clean observations.
  • mockLocationAppsFound remains in the optional public type for compatibility but is intentionally
    not populated because complete discovery would require broad app enumeration.

More granular integrity evidence

  • Android adds isDebuggerWaiting, the exact matched dangerousSystemProperties, and
    loadedHookClassNames for loadable Xposed/Substrate/LSPosed classes.
  • Class lookup disables initialization, so the probe does not execute third-party initializers.
  • Raw artifact coverage now includes selected KernelSU, APatch, resetprop, modern rootless
    jailbreak, Dopamine, palera1n, TrollStore, ElleKit, and Frida paths, images, and environment names.
  • Findings remain explainable paths, key=value pairs, class names, or mapped images. The SDK does
    not turn them into a root/jailbreak score or trust verdict.

Resource and execution context

  • Android and iOS add lowPowerModeEnabled and processResidentMemoryBytes.
  • Android adds isLowRamDevice, runtimeMaxMemoryBytes, and
    isInstalledOnExternalStorage for the host app.
  • iOS adds isIosAppOnMac and isMacCatalystApp execution-environment flags.
  • Failed /proc, Mach task, system-property, or platform-service reads omit optional values rather
    than substituting zero or false.

Compatibility and privacy

  • Backward-compatible additive API for React Native 0.76+ with the New Architecture enabled.
  • No npm, Gradle, CocoaPods, or bundled native-binary dependencies were added.
  • No new permissions, permission prompts, network requests, persistent identifiers,
    QUERY_ALL_PACKAGES, installed-app/process inventory, or Apple Required-Reason APIs were added.
  • The Probe Catalog, Data Dictionary, README, public TypeScript contract, and both native
    implementations describe the same optional fields and platform gating.

Upgrade

npm install react-native-device-risk-signals@0.4.0

For iOS applications, refresh CocoaPods after updating the package:

cd ios && bundle exec pod install

No configuration migration is required. Consumers should treat every newly added field as optional
and preserve the distinction between “unavailable” and an observed negative value.

See the complete changelog and
Data Dictionary for field-level detail.

v0.3.0 — Explainable emulator and runtime signals

Choose a tag to compare

@AfanasievN AfanasievN released this 21 Jul 08:52

Highlights

Version 0.3.0 makes device observations more explainable and gives teams better raw inputs for their own risk models—without adding an SDK-side score, verdict, network transport, persistent identifier, or permission prompt.

Better emulator and device-farm evidence

  • Expanded Android markers for Genymotion, BlueStacks, Nox, MEmu, LDPlayer, Andy, Droid4X, and KoPlayer.
  • Added Firebase Test Lab, Android test-harness, iOS simulator-environment, and XCTest markers.
  • Added structured evidence arrays and emulatorChecksPerformed, so applications can understand why a marker was observed instead of relying only on an opaque boolean.

New explainable computation signals

  • Added deriveObservationMetrics(event) for ratios, consistency checks, and probe outcome counts computed from an already-collected event.
  • Added runtime_timing observations across the JavaScript event loop, React Native bridge, and native runtime.
  • Added numeric_consistency observations for deterministic integer and floating-point calculations across JavaScript and native runtimes.
  • Extended gpu_benchmark with median, p95, median absolute deviation, coefficient of variation, and warm-up slope.

runtime_timing, numeric_consistency, and gpu_benchmark remain disabled by default. Enable them only for calibrated cohorts after representative physical-device testing.

Integrity and posture coverage

  • Expanded application provenance with Android SDK/signing and iOS receipt/build observations.
  • Strengthened OS-integrity evidence for tracing, test keys, suspicious mounts, Zygisk, executable mappings, and environment markers.
  • Added device_security_posture, the default-off transaction_safety probe, and deriveConsistencySignals().

Quality and documentation

  • Verified parity across all 19 TurboModule methods in TypeScript, Kotlin, and Objective-C++.
  • Added Android unit coverage for emulator classification and computation helpers.
  • Updated the Probe Catalog, Data Dictionary, benchmark guide, README examples, and GitHub Pages documentation.

Upgrade

npm install react-native-device-risk-signals@0.3.0

This is an additive minor release with no intentional breaking API changes. Review the new optional fields if your backend strictly validates the event schema.

Full changelog: v0.2.0...v0.3.0

v0.2.0

Choose a tag to compare

@AfanasievN AfanasievN released this 16 Jul 11:53

Breaking changes

  • Removed the built-in transport API (collectAndSend, TransportConfig, wire envelope, and sendFields). The host app now owns all network delivery.
  • Raised the supported React Native floor to 0.76 and documented the package as New Architecture-only.

Added

  • Machine-readable Probe Catalog and strict configuration validation.
  • Data Dictionary, privacy characteristics, and reproducible JS orchestration benchmark.
  • React Native compatibility CI for 0.76.9, 0.81.6, and 0.86.0.
  • Native Android/iOS builds, TurboModule contract verification, and CodeQL for TypeScript, Kotlin, Objective-C, and C++.
  • Contributor guidance in AGENTS.md for adding new probes safely.

Fixed

  • Probe timeout timers are cleared after completion.
  • Synchronous probe failures are isolated like rejected promises.
  • The demo reports end-to-end collection duration.
  • Session IDs use native CSPRNG-backed UUIDs.

Migration

Replace collectAndSend() with collect(), then send the returned result through your application's existing API client or transport layer.

See the full changelog.

v0.1.1 — Automated trusted publishing

Choose a tag to compare

@AfanasievN AfanasievN released this 15 Jul 18:03

Changes

  • Added npm version and CI status badges to the README.
  • Enabled automated npm publishing through GitHub Actions Trusted Publishing.

Install

npm install react-native-device-risk-signals@0.1.1

v0.1.0 — Initial public release

Choose a tag to compare

@AfanasievN AfanasievN released this 15 Jul 17:53

Highlights

  • Collect raw device, hardware, integrity, network, locale, application, and runtime observations on Android and iOS.
  • Receive an independent success, skipped, timeout, or error outcome for every probe.
  • Keep collection local by default and configure an optional HTTPS transport when your application is ready to send events.
  • Control probes through configuration, field projection, timeouts, and a subtractive consent gate.
  • Explore the complete response using the included light-theme Signal Bench demo application.

Install

npm install react-native-device-risk-signals

For iOS applications, install CocoaPods dependencies after adding the package:

npx pod-install

Status

This is the first public release. The API and collected fields may evolve before 1.0.0; review every enabled probe, permission, disclosure, and retention rule before production use.

See the README for the complete response example, platform notes, and configuration reference.