Code injection prevention should answer one question: does the product know which code belongs in your app’s process, and does it act when something else appears there? Otukan does both. It records the modules your release is expected to load, compares them with what is actually running on Android and iOS, and checks that protected code in memory has not been patched. When foreign code shows up, the app applies your response before tokens, keys or signing logic are touched, and the finding reaches your backend. Injection prevention adds to the operating system’s code signing, covering the gaps opened by modified devices and modified copies.
For the full set of integrity controls, return to application integrity.
Where injected code does damage
Injected code runs with your app’s identity. It can read what your app reads, send what your app sends and change what your app decides. That makes the process boundary the trust boundary that matters.
Affected flows
The harm lands in a handful of flows. Session tokens are copied out of memory and replayed elsewhere. Requests are altered after the user confirms them but before your app signs them. A biometric or PIN result is replaced with a pass. A server-issued limit is ignored on the device. Each of these starts with code your team never wrote running beside code it did.
The trust boundary
The platform treats everything inside your process as your app: it lets that code use your keychain or keystore entries, your network session and your files. Otukan draws a line inside that boundary between code your release brought and code that arrived later.
| Entry route | Android | iOS | What Otukan checks |
|---|---|---|---|
| System loader tampering | Needs a rooted device | Needs a jailbroken device | Modules loaded against the expected set |
| Library added to a copy | Re-signed APK with an extra native library | Re-signed bundle with an extra dynamic library | Packaged modules against the genuine release |
| Code loaded at runtime | Executable code read from writable storage | Blocked for unsigned code on unmodified devices | Undeclared code sources on Android |
| Memory patching | Protected native code rewritten in place | Protected code rewritten on a modified device | Protected executable regions |
Who does what
Code injection is stopped best when the operating system, the app and the backend each do the part only they can do.
The operating system
Android and iOS enforce code signing and sandboxing. On iOS, unmodified devices refuse to execute unsigned code pages. On Android, the platform verifies the package signature at install and update. These controls weaken once the device is rooted or jailbroken, and they do not object to a copy that someone else signed properly.
The app
Only code inside the process can see the modules loaded beside it. Otukan’s checks run there at launch and during the session, and compare what they find with the module set recorded for your release, including your framework runtime and declared plugins.
The backend
Your server cannot see the device, but it can refuse a request. Otukan attaches injection findings to the requests they affect, so your backend can decline a token refresh or a transfer that came from a process carrying foreign code.
| Layer | Responsible for | Cannot see |
|---|---|---|
| Operating system | Signing, sandbox, install-time checks | Code added to a properly re-signed copy |
| App with Otukan | Loaded modules, protected memory, in-flow response | Anything outside its own process |
| Backend | Final decision on each request | The device itself |
How to evaluate code injection prevention
Supported platforms
Ask for each injection route to be scoped separately for Android and iOS, with the OS versions covered. Runtime code loading, for example, is an Android concern with no direct iOS counterpart on unmodified devices. Confirm how Flutter and React Native engines are recognised as legitimate.
Evidence to ask for
Request a reproducible test for each route: a test module loaded through the system loader on a modified device, a module packaged into a re-signed copy, and a patched protected function. For each, confirm the in-app response and the record your backend receives, including module name and load path.
User-impact checks
Accessibility services, device-maker extensions and your own analytics SDKs also interact with your app at runtime. Run your normal journeys on clean devices with every production SDK in place and confirm no injection finding fires. Then repeat install, update, sign-in and the flow you protect most, before and after enforcement.
Related protection for compiled code is covered on binary protection.