security-misconfiguration について
Flask または FastAPI を使う Python Web アプリのセキュリティ監査スキルです。Bandit のスキャン、分類別チェックリスト、修正後の再確認を組み合わせ、CWE、深刻度、対処案を含む所見の整理を支援します。
主な機能
- 01デバッグモードとハードコードされた秘密情報の確認
- 02API ドキュメント公開とセキュリティヘッダーの確認
- 03Cookie、XML、インフラ設定の点検
- 04Bandit による静的スキャン
- 05CWE と修正案を含む所見の作成
活用シーン
- 01Flask または FastAPI アプリの監査
- 02デプロイ前の設定確認
- 03修正後の所見の再検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ scholarly360/ owasp-top10-web-skills --skill security-misconfigurationインストール後、Claude Code で/security-misconfigurationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/fastapi-hardening.mdflask-hardening.mdsecurity-headers.md詳細
セキュリティ設定ミス(OWASP A02:2025)
セキュリティ設定ミスは、OWASP Top 10:2025で5位から2位に急上昇し、**アプリケーションの3.00%**で確認され、719,000件を超える発生が報告されています。システムがセキュリティの観点から誤って設定されている場合に発生し、Python の Web アプリでは攻撃対象領域が広範囲に及びます。
ワークフロー
- フレームワークを特定する — Flask、FastAPI、またはその両方
- 静的チェックを実行する — Bandit による SAST スキャン(「ツール」セクションを参照)
- チェックリストを確認する — 以下の各カテゴリを確認し、問題に印を付ける
- レポートを作成する — CWE ID、重大度、修正用スニペットとともに検出事項を一覧にする
- 修正を検証する — 修正後に Bandit と動的なヘッダースキャンを再実行する
個別のカテゴリについて詳しく知りたい場合は、以下を参照してください。
references/flask-hardening.md— Flask 固有の設定と拡張機能references/fastapi-hardening.md— FastAPI 固有の設定とミドルウェアreferences/security-headers.md— CSP の例を含むヘッダーの詳細リファレンス
カテゴリ別チェックリスト
1. デバッグモードの露出(重大)
Flask
# BAD — never in production
app.run(debug=True)
app = Flask(__name__, debug=True)
# BAD — environment variable
# FLASK_DEBUG=1
# GOOD
app.run(debug=False)
# or: rely on FLASK_ENV=production (Flask 2.x) / FLASK_DEBUG=0
- Werkzeug の対話型デバッガーでは、PIN のバイパスにより任意のコードを実行できます
- Bandit ルール:
B201(flask_debug_true)
FastAPI — 同等のデバッグモードはありませんが、/docs と /redoc の露出は同様の問題です(§3を参照)
2. ハードコードされたシークレット(重大)
以下のパターンを検出します。
# BAD
SECRET_KEY = "supersecretkey123"
DATABASE_URL = "postgresql://user:password@host/db"
JWT_SECRET = "my-jwt-secret"
AWS_SECRET_ACCESS_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
適切な方法:
import os
SECRET_KEY = os.environ["SECRET_KEY"] # raises if missing — intentional
DATABASE_URL = os.environ.get("DATABASE_URL") # or use python-dotenv / pydantic-settings
- Bandit ルール:
B105、B106、B107(hardcoded_password_*) - 以下も問題として扱います。バージョン管理にコミットされた
.envファイル内のシークレット - 主な CWE: CWE-526(環境変数内の機密情報)、CWE-321(ハードコードされた暗号鍵)
3. API ドキュメントの露出(高)
FastAPI — 本番環境では /docs(Swagger UI)と /redoc を無効にする必要があります。
# BAD — default behaviour exposes full API schema
app = FastAPI()
# GOOD — disable in production
import os
docs_url = None if os.getenv("ENV") == "production" else "/docs"
redoc_url = None if os.getenv("ENV") == "production" else "/redoc"
app = FastAPI(docs_url=docs_url, redoc_url=redoc_url)
- ドキュメントを残す必要がある場合は、認証ミドルウェアまたは IP 許可リストで保護します
- 認証なしで使用されている Flask の
flask-swagger-uiまたはflasggerのブループリントも問題として扱います
4. セキュリティヘッダーの欠如または設定の不備(高)
HTTP レスポンスで以下のヘッダーをスキャンします。本番環境ではすべて設定されている必要があります。
| ヘッダー | 必須値/パターン |
|---|---|
Strict-Transport-Security | max-age=31536000; includeSubDomains |
X-Content-Type-Options | nosniff |
X-Frame-Options | DENY または SAMEORIGIN |
Content-Security-Policy | ドメイン固有の値。最低限、unsafe-inline をブロックする |
Referrer-Policy | strict-origin-when-cross-origin |
Permissions-Policy | 必要に応じてカメラ、マイク、位置情報を制限する |
Flask — flask-talisman を使用します。
from flask_talisman import Talisman
Talisman(app, force_https=True, content_security_policy={
"default-src": "'self'",
"script-src": ["'self'", "cdn.example.com"],
})
FastAPI — ミドルウェアを使用する方法:
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
from starlette.middleware import Middleware
from secure import SecureHeaders # 'secure' package
secure_headers = SecureHeaders()
@app.middleware("http")
async def set_secure_headers(request, call_next):
response = await call_next(request)
secure_headers.starlette(response)
return response
主な CWE: CWE-16(設定)、CWE-1021(不適切なフレーム制限)
5. Cookie フラグの設定不備(高)
Flask セッション Cookie:
# BAD defaults — cookies sent over HTTP, accessible by JS
app.config["SESSION_COOKIE_SECURE"] = False
app.config["SESSION_COOKIE_HTTPONLY"] = False
# GOOD
app.config.update(
SESSION_COOKIE_SECURE=True, # HTTPS only
SESSION_COOKIE_HTTPONLY=True, # No JS access
SESSION_COOKIE_SAMESITE="Lax", # CSRF protection
SESSION_COOKIE_NAME="__Host-session", # __Host- prefix enforces additional constraints
PERMANENT_SESSION_LIFETIME=3600, # 1-hour expiry
)
FastAPI — Cookie を手動で設定する場合:
response.set_cookie(
key="session",
value=token,
httponly=True,
secure=True,
samesite="lax",
max_age=3600,
)
主な CWE: CWE-614(Secure 属性のない機密 Cookie)、CWE-1004(HttpOnly 属性のない機密 Cookie)
6. XML 外部実体(XXE)の処理(高)
外部実体を明示的に無効にしていない XML 解析はすべて問題として扱います。
# BAD — lxml with default parser
from lxml import etree
tree = etree.parse(xml_input) # vulnerable
# BAD — stdlib xml.etree (not vulnerable to XXE by default, but flag for review)
import xml.etree.ElementTree as ET
ET.fromstring(user_input) # safe in CPython, but document why
# GOOD — lxml with entity expansion disabled
parser = etree.XMLParser(
resolve_entities=False,
no_network=True,
load_dtd=False,
)
tree = etree.parse(xml_input, parser)
# GOOD — use defusedxml for untrusted input
import defusedxml.ElementTree as ET
tree = ET.fromstring(user_input)
- Bandit ルール:
B405、B408、B410(xml_* ルール) - 主な CWE: CWE-611(XXE)
7. 不要な機能/攻撃対象領域(中)
本番環境に存在すべきでないサービス、ルート、ミドルウェアを確認します。
- Werkzeug プロファイラー — 本番環境では
ProfilerMiddlewareを削除する - Flask シェル —
/consoleルートへのアクセスを無効化または制限する - 管理インターフェース —
flask-admin、sqladminは認証と IP 制限で保護する - デバッグ用エンドポイント —
sys.environ、スタックトレース、または内部状態を返すルートがあれば問題として扱う - 未使用のミドルウェア — Flask では
app.wsgi_appのチェーンを、FastAPI ではapp.middleware_stackを監査する
8. クラウド/インフラの設定ミス(中)
コードレベルのスキャンではすべてのインフラ設定ミスを検出できませんが、次のパターンに注意してください。
- コード内の S3 バケット名 — パブリック ACL のパターンや、バケットポリシーの欠如を確認します
- データベース接続文字列 — 接続に
sslmode=disableが使用されている場合は警告します - CORS の許可範囲が広すぎる場合:
# BAD — FastAPI
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True)
# allow_origins=["*"] + allow_credentials=True is rejected by browsers but signals intent error
# GOOD
app.add_middleware(CORSMiddleware,
allow_origins=["https://app.example.com"],
allow_credentials=True,
allow_methods=["GET", "POST"],
allow_headers=["Authorization", "Content-Type"],
)
# BAD — Flask
from flask_cors import CORS
CORS(app, origins="*")
# GOOD
CORS(app, origins=["https://app.example.com"], supports_credentials=True)
主な CWE: CWE-16(設定)
ツール
Bandit(SAST)— 主なツール
pip install bandit
bandit -r ./app -f json -o bandit-report.json
# Focus on misconfiguration-relevant rules:
bandit -r ./app -t B105,B106,B107,B201,B405,B408,B410
A02 に関する主な Bandit ルール:
| ルール | 説明 |
|---|---|
B105 | ハードコードされたパスワード文字列 |
B106 | 関数引数にハードコードされたパスワード |
B107 | デフォルト値にハードコードされたパスワード |
B201 | flask_debug_true |
B405 | import xml.etree — defusedxml を推奨 |
B408 | import xml.minidom — defusedxml を推奨 |
B410 | import lxml — XXE のレビュー対象として警告 |
OWASP ZAP(DAST)— ヘッダーと設定の検証
# Docker quick scan — checks headers, misconfigured endpoints, debug info leaks
docker run -t owasp/zap2docker-stable zap-baseline.py \
-t https://your-app.example.com \
-r zap-report.html
ZAP は、セキュリティヘッダーの欠如、スタックトレースの露出、ディレクトリ一覧表示、デバッグエンドポイント、安全でない Cookie を自動的にテストします。
python-dotenv + pydantic-settings(防止)
pip install python-dotenv pydantic-settings
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
secret_key: str # required — fails fast if missing
database_url: str
debug: bool = False # safe default
env: str = "production"
class Config:
env_file = ".env" # loaded only in dev; never committed
settings = Settings()
主な CWE の概要
| CWE | 説明 | 深刻度 |
|---|---|---|
| CWE-16 | 設定(包括的な分類) | 高 |
| CWE-489 | 有効なデバッグコード | 重大 |
| CWE-526 | 環境変数内の機密情報 | 高 |
| CWE-321 | ハードコードされた暗号鍵 | 重大 |
| CWE-611 | XML 外部エンティティ(XXE) | 高 |
| CWE-614 | Secure 属性のない機密 Cookie | 高 |
| CWE-1004 | HttpOnly 属性のない機密 Cookie | 高 |
クイック監査コマンド
Python プロジェクトで A02 の攻撃対象領域を素早くスキャンするには、次のワンライナーを実行してください。
bandit -r . -t B105,B106,B107,B201,B405,B408,B410 --severity-level medium \
&& grep -rn "debug=True\|FLASK_DEBUG=1\|allow_origins=\[.\"\*\"\]\|verify=False" . \
&& echo "Manual checks needed: /docs exposure, cookie flags, security headers"