Documentation Index

Fetch the complete documentation index at: https://docs.onespan.com/llms.txt

Use this file to discover all available pages before exploring further.

Binding rules

Prev Next

The Shielding Tool rule files support the following binding-related options:

Option

Description

bind

Select classes or members to include in the binding process.

unbind

Select classes or members to exclude from binding (i.e., leave their values in the app code).

untouchable

Alias of unbind.

bindingStyle

Define a binding configuration to use in conjunction with bind.

bindingCache

Specify the percentage of pull bindings to keep in a Least Recently Used cache.

Note that you would rarely need to include a specific value in the binding process, as App Shielding will most likely bind the value, regardless. If you are using reflection, however, the affected classes and members could cause issues and should be manually marked as untouchable or unbind.

Binding can also affect performance, especially for classes and methods that are frequently called during runtime. If performance becomes an issue, consider excluding heavily used classes/methods from the binding process.

Example selectors

The following example excludes binding in MyClass:

unbind class com.example.MyClass;

The following example excludes binding in any class under the com.example package:

unbind class com.example.*;

The following example excludes binding in any class that implements MyInterface:

unbind class * implements com.example.MyInterface;

The following example excludes binding in any class that extends MyBaseClass:

unbind class * extends com.example.MyBaseClass;

The following example excludes binding to the myField field under MyClass:

match class com.example.MyClass {
    unbind java.lang.String myField;
}

The following example excludes binding in any static constructor (i.e., clinit):

match * {
    unbind method <clinit>;
}

The following example excludes binding in any constructor:

match * {
    unbind <init>;
    unbind <clinit>(...);
}

Binding Styles

The bindingStyle option is used to configure a set of pull and push binding rules to apply with the bind keyword. The syntax looks like the following:

bindingStyle my-rules {
    pull { ... }

    push { ... }
}

bind:my-rules *;

In the above example, the binding style has a custom name of my-rules and is applied to all classes and methods (*). Styles can also be applied to more specific selectors (e.g., bind:my-rules com.example.*;).

Pull Bindings

Pull bindings rewrite the app code to retrieve values from native calls to App Shielding. Binding styles can control the number of pull bindings to use for integers and strings. The default configuration looks like the following:

bindingStyle default-bindings {
    pull {
        max-integers 0
        max-strings all
        max-alu-ops 0
        percent-decoy-path-ints 0%
        percent-decoy-path-strings 0%
    }
}

bind:default-bindings *;

Pull binding styles support the following options:

Option

Description

max-integers

Configures how many in-scope integers are converted into pull bindings per method. Default value: 0.

max-strings

Configures how many in-scope strings are converted into pull bindings per method.

Default value: all.

max-alu-ops

Configures how many in-scope integer binary operations are converted into ALU (Arithmetic Logic Unit) bindings per method. This means instructions are then computed in Shield instead of in the code.

Default value: 0.

percent-decoy-path-ints

Configures the percentage of max-integers bindings for which to create fake/decoy bindings.

Default value 0%.

percent-decoy-path-strings

Configures the percentage of max-strings bindings for which to create fake/decoy bindings.

Default value 0%.

The max-integers, max-strings, and max-alu-ops options can be set to one of the following:

Value

Description

0

Disable bindings.

all

Enable bindings for all in-scope integers, strings, or binary operations.

Any positive integer

Explicitly set the number of bindings (e.g., 100).

Pull bindings make it more difficult to remove App Shielding from the app, but each type of binding adds a performance overhead. Generally, it is good to keep the default string pull bindings and then add integer or ALU bindings if you specifically want coverage for numeric values or binary operations.

Similarly, creating fake/decoy bindings makes it harder for attackers to map entries to real values, but this adds an even greater performance overhead at runtime and when protecting the app. See Best practices for guidance on using these options.

Push Bindings

Push bindings remove values from static class fields. App Shielding then re-inserts the values on first usage of the Java class.

For push bindings, binding styles only support disabling them altogether. For example:

bindingStyle no-push-bindings {
    push {
        max 0
    }
}

bind:no-push-bindings *;

This might speed up application launch time at the cost of security degradation and should only be used if the application launch is extremely slow.

Least Recently Used Cache

To improve performance, you can use the bindingCache option to specify which percentage of pull binding strings to store in a Least Recently Used (LRU) cache. For example:

bindingCache { max-size 4% }

Without an LRU cache in place, every retrieval of a pull binding string requires a call to a native method. This is more secure but comes with a performance cost. With the LRU cache enabled, the most recently used strings are stored on the Java side after their initial retrieval, reducing the number of native calls.

A good cache size depends on the application and how it uses strings, but 4% is a good starting point. If you integrate a debug version of App Shielding (using the --debug command line option), then you can monitor the cache activity in the logs and adjust the max-size based on your findings.

A cache log looks like the following example:

03-10 12:57:53.033 26159 26184 D ShieldSDK: Pull bindings LruCache[maxSize=185,hits=416,misses=110,hitRate=79%]

The logs contain the following information:

Data

Description

maxSize

The size of the cache, which depends on the number of pull bindings and the configured max-size percentage .

hits

The number of strings found in the cache.

misses

The number of times the cache needed to ask the native code for a string.

hitRate

The percentage of calls that were hits. This should be neither too high (i.e., too much is being cached) nor too low (i.e., there is no performance gain).

Best practices

A good starting point is to first establish a baseline binding style for most of the app that enables pull bindings on all strings but limits integer bindings to a small amount. For example:

bindingStyle baseline {
    pull {
        max-integers 5
        max-strings all
    }
}

Next, create a separate binding style that maxes out the ALU (Arithmetic Logic Unit) bindings. This is useful for code that performs many numeric computations. For example:

bindingStyle alu-ops {
    pull {
        max-alu-ops all
    }
}

Lastly, create a binding style that increases all forms of pull bindings, including creating decoy bindings. This style adds the most performance overhead, so only use it for very small but highly sensitive areas. For example:

bindingStyle hardened {
    pull {
        max-integers all
        max-strings all
        max-alu-ops 50
        percent-decoy-path-ints 5%
        percent-decoy-path-strings 5%
    }
}

Afterwards, , apply the styles in the following manner:

# Apply the baseline style as default
bind:baseline com.example.*;

# Apply ALU bindings to specific arithmetic logic
bind:alu-ops class com.example.licensing.*;
bind:alu-ops class com.example.integrity.*;

# Only use increased bindings in small, highly sensitive areas
bind:hardened com.example.attestation.*;

# Cache pull-bound strings to reduce repeated native calls
bindingCache { max-size 4% }