skills/capacitor-security/SKILL.md
Comprehensive security guide for Capacitor apps using Capsec scanner. Covers 63+ security rules across secrets, storage, network, authentication, cryptography, and platform-specific vulnerabilities. Use this skill when users need to secure their mobile app or run security audits.
npx skillsauth add cap-go/capgo-skills capacitor-securityInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Zero-config security scanning for Capacitor and Ionic apps.
# Scan current directory (no installation needed)
npx capsec scan
# Scan specific path
npx capsec scan ./my-app
# CI mode (exit code 1 on high/critical issues)
npx capsec scan --ci
# CLI output (default)
npx capsec scan
# JSON report
npx capsec scan --output json --output-file report.json
# HTML report
npx capsec scan --output html --output-file security-report.html
# Only critical and high severity
npx capsec scan --severity high
# Specific categories
npx capsec scan --categories secrets,network,storage
# Exclude test files
npx capsec scan --exclude "**/test/**,**/*.spec.ts"
| Rule | Severity | Description | |------|----------|-------------| | SEC001 | Critical | Hardcoded API Keys & Secrets | | SEC002 | High | Exposed .env File |
What Capsec Detects:
Fix Example:
// BAD - Hardcoded API key
const API_KEY = 'sk_live_abc123xyz';
// GOOD - Use environment variables
import { Env } from '@capgo/capacitor-env';
const API_KEY = await Env.get({ key: 'API_KEY' });
| Rule | Severity | Description | |------|----------|-------------| | STO001 | High | Unencrypted Sensitive Data in Preferences | | STO002 | High | localStorage Usage for Sensitive Data | | STO003 | Medium | SQLite Database Without Encryption | | STO004 | Medium | Filesystem Storage of Sensitive Data | | STO005 | Low | Insecure Data Caching | | STO006 | High | Keychain/Keystore Not Used for Credentials |
Fix Example:
// BAD - Plain preferences for tokens
import { Preferences } from '@capacitor/preferences';
await Preferences.set({ key: 'auth_token', value: token });
// GOOD - Use secure storage
import { NativeBiometric } from '@capgo/capacitor-native-biometric';
await NativeBiometric.setCredentials({
username: email,
password: token,
server: 'api.myapp.com',
});
| Rule | Severity | Description | |------|----------|-------------| | NET001 | Critical | HTTP Cleartext Traffic | | NET002 | High | SSL/TLS Certificate Pinning Missing | | NET003 | High | Capacitor Server Cleartext Enabled | | NET004 | Medium | Insecure WebSocket Connection | | NET005 | Medium | CORS Wildcard Configuration | | NET006 | Medium | Insecure Deep Link Validation | | NET007 | Low | Capacitor HTTP Plugin Misuse | | NET008 | High | Sensitive Data in URL Parameters |
Fix Example:
// BAD - HTTP in production
const config: CapacitorConfig = {
server: {
cleartext: true, // Never in production!
},
};
// GOOD - HTTPS only
const config: CapacitorConfig = {
server: {
cleartext: false,
// Only allow specific domains
allowNavigation: ['https://api.myapp.com'],
},
};
| Rule | Severity | Description | |------|----------|-------------| | CAP001 | High | WebView Debug Mode Enabled | | CAP002 | Medium | Insecure Plugin Configuration | | CAP003 | Low | Verbose Logging in Production | | CAP004 | High | Insecure allowNavigation | | CAP005 | Critical | Native Bridge Exposure | | CAP006 | Critical | Eval Usage with User Input | | CAP007 | Medium | Missing Root/Jailbreak Detection | | CAP008 | Low | Insecure Plugin Import | | CAP009 | Medium | Live Update Security | | CAP010 | High | Insecure postMessage Handler |
Fix Example:
// BAD - Debug mode in production
const config: CapacitorConfig = {
ios: {
webContentsDebuggingEnabled: true, // Remove in production!
},
android: {
webContentsDebuggingEnabled: true, // Remove in production!
},
};
// GOOD - Only in development
const config: CapacitorConfig = {
ios: {
webContentsDebuggingEnabled: process.env.NODE_ENV === 'development',
},
};
| Rule | Severity | Description | |------|----------|-------------| | AND001 | High | Android Cleartext Traffic Allowed | | AND002 | Medium | Android Debug Mode Enabled | | AND003 | Medium | Insecure Android Permissions | | AND004 | Low | Android Backup Allowed | | AND005 | High | Exported Components Without Permission | | AND006 | Medium | WebView JavaScript Enabled Without Safeguards | | AND007 | Critical | Insecure WebView addJavascriptInterface | | AND008 | Critical | Hardcoded Signing Key |
Fix AndroidManifest.xml:
<!-- BAD -->
<application android:usesCleartextTraffic="true">
<!-- GOOD -->
<application
android:usesCleartextTraffic="false"
android:allowBackup="false"
android:networkSecurityConfig="@xml/network_security_config">
network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">api.myapp.com</domain>
<pin-set>
<pin digest="SHA-256">your-pin-hash</pin>
</pin-set>
</domain-config>
</network-security-config>
| Rule | Severity | Description | |------|----------|-------------| | IOS001 | High | App Transport Security Disabled | | IOS002 | Medium | Insecure Keychain Access | | IOS003 | Medium | URL Scheme Without Validation | | IOS004 | Low | iOS Pasteboard Sensitive Data | | IOS005 | Medium | Insecure iOS Entitlements | | IOS006 | Low | Background App Refresh Data Exposure | | IOS007 | Medium | Missing iOS Jailbreak Detection | | IOS008 | Low | Screenshots Not Disabled for Sensitive Screens |
Fix Info.plist:
<!-- BAD - Disables ATS -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<!-- GOOD - Specific exceptions only -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>legacy-api.example.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
</dict>
</dict>
</dict>
| Rule | Severity | Description | |------|----------|-------------| | AUTH001 | Critical | Weak JWT Validation | | AUTH002 | High | Insecure Biometric Implementation | | AUTH003 | High | Weak Random Number Generation | | AUTH004 | Medium | Missing Session Timeout | | AUTH005 | High | OAuth State Parameter Missing | | AUTH006 | Critical | Hardcoded Credentials in Auth |
Fix Example:
// BAD - No JWT validation
const decoded = jwt.decode(token);
// GOOD - Verify JWT signature
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
issuer: 'https://auth.myapp.com',
audience: 'myapp',
});
| Rule | Severity | Description | |------|----------|-------------| | WEB001 | Critical | WebView JavaScript Injection | | WEB002 | Medium | Unsafe iframe Configuration | | WEB003 | Medium | External Script Loading | | WEB004 | Medium | Content Security Policy Missing | | WEB005 | Low | Target _blank Without noopener |
Fix - Add CSP:
<!-- index.html -->
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self' https://api.myapp.com;
font-src 'self';
frame-ancestors 'none';
">
| Rule | Severity | Description | |------|----------|-------------| | CRY001 | Critical | Weak Cryptographic Algorithm | | CRY002 | Critical | Hardcoded Encryption Key | | CRY003 | High | Insecure Random IV Generation | | CRY004 | High | Weak Password Hashing |
Fix Example:
// BAD - Weak algorithm
const encrypted = CryptoJS.DES.encrypt(data, key);
// GOOD - Strong algorithm
const encrypted = CryptoJS.AES.encrypt(data, key, {
mode: CryptoJS.mode.GCM,
padding: CryptoJS.pad.Pkcs7,
});
// BAD - Hardcoded key
const key = 'my-secret-key-123';
// GOOD - Derived key
const key = await crypto.subtle.deriveKey(
{ name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256' },
baseKey,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt', 'decrypt']
);
| Rule | Severity | Description | |------|----------|-------------| | LOG001 | High | Sensitive Data in Console Logs | | LOG002 | Low | Console Logs in Production |
Fix Example:
// BAD - Logging sensitive data
console.log('User password:', password);
console.log('Token:', authToken);
// GOOD - Redact sensitive data
console.log('User authenticated:', userId);
// Use conditional logging
if (process.env.NODE_ENV === 'development') {
console.debug('Debug info:', data);
}
name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Run Capsec Security Scan
run: npx capsec scan --ci --output json --output-file security-report.json
- name: Upload Security Report
uses: actions/upload-artifact@v4
if: always()
with:
name: security-report
path: security-report.json
security-scan:
image: node:20
script:
- npx capsec scan --ci
artifacts:
reports:
security: security-report.json
only:
- merge_requests
- main
{
"exclude": [
"**/node_modules/**",
"**/dist/**",
"**/*.test.ts",
"**/*.spec.ts"
],
"severity": "low",
"categories": [],
"rules": {
"LOG002": {
"enabled": false
},
"SEC001": {
"severity": "critical"
}
}
}
npx capsec init
import { IsRoot } from '@capgo/capacitor-is-root';
async function checkDeviceSecurity() {
const { isRooted } = await IsRoot.isRooted();
if (isRooted) {
// Option 1: Warn user
showWarning('Device security compromised');
// Option 2: Restrict features
disableSensitiveFeatures();
// Option 3: Block app (for high-security apps)
blockApp();
}
}
npx capsec scan --severity highdevelopment
Guide for migrating an existing web app, PWA, or SPA into a store-ready Capacitor iOS and Android app. Use this skill when users want to wrap or convert a web app into a mobile app, avoid thin WebView app store rejection, add native-feeling UX, handle permissions, offline behavior, account deletion, billing, testing, and Capgo live updates.
development
Guide to using Tailwind CSS in Capacitor mobile apps. Covers mobile-first design, touch targets, safe areas, dark mode, and performance optimization. Use this skill when users want to style Capacitor apps with Tailwind.
development
Revenue playbook for getting a mobile or web subscription app from zero to early MRR. Use when users ask how to make revenue, reach $1K MRR, monetize an app, get first users, improve ASO, plan TikTok/Reels/Shorts or Reddit acquisition, design a paywall, choose freemium vs trial, price subscriptions, reduce churn, or build a simple growth loop for an app.
tools
Guides the agent through migrating SQLite and SQL-style Capacitor plugins to @capgo/capacitor-fast-sql. Use when replacing bridge-based SQL plugins, adding encryption, preserving transactions, or moving key-value storage onto Fast SQL. Do not use for non-SQL storage, generic app upgrades, or plugins that already wrap Fast SQL.