mcpField
S
security-misconfiguration

security-misconfiguration

github.com/scholarly360セキュリティ2245 回インストール29 週間前に更新
リポジトリ

security-misconfiguration について

Flask または FastAPI を使う Python Web アプリのセキュリティ監査スキルです。Bandit のスキャン、分類別チェックリスト、修正後の再確認を組み合わせ、CWE、深刻度、対処案を含む所見の整理を支援します。

主な機能

  1. 01デバッグモードとハードコードされた秘密情報の確認
  2. 02API ドキュメント公開とセキュリティヘッダーの確認
  3. 03Cookie、XML、インフラ設定の点検
  4. 04Bandit による静的スキャン
  5. 05CWE と修正案を含む所見の作成

活用シーン

  1. 01Flask または FastAPI アプリの監査
  2. 02デプロイ前の設定確認
  3. 03修正後の所見の再検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/scholarly360/owasp-top10-web-skills --skill security-misconfiguration

インストール後、Claude Code で/security-misconfigurationを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
fastapi-hardening.md
flask-hardening.md
security-headers.md

詳細

セキュリティ設定ミス(OWASP A02:2025)

セキュリティ設定ミスは、OWASP Top 10:2025で5位から2位に急上昇し、**アプリケーションの3.00%**で確認され、719,000件を超える発生が報告されています。システムがセキュリティの観点から誤って設定されている場合に発生し、Python の Web アプリでは攻撃対象領域が広範囲に及びます。


ワークフロー

  1. フレームワークを特定する — Flask、FastAPI、またはその両方
  2. 静的チェックを実行する — Bandit による SAST スキャン(「ツール」セクションを参照)
  3. チェックリストを確認する — 以下の各カテゴリを確認し、問題に印を付ける
  4. レポートを作成する — CWE ID、重大度、修正用スニペットとともに検出事項を一覧にする
  5. 修正を検証する — 修正後に 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-Securitymax-age=31536000; includeSubDomains
X-Content-Type-Optionsnosniff
X-Frame-OptionsDENY または SAMEORIGIN
Content-Security-Policyドメイン固有の値。最低限、unsafe-inline をブロックする
Referrer-Policystrict-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デフォルト値にハードコードされたパスワード
B201flask_debug_true
B405import xml.etree — defusedxml を推奨
B408import xml.minidom — defusedxml を推奨
B410import 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-611XML 外部エンティティ(XXE)高
CWE-614Secure 属性のない機密 Cookie高
CWE-1004HttpOnly 属性のない機密 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"

コメント