取り組みの背景 — なぜAIセキュリティ監査が必要なのか
ソフトウェア開発において、セキュリティは後回しにされがちな領域です。しかし、2026年の調査によると、プロダクションインシデントの約40%がセキュリティ関連の問題に起因しており、その多くは開発段階で検出可能なものでしました。
Antigravityのマルチエージェント機能を活用すれば、コードを書くと同時にセキュリティ監査を自動実行し、脆弱性を早期に発見・修正するパイプラインを構築できます。ここで扱うのは以下の内容を実践的に解説します。
依存関係の脆弱性スキャンを自動化するエージェント設計
OWASP Top 10に準拠したコードレビューの自動化
SQLインジェクション・XSS・認証バイパスの検出パターン
CI/CDパイプラインとの統合による継続的セキュリティ監査
対象読者 : Antigravityの基本操作に慣れており、マルチエージェントの概念を理解している中〜上級の開発者。
前提知識・環境準備
この記事を進めるにあたり、以下の環境が必要です。
Antigravity 最新版(v1.20以降推奨)
Node.js 20以上(依存関係スキャンツールの実行用)
Git(バージョン管理とCI/CD連携用)
npm または yarn(パッケージマネージャー)
また、以下の概念を理解していることを前提とします。
Antigravityのエージェントモードとmanager surface
agents.md によるエージェント定義
GitHub ActionsまたはCloudflare WorkersによるCI/CD基本設定
セキュリティ監査エージェントのアーキテクチャ
AIセキュリティ監査パイプラインは、3つの専門エージェントで構成します。
全体構成
┌─────────────────────────────────────────┐
│ Manager Surface │
│ (セキュリティ監査オーケストレーター) │
├──────────┬──────────┬───────────────────┤
│ Agent 1 │ Agent 2 │ Agent 3 │
│ 依存関係 │ コード │ インフラ │
│ スキャナ │ レビュア │ チェッカー │
└──────────┴──────────┴───────────────────┘
各エージェントの役割を明確に分離することで、並列実行による高速化と、専門領域ごとの深い分析を両立させます。
agents.md の定義
まず、プロジェクトルートに .antigravity/agents.md を作成します。
# Security Audit Manager
あなたはセキュリティ監査のオーケストレーターです。
以下の3つの専門エージェントを管理し、包括的なセキュリティレポートを生成してください。
## 委任ルール
1. 依存関係の脆弱性チェックは `dependency-scanner` に委任
2. ソースコードのセキュリティレビューは `code-reviewer` に委任
3. インフラ設定・環境変数の監査は `infra-checker` に委任
4. 全エージェントの結果を統合し、重要度順にソートしたレポートを生成
---
# dependency-scanner
あなたは依存関係セキュリティの専門家です。
- package.json / package-lock.json を分析
- 既知のCVEデータベースと照合
- 修正バージョンが利用可能か確認
- 重要度(Critical / High / Medium / Low)を判定
---
# code-reviewer
あなたはアプリケーションセキュリティの専門家です。
OWASP Top 10 に基づいてソースコードをレビューしてください。
- SQLインジェクション
- クロスサイトスクリプティング(XSS)
- 認証・認可の不備
- 機密情報のハードコーディング
- 安全でないデシリアライゼーション
---
# infra-checker
あなたはインフラセキュリティの専門家です。
- 環境変数の管理状況を確認
- CORS設定の妥当性を検証
- HTTPSの強制設定を確認
- セキュリティヘッダー(CSP, HSTS等)の設定状況を監査
依存関係スキャンの自動化
npm audit との統合
Antigravityのエージェントに npm audit の結果を解析させ、具体的な修正アクションを提案させます。
// scripts/security-audit.ts
// セキュリティ監査の自動実行スクリプト
import { execSync } from "child_process" ;
import * as fs from "fs" ;
interface AuditVulnerability {
name : string ;
severity : "critical" | "high" | "moderate" | "low" ;
title : string ;
url : string ;
fixAvailable : boolean ;
}
function runDependencyAudit () : AuditVulnerability [] {
try {
// npm audit を JSON形式で実行
const result = execSync ( "npm audit --json" , {
encoding: "utf-8" ,
timeout: 30000 ,
});
const audit = JSON . parse (result);
return Object. entries (audit.vulnerabilities || {}). map (
([ name , data ] : [ string , any ]) => ({
name,
severity: data.severity,
title: data.title || "Unknown vulnerability" ,
url: data.url || "" ,
fixAvailable: !! data.fixAvailable,
})
);
} catch ( error : any ) {
// npm audit はexit code 1で脆弱性を報告する
if (error.stdout) {
const audit = JSON . parse (error.stdout);
return Object. entries (audit.vulnerabilities || {}). map (
([ name , data ] : [ string , any ]) => ({
name,
severity: data.severity,
title: data.title || "Unknown vulnerability" ,
url: data.url || "" ,
fixAvailable: !! data.fixAvailable,
})
);
}
throw error;
}
}
// 実行と結果出力
const vulnerabilities = runDependencyAudit ();
const critical = vulnerabilities. filter (( v ) => v.severity === "critical" );
const high = vulnerabilities. filter (( v ) => v.severity === "high" );
console. log ( ` \n 🔍 依存関係セキュリティレポート` );
console. log ( `${"=" . repeat ( 50 ) }` );
console. log ( `Critical: ${ critical . length } 件` );
console. log ( `High: ${ high . length } 件` );
console. log ( `Total: ${ vulnerabilities . length } 件` );
// 期待する出力例:
// 🔍 依存関係セキュリティレポート
// ==================================================
// Critical: 0 件
// High: 2 件
// Total: 8 件
エージェントへの解析依頼
Antigravityのターミナルで以下のようにエージェントに依頼します。
@dependency-scanner package.jsonとpackage-lock.jsonを分析し、
既知の脆弱性を一覧にしてください。各脆弱性について、
修正バージョンの有無と推奨アクションを含めてください。
エージェントは npm audit の結果を解析し、次のような構造化レポートを生成します。
## 依存関係脆弱性レポート
| パッケージ | 重要度 | CVE | 修正バージョン | 推奨アクション |
|-----------|--------|-----|---------------|--------------|
| lodash | High | CVE-2024-XXXX | 4.17.22 | `npm update lodash` |
| express | Medium | CVE-2024-YYYY | 4.19.3 | `npm update express` |
OWASPベースのコードセキュリティレビュー
SQLインジェクション検出パターン
エージェントに以下のようなパターンマッチングルールを学習させます。
// lib/security-patterns.ts
// セキュリティパターン検出ライブラリ
export const SQL_INJECTION_PATTERNS = [
// 文字列連結によるクエリ構築(危険)
/`SELECT . * \$\{ . * \} `/ g ,
/ ['"] SELECT . * ['"] \+ / g ,
/query \( . * \+ . * \) / g ,
// テンプレートリテラルの直接挿入(危険)
/ \. query \( ` [ ^ `] * \$\{ [ ^ }] + \} [ ^ `] * ` \) / g ,
// eval や Function コンストラクタ(極めて危険)
/eval \s * \( / g ,
/new \s + Function \s * \( / g ,
] as const ;
export const XSS_PATTERNS = [
// innerHTML への未サニタイズ入力
/ \. innerHTML \s * = \s * (?! ['"`] )/ g ,
// dangerouslySetInnerHTML(React)
/dangerouslySetInnerHTML \s * = \s * \{ \s * \{ \s * __html: \s * (?!DOMPurify)/ g ,
// document.write
/document \. write \s * \( / g ,
] as const ;
export const AUTH_PATTERNS = [
// ハードコードされたシークレット
/(?:password | secret | api [_-] ? key | token) \s * [:=]\s * ['"][ ^ '"] {8,} ['"] / gi ,
// JWT検証のスキップ
/verify \s * : \s * false/ g ,
// 安全でないランダム生成
/Math \. random \(\) / g ,
] as const ;
/**
* ファイルをスキャンしてセキュリティ問題を検出する
*/
export function scanFile (
content : string ,
filePath : string
) : SecurityIssue [] {
const issues : SecurityIssue [] = [];
// SQLインジェクションチェック
SQL_INJECTION_PATTERNS . forEach (( pattern ) => {
const matches = content. matchAll ( new RegExp (pattern));
for ( const match of matches) {
issues. push ({
type: "SQL_INJECTION" ,
severity: "critical" ,
file: filePath,
line: getLineNumber (content, match.index ! ),
message: "SQL文に未サニタイズの入力が直接挿入されています" ,
recommendation:
"パラメータ化クエリまたはORMを使用してください" ,
});
}
});
// XSSチェック
XSS_PATTERNS . forEach (( pattern ) => {
const matches = content. matchAll ( new RegExp (pattern));
for ( const match of matches) {
issues. push ({
type: "XSS" ,
severity: "high" ,
file: filePath,
line: getLineNumber (content, match.index ! ),
message: "未サニタイズの入力がDOMに挿入される可能性があります" ,
recommendation: "DOMPurifyまたはテキストノードを使用してください" ,
});
}
});
return issues;
}
interface SecurityIssue {
type : string ;
severity : "critical" | "high" | "medium" | "low" ;
file : string ;
line : number ;
message : string ;
recommendation : string ;
}
function getLineNumber ( content : string , index : number ) : number {
return content. substring ( 0 , index). split ( " \n " ). length ;
}
// 期待する出力例(scanFile実行時):
// [
// {
// type: "SQL_INJECTION",
// severity: "critical",
// file: "src/api/users.ts",
// line: 42,
// message: "SQL文に未サニタイズの入力が直接挿入されています",
// recommendation: "パラメータ化クエリまたはORMを使用してください"
// }
// ]
エージェントによる自動修正
検出された脆弱性に対して、エージェントが自動修正を提案します。
@code-reviewer 以下のファイルにSQLインジェクションの脆弱性が検出されました。
パラメータ化クエリに修正してください。
修正前:
const user = await db.query(`SELECT * FROM users WHERE id = ${userId}`);
修正後(エージェントが生成):
const user = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
インフラセキュリティの自動監査
セキュリティヘッダーチェッカー
// scripts/check-security-headers.ts
// Webアプリのセキュリティヘッダーを検証するスクリプト
interface SecurityHeaderCheck {
header : string ;
expected : string | RegExp ;
severity : "critical" | "high" | "medium" ;
description : string ;
}
const REQUIRED_HEADERS : SecurityHeaderCheck [] = [
{
header: "Strict-Transport-Security" ,
expected: /max-age= \d {8,} / ,
severity: "critical" ,
description: "HSTS: HTTPSの強制(max-ageは1年以上推奨)" ,
},
{
header: "Content-Security-Policy" ,
expected: /default-src/ ,
severity: "high" ,
description: "CSP: XSSやデータインジェクション攻撃の防御" ,
},
{
header: "X-Content-Type-Options" ,
expected: "nosniff" ,
severity: "medium" ,
description: "MIMEタイプスニッフィングの防止" ,
},
{
header: "X-Frame-Options" ,
expected: /DENY | SAMEORIGIN/ ,
severity: "medium" ,
description: "クリックジャッキング攻撃の防止" ,
},
{
header: "Referrer-Policy" ,
expected: /strict-origin | no-referrer/ ,
severity: "medium" ,
description: "リファラ情報の漏洩防止" ,
},
];
async function checkSecurityHeaders ( url : string ) {
const response = await fetch (url, { method: "HEAD" });
console. log ( ` \n 🛡️ セキュリティヘッダー監査: ${ url }` );
console. log ( "=" . repeat ( 60 ));
let issues = 0 ;
for ( const check of REQUIRED_HEADERS ) {
const value = response.headers. get (check.header);
const passed = value
? typeof check.expected === "string"
? value === check.expected
: check.expected. test (value)
: false ;
const status = passed ? "✅" : "❌" ;
console. log ( `${ status } ${ check . header }` );
if ( ! passed) {
console. log ( ` 重要度: ${ check . severity }` );
console. log ( ` 説明: ${ check . description }` );
console. log ( ` 現在の値: ${ value || "(未設定)"}` );
issues ++ ;
}
}
console. log ( ` \n 合計: ${ issues } 件の問題が見つかりました` );
return issues;
}
// 使用例
// checkSecurityHeaders("https://your-app.example.com");
// 期待する出力例:
// 🛡️ セキュリティヘッダー監査: https://your-app.example.com
// ============================================================
// ✅ Strict-Transport-Security
// ❌ Content-Security-Policy
// 重要度: high
// 説明: CSP: XSSやデータインジェクション攻撃の防御
// 現在の値: (未設定)
// ✅ X-Content-Type-Options
// ✅ X-Frame-Options
// ✅ Referrer-Policy
//
// 合計: 1 件の問題が見つかりました
環境変数の安全性チェック
// scripts/check-env-security.ts
// 環境変数と機密情報の管理状態を監査するスクリプト
import * as fs from "fs" ;
import * as path from "path" ;
const SENSITIVE_PATTERNS = [
/API [_-] ? KEY/ i ,
/SECRET/ i ,
/PASSWORD/ i ,
/TOKEN/ i ,
/PRIVATE [_-] ? KEY/ i ,
/DATABASE [_-] ? URL/ i ,
/STRIPE [_-] ? SECRET/ i ,
];
function auditEnvSecurity ( projectRoot : string ) : void {
const issues : string [] = [];
// .env ファイルが .gitignore に含まれているか確認
const gitignorePath = path. join (projectRoot, ".gitignore" );
if (fs. existsSync (gitignorePath)) {
const gitignore = fs. readFileSync (gitignorePath, "utf-8" );
if ( ! gitignore. includes ( ".env" )) {
issues. push (
"⚠️ CRITICAL: .env が .gitignore に含まれていません"
);
}
}
// ソースコード内のハードコードされたシークレットを検出
const srcDir = path. join (projectRoot, "src" );
if (fs. existsSync (srcDir)) {
scanDirectory (srcDir, issues);
}
console. log ( " \n 🔐 環境変数セキュリティ監査レポート" );
console. log ( "=" . repeat ( 50 ));
if (issues. length === 0 ) {
console. log ( "✅ 問題は検出されませんでした" );
} else {
issues. forEach (( issue ) => console. log (issue));
}
}
function scanDirectory ( dir : string , issues : string []) : void {
const files = fs. readdirSync (dir, { withFileTypes: true });
for ( const file of files) {
const fullPath = path. join (dir, file.name);
if (file. isDirectory () && file.name !== "node_modules" ) {
scanDirectory (fullPath, issues);
} else if (
file. isFile () &&
/ \. (ts | js | tsx | jsx) $ / . test (file.name)
) {
const content = fs. readFileSync (fullPath, "utf-8" );
const lines = content. split ( " \n " );
lines. forEach (( line , index ) => {
SENSITIVE_PATTERNS . forEach (( pattern ) => {
if (
pattern. test (line) &&
/ ['"][ ^ '"] {8,} ['"] / . test (line)
) {
issues. push (
`⚠️ HIGH: ${ fullPath }:${ index + 1 } — ` +
`機密情報がハードコードされている可能性`
);
}
});
});
}
}
}
// 実行
// auditEnvSecurity(process.cwd());
// 期待する出力例:
// 🔐 環境変数セキュリティ監査レポート
// ==================================================
// ⚠️ HIGH: src/config/database.ts:15 — 機密情報がハードコードされている可能性
// ⚠️ CRITICAL: .env が .gitignore に含まれていません
CI/CDパイプラインへの統合
GitHub Actionsワークフロー
セキュリティ監査をCI/CDに組み込むことで、プルリクエストごとに自動チェックを実行します。
# .github/workflows/security-audit.yml
name : Security Audit
on :
pull_request :
branches : [ main ]
push :
branches : [ main ]
schedule :
# 毎週月曜 9:00 JST に定期実行
- cron : "0 0 * * 1"
jobs :
dependency-scan :
name : Dependency Vulnerability Scan
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- uses : actions/setup-node@v4
with :
node-version : "20"
- run : npm ci
- name : Run npm audit
run : |
npm audit --audit-level=high || true
npm audit --json > audit-report.json
- name : Upload audit report
uses : actions/upload-artifact@v4
with :
name : audit-report
path : audit-report.json
code-security-review :
name : Code Security Review
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- uses : actions/setup-node@v4
with :
node-version : "20"
- run : npm ci
- name : Run security pattern scan
run : npx ts-node scripts/security-audit.ts
- name : Check for hardcoded secrets
run : |
# 機密情報のハードコードを検出
if grep -rn \
-e "API_KEY\s*=\s*['\"][^'\"]*['\"]" \
-e "SECRET\s*=\s*['\"][^'\"]*['\"]" \
--include="*.ts" --include="*.js" \
--exclude-dir=node_modules \
src/; then
echo "::error::Hardcoded secrets detected!"
exit 1
fi
security-headers :
name : Security Headers Check
runs-on : ubuntu-latest
if : github.event_name == 'schedule'
steps :
- uses : actions/checkout@v4
- uses : actions/setup-node@v4
with :
node-version : "20"
- run : npm ci
- name : Check production security headers
run : npx ts-node scripts/check-security-headers.ts
env :
TARGET_URL : ${{ secrets.PRODUCTION_URL }}
Antigravityエージェントとの連携フロー
CI/CDの結果をAntigravityエージェントにフィードバックし、自動修正を実行する流れを構築します。
1. PR作成 → GitHub Actions 実行
2. セキュリティスキャン結果をPRコメントに投稿
3. Antigravity で修正ブランチを開く
4. @code-reviewer にスキャン結果を共有
5. エージェントが修正コードを生成
6. 修正をコミット → 再スキャン → マージ
個人開発者の視点から(実体験メモ)
まとめ — セキュリティを開発プロセスに組み込む
ここで扱うのはAntigravityのマルチエージェント機能を活用したセキュリティ監査自動化パイプラインの構築方法を解説しました。
重要なポイントを振り返ります。まず、専門エージェントの分離により、依存関係・コード・インフラそれぞれに特化した監査を並列実行できます。次に、OWASP Top 10に基づくパターン検出で、一般的なWebアプリケーションの脆弱性を網羅的にカバーできます。そして、CI/CDパイプラインとの統合により、継続的なセキュリティ監査を自動化できます。
セキュリティは一度設定して終わりではなく、継続的に改善していくプロセスです。Antigravityのエージェントを活用して、開発速度を落とすことなくセキュリティ品質を向上させましょう。
マルチエージェントの設計パターンについてさらに詳しく知りたい方は、マルチエージェントオーケストレーション実践ガイドもあわせてご覧ください。環境変数の安全な管理については、環境変数・シークレット管理ガイド が参考になります。