capacitor-security について
Capacitor アプリのセキュリティ監査と強化を支援するスキルです。モバイルセキュリティの調査や侵入テストの指摘対応に向け、スキャナーの確認と、バンドル、ストレージ、通信、WebView、ネイティブ設定の点検を扱います。
主な機能
- 01Capgo スキャナーの実行と結果の分類
- 02バンドル内の秘密情報と保存領域の確認
- 03通信と証明書に関する指針
- 04WebView とネイティブブリッジの点検
- 05Android と iOS のマニフェスト強化
活用シーン
- 01モバイルセキュリティ指摘に基づくアプリ監査
- 02ビルド成果物に含まれる認証情報の確認
- 03トークン保存と通信の保護
- 04ブリッジアクセスとプラットフォーム設定の監査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ cap-go/ capgo-skills --skill capacitor-securityインストール後、Claude Code で/capacitor-securityを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
metadata.jsonreferences/capsec-scanner.mdnetwork.mdplatform-hardening.mdsecrets-and-storage.mdwebview-and-bridge.md詳細
Capacitor のセキュリティ
Capacitor アプリのアプリ層を監査し、強化します。対象は、バンドル内のシークレット、デバイス上のストレージ、ネットワーク通信、WebView とネイティブブリッジの公開範囲、プラットフォームのマニフェストです。
使用する場面
次の場合に使用します:
- ユーザーがセキュリティ監査、OWASP Mobile Top 10 / MASVS のレビューを依頼した場合、またはペネトレーションテストの指摘事項を修正したい場合。
- ユーザーが
@capgo/capgo-sec(capsec)の結果や、SEC001、STO002、NET003、CAP004、AND004、IOS001などのルール ID の実行または解釈を希望する場合。 - API キー、サービスロールキー、または
.envの値がsrc/、dist/、www/、capacitor.config.*に含まれている場合。 - 認証トークンが
Preferences.set、localStorage、IndexedDB、またはプレーンな SQLite に保存されている場合。 capacitor.config.*にserver.cleartext: true、server.url、範囲の広いserver.allowNavigation、android.allowMixedContent、またはwebContentsDebuggingEnabled: trueが含まれている場合。- ネイティブファイルに
NSAllowsArbitraryLoads、android:usesCleartextTraffic="true"、android:allowBackup="true"、android:debuggable、または権限のないエクスポート済みコンポーネントが含まれている場合。 - ユーザーが証明書ピンニング、Content Security Policy、スクリーンショット保護、またはルート化/脱獄検出を必要としている場合。
次の場合は使用しないでください:
- Xcode のビルド設定、Enhanced Security、ポインター認証、スタック/ヒープの強化 →
capacitor-ios-security-hardening。 - Universal Links / App Links の設定 →
capacitor-deep-linking(このスキルの対象は受信 URL の検証のみです)。 - プライバシーマニフェスト、App Review の却下 →
capacitor-apple-review-preflight、ストア掲載情報 →capacitor-app-store。 - CI におけるパイプライン構成や署名シークレット →
capacitor-ci-cd。 - ライブアップデートのインストールやチャネル →
capgo-live-updates(このスキルの対象はバンドルの暗号化のみです)。 - 実行時のクラッシュや WebView の検査 →
debugging-capacitor。
ワークフロー
- 編集前に調査します。
capacitor.config.ts|json、package.json(Capacitor のメジャーバージョン、インストール済みプラグイン)、android/app/src/main/AndroidManifest.xml、android/app/src/main/res/xml/network_security_config.xml(存在する場合)、ios/App/App/Info.plist、*.entitlements、index.htmlを読みます。 - スキャンします。 プロジェクトのルートから Capgo スキャナーを実行します(Node 18 以降):
npm パッケージ名はnpx @capgo/capgo-sec@latest scan --severity medium@capgo/capgo-secで、capsecバイナリがインストールされます。npm にcapsecという名前のパッケージは存在しないため、npx capsecは動作しません。 - スキャナーが検出できないものを grep で検索します(「検証」を参照)。先に Web アプリをビルドし、
dist/またはwww/も grep します。バンドラーはimport.meta.env.*やprocess.env.*の値をインライン化するためです。 - 大規模な変更の前に、調査結果を分類して報告します。 指摘事項をファイルと行番号とともに、Critical/High/Medium/Low に分類します。動作を変える変更(証明書ピンニング(証明書のローテーション時にユーザーがアクセスできなくなる可能性があります)、ルート化されたデバイスのブロック、
allowNavigationホストの削除、厳格な CSP)を行う前に、ユーザーに確認します。 - 該当するリファレンスを読み込み、領域ごとに修正します。
- **スキャンと検証チェックを再実行し、**その後
npx cap syncを実行して、デバイス上でリリースビルドをテストします。
Capacitor 固有の落とし穴
- バンドル内に秘密情報はありません。 Web アセットは IPA/APK に含まれ、
capacitor.config.jsonはネイティブアセットにコピーされます。plugins.*設定の値(@capgo/capacitor-envを含む)は抽出可能です。秘密情報を含む呼び出しはバックエンドに移してください。 allowNavigationはブリッジへのアクセスを許可します。 Android では、すべてのallowNavigationエントリがブリッジの許可オリジンルールに追加されるため、それらのホストのページからネイティブプラグインを呼び出せます。自分が管理するホストのみを指定してください。サードパーティのページは、代わりに@capacitor/browserまたは@capgo/inappbrowserで開いてください。server.urlとserver.cleartextは開発専用です。 Capacitor のドキュメントでは、どちらも「本番環境での使用を意図していない」とされています。LAN IP をコミットすると、HTTP 経由でリモートコードを読み込む WebView が出荷されます。- リリースビルドで WebView がデバッグ可能になります。
ios.webContentsDebuggingEnabled/android.webContentsDebuggingEnabledは、デフォルトではデバッグビルドでのみオンになります。trueをハードコードすると、すべてのリリースビルドで WebView が Safari /chrome://inspectに公開されます。 - CapacitorHttp はピンニングではありません。
plugins.CapacitorHttp.enabledはfetch/ XHR をネイティブネットワーキング経由で処理するだけです。ピンニングには、CapacitorHttp にフックする@capgo/capacitor-ssl-pinningが必要です。 - 生体認証プロンプトは認証ではありません。 ルート化/脱獄されたデバイスでは
verifyIdentity()をフックできます。秘密情報はaccessControl(ハードウェアに紐付いた Keychain/Keystore 項目)で保護し、セッションはサーバー側で検証してください。 - カスタムスキームによる OAuth には PKCE が必要です。 どのアプリでも
myapp://を登録できます。PKCE を使用し、リダイレクトには Universal Links / App Links を優先してください。 - ライブアップデートのバンドルは、暗号化されていない限り公開状態です。 プライベートチャネルでは、バンドルを受け取るユーザーを制限できます。ただし、機密性は確保されません。
参考資料
トピックが該当する場合にのみ、参考資料を読み込んでください。
| 参考資料 | 読み込むタイミング |
|---|---|
| references/capsec-scanner.md | スキャナーの実行、ルール ID の確認、CI のゲート設定、JSON/HTML レポート |
| references/secrets-and-storage.md | ハードコードされたキー、.env の漏えい、トークンの保存、Keychain/Keystore、暗号化された SQLite、ログ記録 |
| references/network.md | HTTPS/ATS/クリアテキスト、network_security_config.xml、証明書ピンニング、CORS と CapacitorHttp の違い |
| references/webview-and-bridge.md | CSP、allowNavigation、iframe、postMessage、eval、ディープリンク/OAuth の検証 |
| references/platform-hardening.md | AndroidManifest のフラグ、R8、iOS Info.plist/entitlements、スクリーンショット保護、ルート化/脱獄の検出、ライブアップデートの暗号化 |
Xcode のコンパイラー/リンカーの強化については、ここでは扱いません。capacitor-ios-security-hardening を使用してください。
検証
プロジェクトのルートから実行してください。リリースビルドでは各 grep の結果が空になるか、意図的に記録された該当箇所のみが表示される必要があります。
# 1. Scanner gate (exit code 1 on high/critical)
npx @capgo/capgo-sec@latest scan --ci
# 2. Dev-only config left in capacitor.config
grep -nE "cleartext|server:\s*\{|\"url\"|url:|allowMixedContent|webContentsDebuggingEnabled" capacitor.config.*
# 3. Secrets in the built bundle (build first)
npm run build
grep -rnE "sk_live_|sk-ant-|sk-proj-|AKIA[0-9A-Z]{16}|service_role|-----BEGIN (RSA |EC )?PRIVATE KEY" dist/ www/ 2>/dev/null
# 4. Tokens in plain storage
grep -rnE "(Preferences\.set|localStorage\.setItem)\(.*(token|password|secret|jwt)" -i src/
# 5. Android manifest flags
grep -nE "usesCleartextTraffic|allowBackup|debuggable|exported=\"true\"" android/app/src/main/AndroidManifest.xml
# 6. iOS transport and file sharing
plutil -p ios/App/App/Info.plist | grep -E "NSAllowsArbitraryLoads|NSExceptionAllowsInsecureHTTPLoads|UIFileSharingEnabled|LSSupportsOpeningDocumentsInPlace"
# 7. Native projects pick up config changes
npx cap sync
次に、リリースビルドをデバイスにインストールして、ログインが機能すること、API 呼び出しが成功すること(ピンニングによって妨げられていないこと)、Safari Web Inspector / chrome://inspect が接続できないことを確認してください。
エラー処理
| エラー | 原因 | 修正方法 |
|---|---|---|
net::ERR_CLEARTEXT_NOT_PERMITTED(Android) | HTTP リクエストがブロックされています。API 28 以降、クリアテキスト通信はデフォルトで無効です | HTTPS を使用してください。開発時のライブリロードに限り、開発専用の設定で server.cleartext: true を使用してください。usesCleartextTraffic="true" を製品版に含めないでください。 |
The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.(iOS、NSURLError -1022) | ATS によって HTTP URL がブロックされています | HTTPS を使用してください。レガシーホストが避けられない場合は、限定的な NSExceptionDomains エントリを追加し、NSAllowsArbitraryLoads は使用しないでください。 |
... has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present | バックエンドが WebView のオリジンを許可していません | サーバーで capacitor://localhost(iOS)および https://localhost(Android のデフォルト)を許可するか、CapacitorHttp を有効にしてください。認証が必要なエンドポイントに Access-Control-Allow-Origin: * を追加しないでください。 |
Refused to connect to '<url>' because it violates the following Content Security Policy directive | CSP の connect-src にホストがありません | 正確な API オリジンを connect-src に追加してください。* にフォールバックしないでください。 |
| 証明書の更新後にピン留めされたリクエストが失敗する | 古いリーフ証明書だけにピン留めされています | CA または中間証明書とバックアップ証明書をピン留めし、ローテーション前にバックアップを配布してください。 |
npm error 404 Not Found - GET https://registry.npmjs.org/capsec | パッケージ名が正しくありません | npx @capgo/capgo-sec@latest scan を使用してください。 |
No protected credentials found / No protected data found(コード 21、@capgo/capacitor-native-biometric) | accessControl を指定して保存されたデータがない、新規インストール、または生体認証の登録変更によって項目が無効になっています | 「ログアウト済み」として扱い、サーバーに再認証してから、AccessControl.BIOMETRY_CURRENT_SET または BIOMETRY_ANY を指定して再度保存してください。 |
リソース
- Capacitor セキュリティガイド:https://capacitorjs.com/docs/guides/security
- Capgo セキュリティスキャナー:https://capgo.app/security-scanner/(ソース:https://github.com/Cap-go/capgo-sec)
- OWASP Mobile Top 10:https://owasp.org/www-project-mobile-top-10/
- OWASP MASVS / MASTG:https://mas.owasp.org/
コメント
Markdown 対応