XTD

XTD SDK v1.50.1

XTD SDK v1.50.1

What's New

v1.50.0 → v1.50.1: Added Set VUIT response command message (PROVISION_VUIT_RESPONSE). Improved propagation of event detections. Added proper MITM detection event handling.

For the complete list of changes across all versions, see XTD SDK Version History.

Download SDK

Introduction

ProtectMyApp XTD is an application protection and threat analytics system. It protects mobile applications by preventing tampering and intrusions into application code. In addition, it collects security/threat analytics data and creates a risk assessment of the environment that the application is running in.

The risk assessment can be retrieved from APIs exposed by XTD. XTD also provides operations to interact with the protected application, allowing the service provider to take actions such as suspending the application remotely. To support this, the protection process injects an analytics agent into the application, which runs in parallel to the protected application code.

The XTD SDK is a software developer kit that allows closer integration with XTD services. It provides an asynchronous API, enabling a bi-directional channel for communicating with the XTD infrastructure, both on-device and from the XTD analytics backend.

API Capabilities

The current abilities of the API provide the following:

  • Basic connectivity callbacks — Signal connectivity state between the analytics agent and the XTD backend
  • Provisioning ProtectMyApp User Transaction Identifier (VUIT) — Link application instances to service provider user identities
  • Response actions — Receive and process commands from the XTD analytics backend (e.g., Degrade)

Basic Connectivity Callbacks

The XTD SDK provides functionality to signal that the underlying analytics agent has connectivity with the XTD security analytics backend. This is sent to the application layer to allow it to take action if the analytics agent does not regularly signal connections to the backend.

  • Connection Established
  • Connection Closed
  • Connection Errors

The connectivity events are delivered via the main callback, registered as part of integrating the SDK. See API Overview for details.

User Transaction Identifier (VUIT)

XTD's analytics agent internally uses an application instance identifier (AIID) to identify a specific application instance running on a specific device. This unique identifier ensures that the same application, running on two different devices, appear as different instances in the XTD ecosystem.

The AIID is not exposed to the protected application to ensure device-specific information is not leaked. As a result, the service provider cannot link the application instance to the user that is logged into their service via the application.

To connect an instance of a protected application to a real user, ProtectMyApp allows the service provider to optionally provision an application with a ProtectMyApp User Identity Tag (VUIT). The VUIT is generated and provisioned by the service provider and is not related to the Verimatrix application instance identifier in any way.

The use of VUIT is optional; if not provisioned, some API functionality may be limited.

GDPR

The provisioned identifier provides no identifiable information about the actual user. Identity inference can be made only by the service provider and their internal system.

Integration Points

The following integration points are used when interacting with Verimatrix XTD while using VUIT:

Provisioning

The provisioning integration point establishes the link between the application instance and the user identity. The typical provisioning flow:

  1. User logs into the service
  2. Service provider generates provisioning information (VUIT) and provides it back to the application based on subscriber information
  3. Application shares the provisioning information (VUIT) with the analytics agent
  4. Analytics agent ingests the provisioning information (VUIT) and shares this with Verimatrix XTD analytics
  5. Service provider can use the VUIT to request a risk assessment of the application instance

This flow assumes server-side provisioning. Application-driven provisioning (client-side VUIT generation) is less secure and should be avoided.

Application Driven Provisioning

If the application provides the provisioning information, it must generate the unique identifier and share it with the analytics agent.

The drawback: no assurance the value won't be intercepted or tampered with, and an attacker could inject fake identities.

Requirements for Generating Identifiers

Entity Relationships

The mapping between a VUIT and the application instance should ideally be one-to-one. Verimatrix XTD also supports mapping a single VUIT to many application instances. One-to-one is preferred.

The use case where the VUIT changes per logged-in user is currently not supported.

Ensuring GDPR compliance

The service provider is fully responsible for generating the VUIT. No Personal Identifiable Information (PII) must be included: usernames, email addresses, names. Apply a forward hash to input information to avoid leaking data.

Uniqueness

The VUIT must be unique across all applications of the service provider. Properties that add uniqueness: application package identifiers, device models, globally unique subscriber identifiers. Use these with a low-collision forward hash function.

Format

The format of the VUIT is restricted to:

SP::<Up to 252 characters>

Maximum 256 characters including the SP:: prefix. Character encoding: US/ASCII, characters allowed:

[a-zA-Z0-9-]

Example:

SP::018Cf454-b814-7CA2-8e43-6a13d7a33cfb

Provisioning Protocol Version 1

JSON format:

{"version":1,"spuid":"SP::<Up to 252 characters>"}
PropertyDescription
spuidProvisioned VUIT value. Maximum 256 characters. Should start with SP:: and be encoded in US/ASCII.
versionVersion of protocol, currently always 1

Typical Application Usage

All interactions use JSON payloads. A typical integration flow:

API Overview

FunctionParametersDescription
registerCallbackMessage callback function/instanceRegisters a callback invoked when response action messages arrive from XTD. Same callback signals errors.
sendMessageJSON message to pass to XTDPasses the JSON message to the analytics agent for processing.

Message Callback

The callback receives the response action payload JSON string.

FunctionParameters
MessageCallback#onMessage(@NonNull String messageJSON) (Android)Response action payload (JSON string)
typedef void (*XTDStubLibCallback)(const char *messageJSON); (iOS)Response action payload (JSON string)

Response Action Processing

Response actions can be immediate/single or long-term/persistent.

Immediate actionsProcess and do not store state
Long-term actionsPersist in the session and enforce until a successful connection established/closed pair is received without another action of the same type in that window

Error Handling & Error Codes

The sendMessage API throws exceptions encapsulating XTD error codes. The message callback also delivers error messages asynchronously.

XTD errorCodeDescription
XTD_SUCCESS0Message successfully processed
XTD_GENERAL_ERROR1General error (no memory, library not initialized, etc)
XTD_JSON_PARSING_FAILED2Message JSON can't be parsed
XTD_INVALID_MESSAGE3Message contains invalid/missing objects
XTD_MESSAGE_VERSION_MISMATCH4Message version doesn't match
XTD_UNRECOGNIZED_COMMAND5Message command not recognized
XTD_INVALID_PAYLOAD6Message payload not in expected format
XTD_CRYPTO_ERROR7Payload cryptographic verification failed

Request/Response Action Payloads

Payload Format

{
  "c": 1,
  "v": 1,
  "p": { "some": "command specific payload data" }
}
PropertyDescription
cMessage payload type
vPayload format version (currently always 1)
pAdditional payload, command specific
tTimestamp in milliseconds (optional). Present on payloads sent by the XTD SDK, such as Event Detected (7), Connection Established (1), Connection Closed (2), and other SDK-originated messages. Omitted on payloads sent by the application.

Response Action Types

Payload TypeManagement Action NameAction Sent ByDescription
0Error OccurredXTD SDKAsynchronous error occurred
1Connection EstablishedXTD SDKConnection to XTD Analytics Server established
2Connection ClosedXTD SDKConnection to XTD Analytics Server closed
6Provision VUITCustomer ApplicationProvisions VUIT from app into analytics agent
7Event DetectedXTD SDKSecurity event detected
8Get VersionCustomer ApplicationRequests analytics agent version
9Analytics Agent VersionXTD SDKResponse to Get Version
10Provision VUIT AcknowledgementXTD SDKVUIT provisioned successfully

Event Detected (7) Types

Event Detected (7) messages are sent by the XTD SDK to your application when it detects a security-relevant condition on the device or in the app environment—for example, rooting, debugger attachment, or a man-in-the-middle proxy. The app receives these via its callback and can react (e.g., warn the user, restrict features, or deny access).

Event IDEvent NameOSDescriptionVersion Added
100Bootloader DetectedAndroidDevice bootloader is unlocked, which can indicate a compromised or tampered device.v1.49.0
101Debugger DetectedAndroidA debugger is attached to the application, indicating potential reverse engineering or tampering.v1.49.0
102Emulator DetectedAndroidApplication is running in an emulator rather than on a physical device.v1.49.0
103Overlay DetectedAndroidAn overlay or accessibility service is drawing on top of the application, which may indicate credential theft attempts.v1.49.0
104Rooting/Jailbreak DetectedAndroid, iOSDevice is rooted (Android) or jailbroken (iOS), indicating elevated privileges and reduced security.v1.49.0
105Side Loading DetectedAndroidApplication was installed outside the official app store, increasing tampering risk.v1.49.0
106Tampering DetectedAndroid, iOSApplication binary or runtime integrity has been compromised.v1.49.0
107Hooking DetectedAndroid, iOSRuntime hooking frameworks (e.g., Frida) are detected, indicating code injection or manipulation.v1.49.0
108Hostname Whitelist ViolationAndroid, iOSA network request targeted a hostname not in the configured whitelist.v1.50.0
109Installer MismatchAndroidThe application's installer does not match the expected store or distribution channel.v1.50.0
200Man in the Middle DetectedAndroid, iOSA MITM attack is detected, such as an intercepting proxy or invalid certificate chain.v1.49.0
201VPN DetectedAndroid, iOSA VPN is active. Payload details distinguish whether VPN was turned on or off.v1.49.0
202Proxy DetectedAndroid, iOSA proxy is in use. Payload details distinguish whether proxy was turned on or off.v1.49.0
203DNS Inconsistency DetectedAndroid, iOSDNS resolution results differ from expected consensus, indicating possible DNS manipulation.v1.49.0
204DNS Consensus Mismatch DetectedAndroid, iOSDNS resolution results differ from expected consensus, indicating possible DNS manipulation.v1.49.0

XTD SDK API Commands by Version

See XTD SDK API Commands by Version for a table of which commands are available in each SDK version.

Example Request Payloads

Provision VUIT

{
  "v": 1,
  "c": 6,
  "p": {
    "version": 1,
    "spuid": "SP::<VUIT Data>"
  }
}

Get Version

{
  "v": 1,
  "c": 8
}

Example Response Payloads

Connection Established

{
  "t": 1760081486636,
  "c": 1,
  "v": 1
}

Connection Closed

{
  "t": 1760081486636,
  "c": 2,
  "v": 1
}

Provision VUIT Acknowledgement

{
  "t": 1760081486636,
  "c": 10,
  "v": 1
}

Example Event Detection Response Payloads

Rooting/Jailbreak (104)

{
  "t": 1760081486636,
  "c": 7,
  "v": 1,
  "p": {
    "id": 104,
    "name": "RootingDetected",
    "details": {
      "version": 1,
      "names": ["Checkra1n", "Dopamine"]
    }
  }
}

Hooking (107)

{
  "t": 1760081486636,
  "c": 7,
  "v": 1,
  "p": {
    "id": 107,
    "name": "HookingDetected",
    "details": {
      "version": 1,
      "names": ["Frida"]
    }
  }
}

DNS Consensus Mismatch (204)

{
  "t": 1760081486636,
  "c": 7,
  "v": 1,
  "p": {
    "id": 204,
    "name": "DNSConsensus"
  }
}

JSON Schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://verimatrix.com/xtd/response-actions-payloads/2025-01/schema.json",
  "title": "Verimatrix XTD Response Actions Payloads",
  "description": "Describes response actions payloads used when interacting with Verimatrix secure analytics library (SAIL)",
  "type": "object",
  "required": ["c", "v"],
  "additionalProperties": false,
  "properties": {
    "t": {
      "description": "Timestamp in milliseconds. Present on payloads sent by the XTD SDK (e.g., Event Detected, Connection Established, Connection Closed). Omitted on payloads sent by the application.",
      "type": "integer",
      "minimum": 0
    },
    "c": {
      "description": "Defines the management action this payload carries.",
      "enum": [0, 1, 2, 3, 6, 7, 8, 9, 10]
    },
    "v": {
      "description": "Indicate the version of the payload being carried",
      "enum": [1]
    },
    "p": {
      "description": "Additional payload, command specific",
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "spuid": { "type": "string" },
            "version": { "type": "number" }
          },
          "required": ["spuid", "version"],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "id": { "type": "number" },
            "name": { "type": "string" },
            "details": {
              "type": "object",
              "properties": {
                "version": { "type": "integer" },
                "names": { "type": "array", "items": { "type": "string" } }
              },
              "additionalProperties": false
            },
            "agentVersion": { "type": "string" }
          },
          "additionalProperties": false
        }
      ]
    }
  }
}

Integrating the SDK into your project

To start using the XTD SDK, you have to make some changes to your project.

Android and iOS specific details follow below.

Android

API Overview

The VMXXTD API is a Java interface that allows an app to send and receive messages to/from VMXXTD. The API is accessible via the class com.verimatrix.stublib.StubLib, the main API entry point and the only one mandatory for XTD API usage.

It exposes two methods, one to send messages into the XTD SDK and one to receive messages back into the application.

/**
 * Sends a message to the XTD system.
 * <p/>
 * @param message The message to send in JSON format.
 * @throws StubLibException If the operation fails.
 *
 */
public static void sendMessage(@NonNull final String message) throws StubLibException
/**
 * Registers a callback for receiving messages from the XTD system.
 * <p/>
 * @param callback The callback to register.
 * @throws StubLibException If the operation fails or the callback is unll
 */
public static void registerCallback(@NonNull MessageCallback callback) throws StubLibException

Receive XTD SDK messages

To receive commands and other messages, the app MUST register its own callback function.

After registering, the callback will be invoked whenever XTD SDK needs to pass any command, operation response results, or errors. It is the application's responsibility to handle those messages accordingly.

The callback is invoked on the UI thread to allow UI interactions if needed. As a result, care should be taken to not do too much work in the callback.

// Import the XTD SDK
import com.verimatrix.stublib.StubLib;
import com.verimatrix.stublib.StubLibMessageBuilder;

/**
 * Receive XTD messages example.
 */
public static void registerCallback() {
    try {
        StubLib.registerCallback(message -> {
            // Parse and process messages received from the VMX XTD
            Log.i(TAG, "Received message: " + message);
        });
    } catch (StubLib.StubLibException e) {
        Log.e(TAG, "Error registering callback: " + e.getMessage());
    }
}

Send messages to XTD SDK

To uniquely identify the running instance, the app needs to define and set the VUIT value. The example above contains the basic implementation that sends the provision VUIT command to the XTD SDK.

// Import the XTD SDK
import com.verimatrix.stublib.StubLib;
import com.verimatrix.stublib.StubLibMessageBuilder;
/**
 * Example method of creating the VUIT payload and provisioning this with the security analytics agent using XTD SDK
 *
 * @param vuit The VUIT to provision
 */
public static void provisionVUIT(String vuit) {
    final String vuitPayload = StubLibMessageBuilder.createNewSetVUITCommand(vuit).build();
    try {
        StubLib.sendMessage(vuitPayload);
    } catch (StubLib.StubLibException e) {
        Log.e(TAG, "Error provisioning VUIT: " + e.getMessage());
    }
}

Similarly, other commands can be constructed and sent using the sendMessage API function. The payloads are always JSON format

Android Studio / Project Setup

Package contents

  • docs (integration guide and installation guide)
  • android/aar (vmx-xtd-sdk.aar)
  • android/example (VmxXtdExample.java)

Copy Library

Copy vmx-xtd-sdk.aar from the VMXXTD SDK package into the project's app/libs. If you do not have one, create the libs folder in the app folder of your project.

build.gradle.kts

If your project uses a build.gradle.kts file, follow these steps. Make the changes shown in the following code snippets in the settings.gradle.kts file and the app/build.gradle.kts files respectively.

// settings.gradle.kts
pluginManagement {
    repositories {
        ...
        flatDir {
            dirs("libs")
        }
    }
}
// app/build.gradle.kts
dependencies {
    implementation(files("libs/vmx-xtd-sdk.aar"))
    ...
}

build.gradle

If your project uses a build.gradle file, follow these steps. Include the following in the project's build.gradle:

repositories {
    flatDir {
        dirs 'libs'
    }
}
dependencies {
    implementation(name: 'vmx-xtd-sdk', ext: 'aar')
}

iOS

Package contents: docs (integration guide and installation guide), ios/inc (XTD library include file), ios/lib-iphoneos (static library for device), ios/lib-iphonesimulator (static library for simulator), ios/example (example Swift functions)

Copy Library and Header Files

Copy the ios/inc, ios/lib-iphoneos, and ios/lib-iphonesimulator folders to your project folder ($SRCROOT) — the folder where your Xcode project is stored. Adjust paths if you put the files elsewhere.

If your project uses xcconfig files, skip to Project Configuration with xcconfig file. Otherwise, the next section shows how to update your build settings.

Xcode Build Settings

For Xcode to find the header file, update the header search paths. Go to Header Search Paths in Build Settings and add $(SRCROOT)/inc.

To link the library, add the library path and the library in the Link Binary With Libraries Build Phase. In Build Settings, find Library Search Paths and add $SRCROOT/lib$(EFFECTIVE_PLATFORM_NAME).

Note that EFFECTIVE_PLATFORM_NAME is either -iphoneos or -iphonesimulator, including the dash.

Then add the library from the Link Binary With Libraries Build Phase.

Click the + button and navigate to one of the static libraries. You need to add only one; the Library Search Paths change above will select the appropriate one for device or simulator.

Project Configuration with xcconfig file

  • Add paths to USER_HEADER_SEARCH_PATHS and LIBRARY_SEARCH_PATHS in your project's .xcconfig file.
  • Link the XTD static library (libvmx-xtd-sdk.a) to your project. Update OTHER_LDFLAGS in your .xcconfig file to link with this library.

Example .xcconfig section:

USER_HEADER_SEARCH_PATHS = $(inherited) $SRCROOT/inc
LIBRARY_SEARCH_PATHS = $(inherited) $SRCROOT/lib$(EFFECTIVE_PLATFORM_NAME)
OTHER_LDFLAGS = $(inherited) -ObjC -lvmx-xtd-sdk

Use the XTD SDK from Swift

To call the API functions from Swift, import the vmx-xtd-sdk.h header in your project bridging header:

#import "vmx-xtd-sdk.h"

If you do not have a bridging header yet, you can induce Xcode to create one by adding a temporary C source file to your project; you can remove and discard it after Xcode has generated the bridging header. Refer to the file ios/example/StublibIntegrationExample.swift for example functions on how to use the XTD API.

// Registering Message Callback
let cbFunc: XTDStubLibCallback = { (messageJSON: Optional<UnsafePointer<CChar>>) -> () in
    let messageFromXTD = String(cString: UnsafePointer<CChar>(messageJSON!))
    DispatchQueue.main.async {
        // Process the message. Note: callback can be called at any time and almost always from a background thread.
    }
}

func registerCallback() {
    XTDStubLib.registerCallback(cbFunc)
}

// Provisioning VUIT
func provisionVUIT(_ vuit: String) {
    let vuitPayload = "{\"v\": 1, \"c\": 6, \"p\": {\"spuid\": \"\(vuit)\"}}"
    do {
        try XTDStubLib.sendMessage(vuitPayload)
    } catch {
        print("XTD stub lib error: \(error)")
    }
}

Use the XTD SDK from Objective-C

Import the header where needed: #import "vmx-xtd-sdk.h"

API Overview

The XTD API provides a few simple Objective-C methods in vmx-xtd-sdk.h for compatibility with both Swift and Objective-C projects:

MethodDescription
(void) registerCallback:(XTDStubLibCallback) callbackRegisters a callback for receiving messages from the XTD system. The callback can be called at any time and from background threads.
(BOOL) sendMessage:(NSString *) messageJSON error:(out NSError **) outErrorSends a command to the XTD ARC server.
(BOOL) setSPUID:(NSString *) spuidJSON error:(out NSError **) outErrorSets the VUIT value for the running instance. Deprecated: use sendMessage() to set the VUIT (previously called SPUID).

Note: Swift translates the "BOOL return code with NSError** error" pattern to exceptions; use a do/try/catch block when calling the XTD library methods from Swift. The returned error will be in the generic variable error after catching. Verimatrix provides the JSON schema of messages in this integration guide, including the available commands with parameters.

On this page