capacitor-security
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.
How do I install this agent skill?
npx skills add https://github.com/cap-go/capgo-skills --skill capacitor-securityIs this agent skill safe to install?
- Gen Agent Trust Hubpass
This skill provides a comprehensive security guide and scanning tool for Capacitor mobile applications. It uses the vendor's own tool, capsec, to audit apps for vulnerabilities and provides examples of secure coding practices. No malicious patterns or security risks were identified.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
- Runlayerwarn
2/2 files flagged
- ZeroLeakspass
1 finding · Score: 82/100
What does this agent skill do?
Capacitor Security with Capsec
Zero-config security scanning for Capacitor and Ionic apps.
When to Use This Skill
- User wants to secure their app
- User asks about security vulnerabilities
- User needs to run security audit
- User has hardcoded secrets
- User needs CI/CD security scanning
- User asks about OWASP mobile security
Quick Start with Capsec
Run Security Scan
# 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
Output Formats
# 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
Filtering
# 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"
Security Rules Reference
Secrets Detection (SEC)
| Rule | Severity | Description |
|---|---|---|
| SEC001 | Critical | Hardcoded API Keys & Secrets |
| SEC002 | High | Exposed .env File |
What Capsec Detects:
- AWS Access Keys
- Google API Keys
- Firebase Keys
- Stripe Keys
- GitHub Tokens
- JWT Secrets
- Database Credentials
- 30+ secret patterns
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' });
Storage Security (STO)
| 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',
});
Network Security (NET)
| 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'],
},
};
Capacitor-Specific (CAP)
| 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',
},
};
Android Security (AND)
| 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>
iOS Security (IOS)
| 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>
Authentication (AUTH)
| 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',
});
WebView Security (WEB)
| 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';
">
Cryptography (CRY)
| 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']
);
Logging (LOG)
| 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);
}
CI/CD Integration
GitHub Actions
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
GitLab CI
security-scan:
image: node:20
script:
- npx capsec scan --ci
artifacts:
reports:
security: security-report.json
only:
- merge_requests
- main
Configuration
capsec.config.json
{
"exclude": [
"**/node_modules/**",
"**/dist/**",
"**/*.test.ts",
"**/*.spec.ts"
],
"severity": "low",
"categories": [],
"rules": {
"LOG002": {
"enabled": false
},
"SEC001": {
"severity": "critical"
}
}
}
Initialize Config
npx capsec init
Root/Jailbreak Detection
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();
}
}
Security Checklist
Before Release
- Run
npx capsec scan --severity high - Remove all console.log statements
- Disable WebView debugging
- Remove development URLs
- Verify no hardcoded secrets
- Enable certificate pinning
- Implement root/jailbreak detection
- Add Content Security Policy
- Use secure storage for credentials
- Enable ProGuard (Android)
- Verify ATS settings (iOS)
Ongoing
- Run security scans in CI/CD
- Monitor for new vulnerabilities
- Update dependencies regularly
- Review third-party plugins
- Audit authentication flows
Resources
- Capsec Documentation: https://capacitor-sec.dev
- OWASP Mobile Top 10: https://owasp.org/www-project-mobile-top-10
- OWASP MASTG: https://mas.owasp.org/MASTG
- Capgo Security Plugins: https://capgo.app
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/cap-go/capgo-skills/capacitor-security">View capacitor-security on skillZs</a>