Initial commit
This commit is contained in:
484
.claude/skills/capacitor-security/SKILL.md
Normal file
484
.claude/skills/capacitor-security/SKILL.md
Normal file
@@ -0,0 +1,484 @@
|
||||
---
|
||||
name: capacitor-security
|
||||
description: 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.
|
||||
---
|
||||
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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**:
|
||||
```typescript
|
||||
// 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**:
|
||||
```typescript
|
||||
// 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**:
|
||||
```typescript
|
||||
// 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**:
|
||||
```typescript
|
||||
// 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**:
|
||||
```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
|
||||
<?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**:
|
||||
```xml
|
||||
<!-- 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**:
|
||||
```typescript
|
||||
// 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**:
|
||||
```html
|
||||
<!-- 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**:
|
||||
```typescript
|
||||
// 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**:
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```yaml
|
||||
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
|
||||
|
||||
```yaml
|
||||
security-scan:
|
||||
image: node:20
|
||||
script:
|
||||
- npx capsec scan --ci
|
||||
artifacts:
|
||||
reports:
|
||||
security: security-report.json
|
||||
only:
|
||||
- merge_requests
|
||||
- main
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### capsec.config.json
|
||||
|
||||
```json
|
||||
{
|
||||
"exclude": [
|
||||
"**/node_modules/**",
|
||||
"**/dist/**",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts"
|
||||
],
|
||||
"severity": "low",
|
||||
"categories": [],
|
||||
"rules": {
|
||||
"LOG002": {
|
||||
"enabled": false
|
||||
},
|
||||
"SEC001": {
|
||||
"severity": "critical"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Initialize Config
|
||||
|
||||
```bash
|
||||
npx capsec init
|
||||
```
|
||||
|
||||
## Root/Jailbreak Detection
|
||||
|
||||
```typescript
|
||||
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
|
||||
Reference in New Issue
Block a user