Skip to content

Commit 1552139

Browse files
author
Cognis Digital
committed
feat: rootsentry v0.1.0 — root/jailbreak/emulator/hook/tamper detection engine with scored posture verdict + Android/iOS reference collectors
0 parents  commit 1552139

16 files changed

Lines changed: 876 additions & 0 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: ci
2+
on:
3+
push:
4+
branches: [main]
5+
pull_request:
6+
branches: [main]
7+
jobs:
8+
test:
9+
runs-on: ubuntu-latest
10+
strategy:
11+
matrix:
12+
python-version: ["3.10", "3.11", "3.12"]
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: actions/setup-python@v5
16+
with:
17+
python-version: ${{ matrix.python-version }}
18+
- run: pip install -e ".[dev]"
19+
- run: python -m pytest -q

‎.gitignore‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
__pycache__/
2+
*.pyc
3+
*.egg-info/
4+
.pytest_cache/
5+
build/
6+
dist/
7+
.venv/

‎LICENSE‎

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
Cognis Open Collaboration License (COCL)
2+
Version 1.0 — 2026
3+
4+
Copyright (c) 2026 Cognis Digital LLC (Wyoming, USA). All rights reserved.
5+
6+
This software and associated documentation files (the "Software") are made
7+
available by Cognis Digital LLC ("Licensor") under the following terms. By
8+
using, copying, modifying, or distributing the Software, or by contributing to
9+
it, you ("You") agree to these terms.
10+
11+
------------------------------------------------------------------------------
12+
1. DEFINITIONS
13+
------------------------------------------------------------------------------
14+
1.1 "Non-Commercial Use" means use for personal projects, internal evaluation,
15+
research, education, security testing You are authorized to perform, and
16+
other use that is not Commercial Use.
17+
1.2 "Commercial Use" means any use of the Software, in whole or in part, that
18+
is primarily intended for or directed toward commercial advantage or
19+
monetary compensation, including without limitation: (a) use in production
20+
to operate a business; (b) offering the Software (or a modified version) to
21+
third parties as a hosted, managed, or software-as-a-service offering;
22+
(c) redistributing the Software as, or as part of, a commercial product;
23+
or (d) use by a for-profit entity beyond a 30-day internal evaluation.
24+
1.3 "Contribution" means any work of authorship You intentionally submit to
25+
Licensor for inclusion in the Software (e.g., via a pull request, patch,
26+
or issue attachment).
27+
28+
------------------------------------------------------------------------------
29+
2. GRANT FOR NON-COMMERCIAL USE
30+
------------------------------------------------------------------------------
31+
Subject to Your compliance with this License, Licensor grants You a worldwide,
32+
royalty-free, non-exclusive, non-transferable license to use, reproduce,
33+
modify, and create derivative works of the Software, and to distribute such
34+
copies and derivative works, FOR NON-COMMERCIAL USE ONLY, provided that:
35+
(a) You retain this License, the NOTICE file, and all copyright,
36+
attribution, and license notices in all copies and derivative works; and
37+
(b) You clearly mark any modified files as changed.
38+
39+
------------------------------------------------------------------------------
40+
3. COMMERCIAL USE REQUIRES A SEPARATE LICENSE
41+
------------------------------------------------------------------------------
42+
Commercial Use of the Software is NOT granted under this License. To obtain a
43+
commercial license, contact Cognis Digital LLC at licensing@cognis.digital.
44+
Nothing in this License limits rights You may separately negotiate in writing
45+
with Licensor.
46+
47+
------------------------------------------------------------------------------
48+
4. CONTRIBUTIONS ("COLLABORATION PULL")
49+
------------------------------------------------------------------------------
50+
4.1 Inbound license. By submitting a Contribution, You license that
51+
Contribution to Licensor and to all recipients of the Software under the
52+
terms of this License (inbound = outbound).
53+
4.2 Relicensing grant. You additionally grant Licensor a perpetual, worldwide,
54+
royalty-free, irrevocable, sublicensable license to use, reproduce, modify,
55+
distribute, and RELICENSE Your Contribution (including under commercial or
56+
other terms) as part of the Software or Cognis Digital offerings. This
57+
enables the dual-licensing model in Sections 2 and 3.
58+
4.3 Representations. You represent that each Contribution is Your original work
59+
or that You have the right to submit it under these terms, and that it does
60+
not knowingly violate any third party's rights.
61+
4.4 Recognition. Accepted Contributions are credited in the project history and,
62+
where appropriate, in a CONTRIBUTORS or NOTICE file.
63+
64+
------------------------------------------------------------------------------
65+
5. PATENT
66+
------------------------------------------------------------------------------
67+
Licensor grants You a license to its patent claims necessarily infringed by the
68+
Software as provided, limited to the scope of the use granted in Section 2. If
69+
You initiate patent litigation alleging the Software infringes a patent, the
70+
licenses granted to You under this License terminate immediately.
71+
72+
------------------------------------------------------------------------------
73+
6. TRADEMARKS
74+
------------------------------------------------------------------------------
75+
This License does not grant permission to use the trade names, trademarks,
76+
service marks, or product names of Licensor, including "Cognis", "Cognis
77+
Digital", and associated logos, except as required for reasonable and customary
78+
attribution.
79+
80+
------------------------------------------------------------------------------
81+
7. TERMINATION
82+
------------------------------------------------------------------------------
83+
This License terminates automatically if You breach it and do not cure the
84+
breach within 30 days of becoming aware of it. Upon termination You must cease
85+
all use and distribution of the Software, except that copies held by downstream
86+
recipients in compliance with this License survive.
87+
88+
------------------------------------------------------------------------------
89+
8. DISCLAIMER OF WARRANTY AND LIMITATION OF LIABILITY
90+
------------------------------------------------------------------------------
91+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
92+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
93+
FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
94+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
95+
IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN
96+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
97+
98+
------------------------------------------------------------------------------
99+
9. SECURITY-TOOL ACCEPTABLE USE
100+
------------------------------------------------------------------------------
101+
Several Cognis tools are dual-use security software. You agree to use them only
102+
against systems, data, and identities You own or are explicitly authorized in
103+
writing to test, and in compliance with all applicable laws. You are solely
104+
responsible for Your use.
105+
106+
------------------------------------------------------------------------------
107+
This is a source-available license. It is NOT an OSI-approved "open source"
108+
license. For questions: legal@cognis.digital · https://cognis.digital

‎NOTICE‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Cognis Neural Suite
2+
Copyright (c) 2026 Cognis Digital LLC (Wyoming, USA)
3+
4+
This product is part of the Cognis Neural Suite and is distributed under the
5+
Cognis Open Collaboration License (COCL) v1.0. See the LICENSE file.
6+
7+
Website: https://cognis.digital
8+
Suite: https://github.com/cognis-digital
9+
Commercial use: licensing@cognis.digital
10+
11+
This software may incorporate, compose, or interoperate with third-party
12+
open-source projects. Those components remain under their own licenses, and
13+
their copyright and license notices are retained in their respective files or
14+
in the per-tool README "Credits / Built on" section. Cognis Digital claims no
15+
ownership over upstream third-party works it composes or wraps.
16+
17+
Trademarks "Cognis", "Cognis Digital", "Cognis Neural Suite", and associated
18+
logos are marks of Cognis Digital LLC and are not licensed for use except as
19+
required for reasonable attribution.

‎README.md‎

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# rootsentry
2+
3+
**Mobile runtime-integrity detection — root, jailbreak, emulator, hooking, tamper.**
4+
5+
`rootsentry` decides whether a mobile device's runtime can be trusted. An app
6+
collects a small telemetry snapshot on-device — suspicious files, installed
7+
packages, system properties, open ports, runtime flags — and `rootsentry`
8+
scores it against a catalog of well-known compromise indicators, returning a
9+
**posture verdict** (`TRUSTED` → `SUSPICIOUS` → `COMPROMISED` → `CRITICAL`) your
10+
app or backend can act on.
11+
12+
Pure standard library, zero dependencies. Defensive by design: the point is for
13+
*your* app to recognize a rooted/jailbroken/instrumented runtime and react —
14+
degrade gracefully, warn, or refuse high-risk actions.
15+
16+
## How it works
17+
18+
```
19+
catalog.py data-only list of indicators (su binaries, Magisk, Cydia,
20+
frida-server ports, test-keys builds, MobileSubstrate, …)
21+
engine.py match an Evidence snapshot -> fired signals + saturating score 0-100
22+
reference/ embeddable on-device collectors (Kotlin / Swift)
23+
```
24+
25+
Scoring saturates: a single weight-10 indicator (e.g. a signing-cert mismatch)
26+
already reaches `CRITICAL`, while several medium indicators converge toward 100
27+
— so you don't get fooled by one cheap check passing.
28+
29+
## Install
30+
31+
```bash
32+
pip install -e . # or ".[dev]" for tests
33+
```
34+
35+
## Use
36+
37+
```bash
38+
# Evaluate a device snapshot (see examples/evidence.android.json)
39+
rootsentry eval evidence.json
40+
# posture: CRITICAL (score 97/100)
41+
# [ 9] root android.su.system_xbin — su binary present in /system/xbin
42+
# [ 9] root android.magisk.pkg — Magisk manager installed
43+
# [ 8] hook android.frida.port — frida-server default control port open
44+
# ...
45+
46+
# Gate a backend attestation check (exit 1 at/above threshold)
47+
rootsentry eval evidence.json --fail-on COMPROMISED
48+
49+
# Inspect the indicator catalog
50+
rootsentry catalog --platform ios
51+
```
52+
53+
### As a library
54+
55+
```python
56+
from rootsentry import Evidence, Platform, evaluate
57+
58+
ev = Evidence(platform=Platform.ANDROID,
59+
present_files=["/system/xbin/su"],
60+
installed_packages=["com.topjohnwu.magisk"])
61+
verdict = evaluate(ev)
62+
print(verdict.posture.label, verdict.score) # COMPROMISED 75
63+
```
64+
65+
## On-device collection
66+
67+
`reference/android_RootCheck.kt` and `reference/ios_JailbreakCheck.swift` show
68+
how to gather the `Evidence` snapshot on each platform. Recommended pattern:
69+
collect on-device, attest + send to your backend (inside Play Integrity /
70+
DeviceCheck where possible), and evaluate server-side so the decision isn't made
71+
solely in an environment the attacker controls.
72+
73+
## Indicator coverage
74+
75+
Root (su, Magisk, SuperSU, busybox, test-keys, ro.secure), emulator
76+
(goldfish/ranchu/qemu), hooking (frida-server, Xposed, Substrate), iOS jailbreak
77+
(Cydia, Sileo, bash/apt, sandbox-escape, fork), and cross-platform tamper
78+
(signature mismatch, integrity failure, attached debugger).
79+
80+
## Scope of use
81+
82+
Defensive runtime self-protection (RASP-style) for apps you own/operate, plus
83+
device-posture analysis during authorized assessments. Detection only —
84+
`rootsentry` does not modify the device.
85+
86+
## License
87+
88+
Cognis Open Collaboration License (COCL) v1.0. See [LICENSE](LICENSE).

‎examples/evidence.android.json‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"platform": "android",
3+
"present_files": ["/system/xbin/su", "/system/xbin/busybox", "/data/local/tmp/frida-server"],
4+
"installed_packages": ["com.topjohnwu.magisk", "com.acme.app"],
5+
"system_props": {
6+
"ro.build.tags": "test-keys",
7+
"ro.debuggable": "1",
8+
"ro.hardware": "qcom"
9+
},
10+
"open_ports": [27042],
11+
"runtime_flags": []
12+
}

‎pyproject.toml‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[build-system]
2+
requires = ["hatchling"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "rootsentry"
7+
version = "0.1.0"
8+
description = "Mobile runtime-integrity detection: root/jailbreak/emulator/hook/tamper indicators with a scored posture verdict."
9+
readme = "README.md"
10+
requires-python = ">=3.10"
11+
license = { text = "COCL-1.0" }
12+
authors = [{ name = "Cognis Digital", email = "dev@cognis.digital" }]
13+
keywords = ["mobile-security", "root-detection", "jailbreak-detection", "android", "ios", "anti-tampering", "frida-detection", "rasp"]
14+
classifiers = [
15+
"Intended Audience :: Information Technology",
16+
"Topic :: Security",
17+
"Programming Language :: Python :: 3",
18+
]
19+
dependencies = []
20+
21+
[project.optional-dependencies]
22+
dev = ["pytest>=7"]
23+
24+
[project.scripts]
25+
rootsentry = "rootsentry.cli:main"
26+
27+
[tool.hatch.build.targets.wheel]
28+
packages = ["rootsentry"]
29+
30+
[tool.pytest.ini_options]
31+
testpaths = ["tests"]

‎reference/android_RootCheck.kt‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Reference: collecting rootsentry Evidence on Android (Kotlin).
2+
//
3+
// This snippet shows how an app gathers the telemetry rootsentry's engine
4+
// scores. Send the resulting JSON to your backend (ideally inside a Play
5+
// Integrity / attestation flow) and run `rootsentry eval` server-side, or port
6+
// the engine on-device. Defensive use only.
7+
8+
import android.content.Context
9+
import org.json.JSONObject
10+
import java.io.File
11+
import java.net.Socket
12+
13+
object RootEvidence {
14+
private val SU_PATHS = listOf("/system/xbin/su", "/system/bin/su", "/sbin/su")
15+
private val ROOT_FILES = SU_PATHS + listOf(
16+
"/system/xbin/busybox",
17+
"/system/lib/libsubstrate.so",
18+
"/data/local/tmp/frida-server",
19+
)
20+
private val ROOT_PACKAGES = listOf(
21+
"com.topjohnwu.magisk",
22+
"eu.chainfire.supersu",
23+
"de.robv.android.xposed.installer",
24+
)
25+
26+
fun collect(ctx: Context): JSONObject {
27+
val files = ROOT_FILES.filter { File(it).exists() }
28+
val pm = ctx.packageManager
29+
val pkgs = ROOT_PACKAGES.filter {
30+
runCatching { pm.getPackageInfo(it, 0); true }.getOrDefault(false)
31+
}
32+
val props = mapOf(
33+
"ro.build.tags" to getProp("ro.build.tags"),
34+
"ro.debuggable" to getProp("ro.debuggable"),
35+
"ro.secure" to getProp("ro.secure"),
36+
"ro.hardware" to getProp("ro.hardware"),
37+
"ro.kernel.qemu" to getProp("ro.kernel.qemu"),
38+
)
39+
val ports = listOf(27042).filter { portOpen(it) }
40+
41+
return JSONObject().apply {
42+
put("platform", "android")
43+
put("present_files", files)
44+
put("installed_packages", pkgs)
45+
put("system_props", JSONObject(props as Map<*, *>))
46+
put("open_ports", ports)
47+
}
48+
}
49+
50+
private fun getProp(name: String): String = runCatching {
51+
val p = Runtime.getRuntime().exec(arrayOf("getprop", name))
52+
p.inputStream.bufferedReader().readLine().orEmpty().trim()
53+
}.getOrDefault("")
54+
55+
private fun portOpen(port: Int): Boolean = runCatching {
56+
Socket("127.0.0.1", port).use { true }
57+
}.getOrDefault(false)
58+
}

‎reference/ios_JailbreakCheck.swift‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Reference: collecting rootsentry Evidence on iOS (Swift).
2+
//
3+
// Gathers jailbreak/hook telemetry rootsentry's engine scores. Defensive use
4+
// only. Note: App Store apps must be careful which paths they probe; this is a
5+
// reference for in-house / assessment builds.
6+
7+
import Foundation
8+
9+
enum JailbreakEvidence {
10+
static let suspiciousPaths = [
11+
"/Applications/Cydia.app",
12+
"/Applications/Sileo.app",
13+
"/bin/bash",
14+
"/etc/apt",
15+
"/Library/MobileSubstrate/MobileSubstrate.dylib",
16+
]
17+
18+
static func collect() -> [String: Any] {
19+
let files = suspiciousPaths.filter { FileManager.default.fileExists(atPath: $0) }
20+
var flags: [String] = []
21+
if canWriteOutsideSandbox() { flags.append("can_write_outside_sandbox") }
22+
if forkSucceeds() { flags.append("fork_succeeded") }
23+
24+
return [
25+
"platform": "ios",
26+
"present_files": files,
27+
"runtime_flags": flags,
28+
]
29+
}
30+
31+
private static func canWriteOutsideSandbox() -> Bool {
32+
let probe = "/private/rootsentry_probe.txt"
33+
do {
34+
try "x".write(toFile: probe, atomically: true, encoding: .utf8)
35+
try? FileManager.default.removeItem(atPath: probe)
36+
return true
37+
} catch { return false }
38+
}
39+
40+
private static func forkSucceeds() -> Bool {
41+
let pid = fork()
42+
if pid >= 0 {
43+
if pid > 0 { /* parent: child will exit */ }
44+
return true // stock sandboxed iOS denies fork()
45+
}
46+
return false
47+
}
48+
}

0 commit comments

Comments
 (0)