What is app-hardening?
app-hardening is an AI-agent skill, not a library you import. Instead of pulling in a dependency, you tell your coding agent what to harden and it runs the loop — assess → build → verify → report — against a canonical playbook. It works by control id (C1–C16), wires every check into one threat bus and one response policy (never scattered exit() calls), and writes an app-hardening-report.md with before/after coverage.
It targets five platforms with native primitives only — hardware key stores, toolchain obfuscators, platform exploit mitigations, and platform attestation APIs. One install wires Claude Code, Codex CLI, Cursor, Gemini CLI, and OpenCode.
16 OS-native controls
From obfuscation and TLS pinning to hardware-backed keys, attestation, and anti-tamper — each control has a concrete native implementation on all five platforms.
One threat bus + policy
Every signal flows into a single threat bus and a single response policy, so the app reacts coherently instead of through ad-hoc kill switches.
Runnable verify harness
verify.sh and verify.ps1 turn the playbook into PASS/WARN/FAIL checks with a non-zero exit on FAIL, so CI catches hardening regressions.
MASVS & MASTG mapping
Every control maps to OWASP MASVS v2.0 and a MASTG test area, so an assess scan rolls up by MASVS category for an audit.
Tiered by data risk
Three tiers (low / standard / high) let you build only the controls your data warrants — every control is code someone maintains at 3am.
No third-party SDK
Built from first-party OS/SDK primitives only. No commercial protection product is required, referenced, or assumed.
- Open source
- 5 platforms
- 16 controls
- OWASP MASVS
- No vendor SDK
- Free
Defense in depth, one layer at a time
Hardening is not a single switch — it is a stack of layers that each raise the cost of an attack. app-hardening builds them from the outside in: ship-time hardening (obfuscation, config), then storage and key protection, then runtime self-defense (integrity, attestation, anti-tamper), all reporting into one policy that decides how the app responds when something looks wrong.
No single layer is meant to be unbreakable. The point of defense in depth is that bypassing one control still leaves the next, and every layer you add buys the backend more time to make the real decision.
The 16 controls (C1–C16)
All 16 controls have a concrete OS-native implementation on every platform. The table shows the primary primitive each one uses — the skill picks the right one for your target.
| # | Control | Android | iOS | macOS | Windows | Linux |
|---|---|---|---|---|---|---|
| C1 | Obfuscation / shrink | R8 full mode | strip + whole-module -O | strip + -O | IL obfuscator + strip | strip + -O2 / LTO |
| C2 | Native logic | Rust cdylib (JNI) | Rust staticlib | Rust staticlib | Rust cdylib + P/Invoke | Rust cdylib + helper split |
| C3 | HW-backed keys | Keystore / StrongBox | Secure Enclave | Secure Enclave / Keychain | TPM via CNG | TPM 2.0 / kernel keyring |
| C4 | Encrypted storage | Keystore AES-GCM | Keychain + Data Protection | Keychain + CryptoKit | DPAPI / TPM-wrapped | TPM-wrapped + Secret Service |
| C5 | Self integrity | signing-cert pin | code-sign / bundle check | SecStaticCode check | Authenticode + WinVerifyTrust | IMA/EVM + self-hash |
| C6 | Attestation | Play Integrity (server) | App Attest (server) | SE key + device attest | TPM health attest (server) | TPM remote attest (server) |
| C7 | Root / JB detect | native su / prop scan | native JB signal fuse | DYLD / SIP signals | elevation / protection signals | euid / LD_* / LSM signals |
| C8 | VM detect | qemu / build props | simulator / env checks | hypervisor / IOReg | CPUID / registry / timing | CPUID / DMI (low weight) |
| C9 | Anti-debug | ptrace / TracerPid | proc_pidinfo TRACED | proc_pidinfo TRACED | IsDebuggerPresent / PEB | prctl + TracerPid |
| C10 | Anti-hook | /proc/self/maps scan | dyld image scan | hardened runtime + scan | mitigation policy + scan | LD_PRELOAD / maps + RELRO |
| C11 | TLS pinning | network config + SPKI | ATS + SecTrust SPKI | URLSession SPKI | HttpClientHandler SPKI | TLS verify-cb SPKI |
| C12 | Config hardening | manifest flags | entitlements / ATS | hardened runtime + notarize | Authenticode + mitigation | hardening flags + systemd |
| C13 | Capture protection | FLAG_SECURE | isCaptured + secure field | window sharingType none | SetWindowDisplayAffinity | Wayland-mediated (limited) |
| C14 | Threat bus + policy | SharedFlow | Combine / notification | Combine / notification | event / IObservable | in-proc dispatcher |
| C15 | Biometric-gated ops | auth-bound Keystore key | SE key + LAContext | SE key + Touch ID | Windows Hello key | PAM / polkit / TPM-PIN |
| C16 | Anti-leak | FLAG_SECURE + log scrub | resign-active cover + scrub | resign-active cover + scrub | capture-exclude + log scrub | no-core + mlock + scrub |
Each control maps to OWASP MASVS v2.0 and a MASTG test area, so coverage rolls up by category for an audit.
Pick the smallest tier that fits your data
Every control is code someone has to maintain. Don't build T3 for a brochure app. Match the tier to the sensitivity of the data the app handles.
| Tier | For | Adds |
|---|---|---|
| T1 — low | Content / marketing | C1, C11, C12, C16 |
| T2 — standard | Accounts / personal data | T1 + C3, C4, C5, C7, C13, C14, C15 |
| T3 — high | Payments / health / identity | T2 + C2, C6, C8, C9, C10, full policy + server attestation |
How the loop works
The whole skill is one repeatable loop. The agent reads the playbook, works by control id, and leaves a report behind every run.
- Assess. A read-only scan marks each control present / partial / missing, with grep snippets per platform and a MASVS coverage score. This is the baseline before, and the confirmation after.
- Build. Implement the missing controls by
Cnid, wired into one threat bus and one response policy — never scattered kill switches. - Verify. Run the
verify/harness against the build for PASS/WARN/FAIL static posture and SKIP-with-guidance for device-bound checks. - Re-assess. Confirm coverage actually rose.
- Report. Every run writes
app-hardening-report.md: actions taken, before/after MASVS coverage, verification results, residual risk, and pin/key rotation duties.
Install & use — two pastes
The whole thing is two messages to your agent. First, install: paste this and the agent clones the repo and wires every tool for you.
git clone --depth 1 https://github.com/andrewloable/app-hardening.git \
~/.claude/skills/app-hardening && \
~/.claude/skills/app-hardening/setup.sh
Windows: replace the last command with pwsh $HOME\.claude\skills\app-hardening\setup.ps1.
Then use it
Paste the task to your agent and let it run the loop:
Use the app-hardening skill. Assess this app's hardening
posture, implement the missing controls for tier 2, wire
them into one threat bus + policy, then run verify/ against
the build and show me the before/after coverage and report.
Claude Code users can also just type /app-hardening. Other prompts that work:
- Gap scan (no code changes): "Run app-hardening assess on this repo — which of C1–C16 are present / partial / missing? Read-only."
- One specific control: "Add C11 TLS pinning (primary + backup pin + expiry) per the app-hardening guide for my platform."
- Wire into CI: "Add app-hardening's verify/ to CI so a hardening regression fails the build."
Verify harness
verify/verify.sh (macOS / Linux) and verify/verify.ps1 (Windows) implement the playbook's verification matrix as runnable checks: PASS/WARN/FAIL for static posture, SKIP plus how-to for device-bound checks, and a non-zero exit on FAIL so CI catches regressions.
verify/verify.sh --project . --artifact build/app-release.aab
pwsh verify/verify.ps1 -Project . -Artifact dist/MyApp.msi
It understands Android (.apk, .aab), iOS (.ipa, .app, .xcarchive), macOS (.app, .pkg, .dmg), Windows (.exe, .dll, .msi, .msix), and raw ELF / PE / Mach-O. Checks that need a missing tool SKIP with guidance instead of false-failing CI. Local-only app with no network? Add --tier 1 so a missing TLS pin WARNs instead of FAILs.
Compliance, red-team & first principles
Compliance
Every control maps to OWASP MASVS v2.0 and the MASTG test area, so assess scores roll up by MASVS category for an audit.
Red-team loop
Static verify proves a control exists, not that it holds. Pair this defensive skill with an offensive app-audit agent that attacks the build (root / debug / MITM / hook bypass) and measures what survives — on a build you own or are authorized to test only.
First principles
- Defense in depth + server-side attestation. Client checks buy time; the backend is the arbiter for anything sensitive.
- Use the OS, don't reinvent it. Hardware key stores, toolchain obfuscators, platform exploit mitigations — never DIY white-box crypto, packers, or obfuscators.
- Fail quiet, degrade gracefully, rotate your pins — and only build the tier the data warrants.
Frequently asked questions
What is app-hardening?
A free, open-source AI-agent skill that adds layered RASP to apps on Android, iOS, macOS, Windows, and Linux. It is not a library — you tell your coding agent what to harden and it runs an assess → build → verify → report loop, implementing 16 OS-native controls wired into one threat bus and policy.
Does it require a third-party or commercial protection product?
No. Every control is built from first-party OS and SDK primitives only. No commercial RASP product is required, referenced, or assumed — though the playbook does describe, vendor-neutrally, when a maintained library might be the better call.
Which AI coding agents does it support?
One install wires Claude Code, Codex CLI, Cursor, Gemini CLI, and OpenCode. Claude Code users can also invoke it with /app-hardening.
Does client hardening replace server-side security?
No. Client hardening raises an attacker's cost and buys time — it never replaces server-side attestation. Real trust decisions are verified on the backend, never on the client's self-report.
How do I know which tier to use?
Pick the smallest tier that fits your data: T1 for content/marketing, T2 for accounts and personal data, T3 for payments, health, and identity. Every control is code someone has to maintain, so only build the tier the data warrants.