Plan-only Capacitor/Ionic native-layer security audit: WebView, token storage, deep links/OAuth, cleartext traffic, exported activities. Use when "is my Capacitor app secure?", "harden my hybrid app", or pre-store hardening. Store readiness → plan-mobile-readiness.
Scanned 9/11/2026
Install to Claude Code
npx -y skills add kensaurus/cursor-kenji --skill plan-capacitor-hardening --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Plan Capacitor Hardening?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/kensaurus-plan-capacitor-hardening)More formats (shields.io, HTML) on the badges page.
---
name: plan-capacitor-hardening
description: >
Plan-only Capacitor/Ionic native-layer security audit: WebView, token
storage, deep links/OAuth, cleartext traffic, exported activities. Use
when "is my Capacitor app secure?", "harden my hybrid app", or
pre-store hardening. Store readiness → plan-mobile-readiness.
license: MIT
---
# Capacitor Native-Layer Hardening Audit + Remediation Plan
**Degree of freedom: HIGH** — native-layer inventory and plan. Stay
**plan-only**. No config, manifest, or code edits until approved.
## This skill vs neighbors
| Skill | Owns |
|---|---|
| **plan-capacitor-hardening** (this) | Native-layer / WebView security plan |
| `plan-mobile-readiness` | Store submission mechanics |
| `enhance-capacitor-ui` | Hybrid shell UI |
## How to reason (every plan item)
1. **Propose** — config, storage, deep-link, or WebView change
2. **Risk** — what a extracted APK or hijacked scheme actually exposes
3. **Keep-working** — native controls that already hold in production
4. **Phase** — prod-config leaks → tokens → auth → WebView → OTA (do not execute)
## Worked example
> **Propose:** `server.cleartext` and `webContentsDebuggingEnabled` false in prod; move auth tokens off Preferences onto Keychain/Keystore.
> **Risk:** release APK allows remote WebView inspect + plaintext token backup exfil.
> **Keep-working:** iOS ATS already blocks cleartext.
> **Phase:** Phase 1 — strip dev config from prod.
**Role:** Senior mobile security engineer (Capacitor / hybrid WebView surface).
**Task:** Inventory `capacitor.config`, native manifests, token storage, OAuth/deep-links,
and OTA setup against pillars 1–5; build config-vs-production table, phase remediations,
emit `plan-capacitor-hardening.md`. **Audit & plan only — no config, manifest, or code
edits until approved.**
**Audit the native layer the web view hides. Change nothing until approved.**
Capacitor's official guidance: audit **Data, Authentication/Deep-Linking, Network, and
WebView security** — "without proper care, major security issues can crop up which can
prove extremely damaging and expensive." Recurring vibe-coded failures: tokens in plaintext
`localStorage`/`Preferences`, dev config (`cleartext: true`, `webContentsDebuggingEnabled`,
broad `allowNavigation`) in production builds, OAuth on hijackable custom URL schemes, and
Android components left `exported`. **Every finding here is invisible to web-only review.**
---
## When this fires
Trigger phrases: *"is my Capacitor app secure"*, *"harden my hybrid app"*,
*"WebView security"*, *"secure storage for tokens"*, *"deep link / OAuth security"*,
*"cleartext traffic"*, *"allowNavigation"*, *"exported activity"*, *"is my OTA update
safe"*, *"pre-store Capacitor hardening"*.
Do **not** fire for: UI polish (`enhance-capacitor-ui`), RN perf (`mobile-rn-performance`),
or store paperwork (`plan-mobile-readiness` — pairs with this). This owns the *native-layer
security surface*.
---
## Why a dedicated skill
`plan-rls-audit`, `plan-secrets-audit`, and `plan-input-validation` cover backend/web.
None know `capacitor.config`, `AndroidManifest.xml`, `Info.plist`, the WebView bridge, or
Keychain/Keystore. Hybrid-native gaps are invisible if you only review web code.
---
## The audit — four pillars (+ OTA) [HIGH freedom]
### 1 · Data security
- **Secrets in the bundle** — API keys, tokens hardcoded in JS or build-time env injection.
Bundle is extractable; move secret-key ops server-side. → `plan-secrets-audit`
- **Plaintext token storage** — auth tokens in `localStorage`, `@capacitor/preferences`,
IndexedDB, plain SQLite. Wrong. Use memory-only or **iOS Keychain / Android Keystore**
(`@capacitor-community/secure-storage`, `capacitor-secure-storage-plugin`, Identity Vault).
- **`allowBackup`** (Android) — `android:allowBackup="true"` exfiltrates app data via backups.
### 2 · Authentication & deep linking
- **Custom URL scheme OAuth** — `myapp://` not globally owned; malicious app can intercept.
- **No PKCE** — OAuth2 in native apps **must** use PKCE.
- **Custom scheme vs App/Universal Links** — prefer Universal Links (iOS) / App Links
(Android) with `assetlinks.json` / AASA. Note silent verification fallback to browser.
- **Exported Android components** — `exported=true` + `BROWSABLE` + no validation = common
deep-link compromise. Audit every `<intent-filter>`.
- **Deep-link input not validated** — URI params → `WebView.loadUrl`, file access, queries.
`startsWith` host checks inadequate.
### 3 · Network security
- **Non-HTTPS** — any `http://` in plaintext.
- **`cleartext: true`** in `capacitor.config` — dev/live-reload only; never production.
- **Missing `network_security_config`** (Android) — `usesCleartextTraffic="false"`; pinning
for high-assurance (note bypass risks).
### 4 · WebView security
- **No / weak CSP** — `Content-Security-Policy` meta tag scoping loads.
- **Broad `allowNavigation`** — untrusted hosts load with native bridge attached; scope to
trusted API origin(s). Note `getPlatform()` quirk on navigated URLs.
- **`webContentsDebuggingEnabled: true`** in production — remote inspection; gate to dev.
- **`addJavascriptInterface` / bridge exposure** — untrusted content + JS interface =
Critical RCE vector.
- **`setAllowFileAccess*` / `file://`**, `eval` on user input, insecure `postMessage`.
### 5 · OTA / live-update governance
- **Update channel integrity** — OTA bundles signed/encrypted; unauthenticated path = RCE.
- **Store-policy** — Google permits WebView updates; **Apple: OTA must not alter core
functionality** (App Store violation independent of security).
- **Rollback / kill switch** — can a bad update be reverted?
Severity aligned with Cap-go CAP001–010 / AND001–008 where applicable.
For each finding: location, gap, exposure, severity, remediation *direction*.
---
## Procedure [HIGH freedom]
1. **Inventory.** Read `capacitor.config.*`, `AndroidManifest.xml`, `Info.plist`, network
configs, OAuth/deep-link setup, token storage. State what you couldn't see.
2. **Run pillars 1–5.** Tag **Critical** (bridge/`addJavascriptInterface` to untrusted
content, hardcoded signing key, plaintext secrets shipped), **High** (cleartext, broad
`allowNavigation`, exported component, custom-scheme OAuth w/o PKCE, plaintext tokens),
**Med** (debug flags, allowBackup, weak CSP), **Low** (logging nits).
3. **Config-vs-production table** — dev-only settings live in prod build.
4. **Phase** burndown. Production-config leaks and token storage first.
5. **Emit `plan-capacitor-hardening.md`. End the turn.**
---
## Guardrails [LOW freedom — run exactly]
- **Plan only.** No config, manifest, or storage migration edits.
- **"Works in the browser" hides all of this.** Say so explicitly.
- **Dev config is a production vulnerability.** `cleartext`, `webContentsDebuggingEnabled`,
broad `allowNavigation` must not ship.
- **In-memory or hardware-backed only** for tokens/keys — not `Preferences`/`localStorage`.
- **Universal/App Links + PKCE** for sensitive OAuth; custom scheme = High even if "works".
- **Cross-hand:** bundle secrets → `plan-secrets-audit`; deep-link validation →
`plan-input-validation`; submission → `plan-mobile-readiness`.
- **Minimal quoting** of config/manifest.
## Self-critique before the burndown [LOW freedom — do not skip]
1. **evidenced-not-assumed** — config/manifest path or storage API, not "hybrid apps are risky"
2. **plan-only** — no config, manifest, or storage migration this pass
3. **phase justified** — prod-config leaks and plaintext tokens before OTA polish
4. **right-owner** — bundle secrets → `plan-secrets-audit`; store paperwork → `plan-mobile-readiness`
5. **no-false-safety** — "works in the browser" hides this surface; custom-scheme OAuth is High even if it works
---
## Report template — `plan-capacitor-hardening.md`
```markdown
# Capacitor Native-Layer Hardening Audit — <app>
_Audit-only. Native security. Nothing changes until each phase is approved._
_These findings are invisible to web-only review._
## Scope
- Inspected: capacitor.config ☐ AndroidManifest ☐ Info.plist ☐ token storage ☐ OAuth ☐ OTA ☐
- Platforms: iOS ☐ Android ☐ | Assumptions: …
## Dev-config-in-production
| Setting | Prod value | Risk | Direction |
|---------|------------|------|-----------|
| server.cleartext | true | plaintext HTTP | false |
| webContentsDebuggingEnabled | true | remote inspection | dev-only |
| server.allowNavigation | ["*"] | bridge on untrusted origin | scope to API |
## Verdict
| Pillar | Crit | High | Med | Worst item |
|--------|------|------|-----|-----------|
| Data | n | n | n | tokens in localStorage |
| Auth/Deep-link | n | n | n | custom-scheme OAuth, no PKCE |
| Network | n | n | n | cleartext enabled |
| WebView | n | n | n | bridge exposed |
| OTA | n | n | n | unsigned channel |
## Findings
| # | Pillar | Location | Gap | Sev | Direction |
|---|--------|----------|-----|-----|-----------|
## Phased burndown
- **Phase 1 — Strip dev config from prod** → `mobile-capacitor-platform`
- **Phase 2 — Secure token storage** → `mobile-capacitor-platform` / `plan-secrets-audit`
- **Phase 3 — Auth & deep-link** → PKCE, App/Universal Links, exported review
- **Phase 4 — WebView & network** → CSP, network_security_config, bridge exposure
- **Phase 5 — OTA governance** → sign channel, store-policy, rollback
## Execution handoff
Re-audit native files after each phase; verify secure storage + deep-links on real devices.
```
---
## Chains with
- **Launch gates** — run with `plan-mobile-readiness` before store submit.
- **`plan-secrets-audit`** — bundle secrets cross-hand.
- **`plan-input-validation`** — deep-link / WebView input validation cross-hand.
- **Execution:** `mobile-capacitor-platform`, `backend-patterns`, `mobile-emulator-test`.
- **Verify:** real-device secure storage + deep-link test; no dev config in release build.
> Plan with a strong model; execute with `composer-2.5-execution.mdc`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!