FlawOpen

flawopen.com/Teardowns/cve-2026-77244-mcp-atlassian-http-auth-bypass

● CVE-2026-77244 · CVSS 10.0[1] · 緊急
セキュリティ研究 · FlawOpen

CVE-2026-77244:mcp-atlassianの未認証HTTPツールアクセス

CVE-2026-77244では、未認証の呼び出し元がコミュニティプロジェクトmcp-atlassianのHTTPツールハンドラーに到達でき、運用者の環境変数に設定されたJiraまたはConfluence資格情報が使われる可能性がありました。主な修正は0.22.0です。SSE利用者は別の関連トランスポート問題の修正を含む0.23.1以降が必要です。[1], [4], [5], [6]

CVSS ベクトルCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N[1]
💡 わかりやすい解説 (ELI5)

受付では、スタッフ専用ドアを開ける前に来訪者のバッジを確認する必要があります。以前の手順では、バッジがないと受付係のマスターキーを貸していました。この問題では、検証済みのユーザーIDなしにHTTPリクエストがツールへ届き、ツールが運用者の共有Atlassian資格情報を使えるという2つの欠落が連鎖しました。修正は未認証HTTPリクエストを拒否し、資格情報のフォールバックを明示的な設定にします。[1], [3]

主要な概念と専門用語

MCPトランスポート
クライアントとサーバー間でModel Context Protocolリクエストを運ぶ通信経路です。このCVEはmcp-atlassianのHTTPトランスポートに関するもので、アドバイザリではstdioは対象外です。[1], [4]
グローバル資格情報フォールバック
リクエストに個別のユーザーIDがない場合、サーバー環境に設定されたJiraまたはConfluence資格情報を使うことです。リモートから到達可能なHTTPでは匿名リクエストが運用者としての操作になり得ます。[1], [4]
認証境界
保護されたツールハンドラーへリクエストを渡す前に、サーバー側で呼び出し元のIDを確認する仕組みです。ネットワーク到達性、空でないトークン文字列、プロキシへの想定上の信頼だけでは本人確認になりません。[1], [7]
CWE-287
不適切な認証:アクセスを許可する前に、申告されたIDを十分に証明できていません。[1], [7]
CWE-303
トークン検証器の認証実装に誤りがあり、有効性を確認せず、空でないトークンをすべて受け入れます。[1], [9]
CWE-862
HTTPリクエストは、検証済みユーザーIDを必須とする認可チェックなしで、特権ツールのハンドラーに到達する可能性がありました。[1], [10]

フレームワーク対応

根本原因の分析 (Root Cause)

GitHub Security Advisoryが説明するのはコミュニティプロジェクトmcp-atlassianの攻撃経路であり、Atlassian製品の脆弱性ではありません。0.22.0より前では、HTTPミドルウェアがユーザーIDのないリクエストをツールハンドラーへ通すことがありました。環境変数に運用者の資格情報が設定されていると、JiraFetcherまたはConfluenceFetcherがそのグローバル資格情報へフォールバックできました。アドバイザリは、空でない任意の文字列を受け入れる不透明トークン検証器についても記載していますが、これは呼び出し元の実際のIDを証明しません。認証境界ではリクエストIDと資格情報選択の両方を保護し、IDがない、または未検証のユーザーに運用者の特権資格情報を継承させてはいけません。0.22.0の修正は未認証のstreamable-HTTP MCP POSTにHTTP 401を返し、単一ユーザー環境でALLOW_GLOBAL_CRED_FALLBACK=trueを明示した場合を除いてHTTPコンテキストでグローバルフォールバックを拒否します。stdioの動作は変更されません。別のGHSA-5j8j-256g-vvp5はSSEパスの照合ミスを説明し、0.23.1で修正されました。これはCVE-2026-77244ではありません。SSE環境は0.23.1以降に更新し、CVEの0.22.0修正だけで別のアドバイザリも直ると考えないでください。アドバイザリは悪用を確認しておらず、この記事も実際の侵害を主張しません。 CVEアドバイザリは、この経路の認証、トークン検証、認可の各不備をCWE-287、CWE-303、CWE-862に分類しています。 このアドバイザリでは、報告者としてcrazydude123が記載されています。[1], [3], [4], [5], [6], [7], [9], [10]

ステップ・バイ・ステップの攻撃フロー

ステップ 1

MCPのHTTPエンドポイントに到達できる

コミュニティ版mcp-atlassianをHTTPで稼働させ、未認証の相手がトランスポートに到達できる構成です。stdioのみの構成はこのCVEの影響経路外です。[1]

ステップ 2

検証済みユーザーがいないままツールに到達する

0.22.0以前では、ユーザーIDのないHTTPリクエストがトランスポート境界で拒否されず、ミドルウェアを通過する可能性がありました。アドバイザリは、空でない文字列もIDとして独立検証されなかったと述べています。[1], [3]

ステップ 3

ツールが運用者の共有資格情報を選ぶ

ユーザーIDがなく、サーバー環境にJiraまたはConfluence資格情報があると、fetcherはグローバル資格情報を使うことがあります。リクエストは運用者に有効化されたツール権限を行使し得ます。影響は権限と設定次第です。[1], [3]

ステップ 4

トランスポートで拒否し、資格情報の選択でも安全側に倒す

0.22.0は未認証のstreamable-HTTPリクエストにHTTP 401を返し、明示的な許可がない限りHTTPコンテキストのグローバルフォールバックを止めます。SSEでは別のパス照合問題が修正された0.23.1以降を使用してください。[1], [4], [5], [6]

ソースコード比較:脆弱 vs 堅牢化

上流の制御フローを絞って表現したもので、関数全体の逐語的なコピーではありません。修正はトランスポート境界でHTTP 401を返し、HTTPコンテキストでグローバルfetcherを返す前にも確認を加えています。[1], [3], [4]

脆弱な実装
# 影響を受ける制御フローを簡略化した表現です。
async def handle_request(scope, ctx):
    user_identity = scope.get("state", {}).get("user_atlassian_auth_type")
    # HTTP 境界で ID の欠落を拒否していませんでした。
    return await call_tool_handler(ctx, user_identity=user_identity)

def get_fetcher(user_identity, global_config):
    if user_identity:
        return fetcher_for_user(user_identity)
    # 環境設定の運用者資格情報にフォールバックします。
    return fetcher_from_config(global_config)
堅牢化されたセキュアパッチ
# 0.22.0 に統合された保護策を簡潔に示したものです。
async def handle_request(scope, ctx):
    user_identity = scope.get("state", {}).get("user_atlassian_auth_type")
    if is_mcp_http_post(scope) and not user_identity and not allow_global_fallback():
        return http_401("Authentication required")
    return await call_tool_handler(ctx, user_identity=user_identity)

def get_fetcher(user_identity, global_config, *, in_http_context):
    if user_identity:
        return fetcher_for_user(user_identity)
    if in_http_context and not allow_global_fallback():
        raise PermissionError("Refusing operator credentials for an unauthenticated HTTP request")
    return fetcher_from_config(global_config)

エンジニアリング&システム堅牢化チェックリスト

参考資料