owasp

Activity

Stars and mentions · Last 30 days, Oct 5 – Nov 3

GitHub stars553
Mentions59
016324864Oct 5Oct 19Nov 3
UTC days · repositories owasp owns10 repositories

Top repositories

owasp’s repositories ranked by new stars, as on trending.

Loading

Contributes to

Repositories outside owasp’s account where owasp opened or reviewed pull requests in the past 365 days.

Who noticed owasp

Everyone who starred or forked owasp’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

60posts
Nov 41 post
  1. なぜWebアプリには「全セッション切断」が必要なのか ChatGPTをはじめ、X、Google、Microsoft、Slackなど、多くの主要Webサービスでは、ログイン中の端末を確認したり、別の端末のログイン状態を取り消したりする仕組みが提供されています。 例: Xのセッション管理UI ところが、自分でWebアプリケーションを開発すると、意外とこの機能が抜け落ちていることがあります。ログアウト機能はあるし、パスワード変更もできる。 しかし、他の端末で有効になっているログイン状態を取り消す手段がない。 ログアウトできることと、他の端末を追い出せることは違う まず、ごく普通のログアウトを考えてみます。 PHPであれば、例えば次のような処理です。 // 現在のセッションを破棄する session_destroy(); // これはサーバー側のセッション破棄だけを示した簡略例です。 // 実際のログアウト処理では、セッション変数の初期化や // セッションCookieの削除なども考慮します。 しかし、同じアカウントで別のブラウザからログインしていた場合、そのセッションには影響しません。 例えば、次のような状態です。 ここでスマートフォンからログアウトしても、終了するのはセッションBだけであり、セッションAやCは引き続き使用できます。 ここで、第三者がセッションAのCookieを盗み、それを自分のブラウザに設定した場合を想定すると、本人が自宅PCのブラウザから通常のログアウトを実行すれば、サーバー側でセッションAが正しく失効し、コピーも使えなくなります。 しかし、本人がスマートフォンしか操作できなかったらどうでしょうか。自宅PCのセッションを遠隔で無効化する機能がなければ、第三者のアクセスを止める手段がありません。 つまり、通常のログアウト機能だけでは、アカウントの所有者がすべての認証状態を制御できるわけではないのです。 パスワードを変えれば解決するのでは? 不正アクセスが疑われる場合、まずパスワードを変更するよう案内されることが多いと思います。もちろん、パスワード変更は重要です。しかし、パスワードを変更しても、既存のログインセッションが自動的に失効するとは限りません。 そもそも、多くのWebアプリケーションは、認証が成功するたびにパスワードを検証しているわけではありません。 ログイン後のアクセスでは、パスワードではなくセッションが認証状態を維持しています。したがって、パスワードを変更しても、既存セッションを失効させる処理がなければ、そのままログイン状態が続く場合があります。 しかもこれは、単純なパスワード認証に限りません。例えば、GitHubやGoogleなどを利用したOAuthログインでも同様です。 認証に成功した後は、アプリケーション自身が発行したセッションによってログイン状態を維持する構成が一般的です。この場合、外部サービス側のパスワードを変更したからといって、アプリケーション側の既存セッションまで自動的に失効するとは限りません。 MFAを有効にしていても結局は同じ 多要素認証(MFA)が有効なら安全なのでは、と考えるかもしれませんが、しかし、MFAは主に認証時の防御です。認証済みのセッションCookieを盗まれた場合、アプリケーションによってはMFAを再度要求せずにアクセスできてしまいます。 ! つまりMFAだろうがパスキーだろうが、結局は扉の鍵をどうするかなのであって、鍵を開けた部屋の中に潜りこまれればいくら鍵を強くしても、あるいは部屋から施錠したとしても有効ではありません。 もちろん、認証情報を端末に結び付ける仕組みや、重要操作時の再認証などで被害を軽減できる場合はありますので、有効ではありますが、ただしそれでも、MFAだけでセッション乗っ取りの問題が解決するわけではありません。新しいログインを防ぐことと、既に成立しているログインを取り消すことは、別のセキュリティ対策なのです。 全セッション切断が必要になる場面 では、どのような状況で全セッション切断が必要になるのでしょうか。 端末の紛失・盗難 もっとも分かりやすい例です。 ログイン状態を維持したままのノートPCやスマートフォンを紛失した場合、別の端末からログイン状態を解除できる必要があります。端末の画面ロックやディスク暗号化は重要ですが、それらだけに依存するのは適切ではありません。 セッションCookieの漏洩 XSS、マルウェア、端末の侵害などによって、セッションCookieや認証トークンが漏洩する可能性があります。 ! 例えば、情報窃取型マルウェア (インフォスティーラー)に端末が感染すると、ブラウザに保存された認証情報やセッションCookieをごっそり窃盗される事があります。 ソフトウェアのサプライチェーン侵害が、こうしたマルウェアの配布経路になる場合もあります。(参考: 800件超の悪性npmパッケージがRAT・スティーラーを配布) HttpOnly属性などの適切なCookie設定は重要ですが、それだけであらゆる漏洩経路を防げるわけではありません。漏洩を完全に防止する仕組みに加えて、漏洩した認証情報を後から使えなくする仕組みも必要です。 共有端末からのログアウト忘れ 大学のPC教室、社内の共有端末、出張先の端末などでログアウトを忘れる場合もあります。本人がその端末に戻れなくても、遠隔からセッションを終了できれば問題を軽減できます。YouTubeなどはよく考えられてはいるものの、他者のテレビにログインしっぱなしという事だってありえます。 アカウント侵害からの復旧 不正アクセスが判明した場合、パスワード変更やMFAの再設定だけでは不十分なことがあります。なぜなら既に別のセッションの入口を持っている可能性があるからです(これはパスワード/MFA/パスキーを経由して鍵を開けるのとは別の概念です)。 ここでは既存セッションをまとめて失効させ、正規ユーザーだけが再びログインできる状態に戻す必要があります。 ! もちろん、攻撃者がパスワードや外部IDプロバイダーのアカウントまで支配しているなら、セッションを切断しただけでは再ログインされてしまいます。したがって、全セッション切断はアカウント復旧の一要素であって、万能な対策ではありません。 管理者による強制切断 ユーザー本人の操作だけでなく、管理者による強制切断も重要です。例えば、退職者のアカウントを無効化した場合です。 アカウントを無効化しても、既存の認証セッションが引き続き利用できる設計では困ります。権限剥奪やアカウント停止の効果が、既存のログイン状態にも確実に反映される必要があります。 ここまで考えると、セッション切断は単なる便利機能ではなく、インシデント発生時にアカウントの制御権を回復するための機能だと分かります。 OWASPもセッションの失効を要求している この問題は、開発者の好みや経験則だけで語られているわけではありません。 Webアプリケーションのセキュリティ基準を公開しているOWASPでは、ASVS(Application Security Verification Standard)という検証基準を策定しています。 OWASP ASVS 5.0のセッション管理に関する要求を見てみます。 要求ID 内容 レベル V7.4.1 終了したセッションを再利用できないこと L1 V7.4.2 アカウント無効化・削除時に全セッションを終了すること L1 V7.4.3 認証要素変更後に他セッションを終了できること L2 V7.4.5 管理者がユーザーのセッションを終了できること L2 V7.5.2 ユーザーがセッションを確認し、再認証後に個別・一括終了できること L2 特にV7.5.2では、ユーザー自身によるセッション一覧の確認と、個別または一括終了が要求されています。 github.com/OWASP/ASVS/blob/master/5.0/en/0x16-V7-… ここで注目したいのは、操作前に少なくとも1つの認証要素による再認証を求めている点です。セッションを乗っ取った攻撃者が、正規ユーザーをすべての端末からログアウトさせることも考えられるためです。 また、OWASPのSession Management Cheat Sheetでも、セッションの遠隔終了、同時ログインの確認、アカウント活動履歴の管理などが推奨されています。 ! ただし、ASVS L2の要求を満たしていないことが、直ちに脆弱性の存在や法令違反を意味するわけではありません。アプリケーションが扱う情報やリスクに応じて、必要な水準を決めることになります。 それでも、一般的な業務アプリケーションや個人情報を扱うサービスでは、全セッション切断を標準的なセキュリティ要件として検討すべきでしょう。 なぜ実装が意外と難しいのか ここまで必要性を説明しましたが、実装は必ずしも簡単ではありません。 理由は単純です。 ログイン状態を作るための仕組みと、既存のログイン状態をすべて探して破棄するための仕組みは別だからです。 例えば、昔ながらのPHPアプリケーションを考えます。 session_start(); $_SESSION['user_id'] = $user['id']; $_SESSION['authenticated'] = true; これでログイン状態を保持できます。 しかし、このコードだけではユーザーIDに紐づく全セッションを探せません。PHP標準のファイルセッションには、ユーザーIDを指定して全セッションを取得するAPIがないためです。 さらに、次のような認証処理があちこちに存在していたらどうでしょうか。 if ($_SESSION['login']) { // 認証済み } if (isset($_SESSION['user_id'])) { // 認証済み } アプリケーションの一部に新しい失効処理を追加しても、別の処理経路からアクセスできる可能性があります。 全セッション切断を正しく実装するには、認証が必要なすべての経路で失効状態を確認する必要があります。結果として、全セッション切断の追加が、認証機構全体の改修になってしまうこともあります。 全セッション切断だけなら別の方法もある 必ずしも、すべてのセッションを列挙する必要はありません。 例えば、ユーザーに認証バージョンを持たせる方式です。 users.auth_version = 3 セッションA:auth_version = 3 セッションB:auth_version = 3 全セッション切断時にバージョンを更新します。 UPDATE users SET auth_version = auth_version + 1 WHERE id = ?; その後、各リクエストで認証バージョンを比較すれば、古いセッションを無効化できます。 users.auth_version = 4 セッションA:auth_version = 3 → 無効 セッションB:auth_version = 3 → 無効 この方式なら、ユーザーとセッションの対応表がなくても全セッションを論理的に失効させられます。ただし、認証が必要な各リクエストでバージョンを検証する必要があります。また、既存の認証処理が散在している場合は、そのすべてに検証処理を適用しなければなりません。 結局、どの方式を採用しても、認証処理の設計が重要になります。 例えばLaravelの場合は比較的少ない改修で実現できる Laravelには、セッション管理や認証の仕組みが標準で用意されていますし、さらに、他の端末をログアウトさせるメソッドも存在します。 // 他のデバイスからログアウトさせる Auth::logoutOtherDevices($currentPassword); ! 最近のLaravelでは、内部的にパスワードハッシュを再生成し、AuthenticateSessionミドルウェアで既存セッションとの不一致を検出する仕組みになっています。 そのため、対象の認証ルートにミドルウェアが適用されていなければ、期待どおりの失効は実現できません。 なお、Laravelには次のような汎用的なメソッドはありません。 // このような標準メソッドはない Auth::logoutAllDevices(); とはいえ、Laravelがすでにセッション管理の仕組みを持っていることは大きな利点です。 Laravelで Database Sessionを利用する場合 LaravelのDatabase Sessionでは、セッションテーブルにユーザーIDが記録されます。 そのため、例えば次のように当該ユーザーのセッションを削除できます。 DB::table('sessions') ->where('user_id', $user->id) ->delete(); ただし、これは全セッション切断処理の一部分にすぎません。 実際には、Remember Meによる再認証への対策、現在のセッションの終了、並行処理なども考慮する必要があります。 そして、この方法はご覧の通りDatabase Sessionを前提としており、ファイルやRedisなど、すべてのセッションドライバでそのまま使えるわけではありません。Laravelが複数のセッションドライバをサポートしていること自体が、汎用的な全セッション切断APIを作りにくくしている理由の一つとも考えられます。 Laravelを利用した独自実装する場合、Remember Meも忘れてはいけない Laravelでは次のような認証が可能です。 Auth::login($user, remember: true); Remember Me機能を有効にしている場合、通常のセッションが失われても、保存されたCookieによって認証状態が復元されることがあります。つまり、セッションテーブルから該当レコードを削除しただけでは、全セッション切断が成立しない可能性があります。 全ログアウト時にはRemember Meトークンも失効させる必要があります。 ! ここで重要なのは、セッションの削除と認証情報の失効は、必ずしも同じ操作ではないということです。 Laravelはそれらを扱う機構を提供していますが、全セッション切断という操作に正しく組み合わせるのはアプリケーション側の仕事です。 他のフレームワークではどうなのか Laravel以外の主要フレームワークも、簡単に調べてみました。 フレームワーク 全セッション切断に利用できる仕組み Ruby on Rails 8 認証ジェネレータのSessionモデル Django 認証ハッシュ、django-allauthのセッション管理 Spring Security SessionRegistry Spring Session ユーザー別のセッション検索・削除 ASP.NET Core Identity Security Stamp Better Auth revokeSessions() Phoenix 認証トークンのDB管理 例えばRails 8の認証ジェネレータでは、ユーザーに紐づく認証セッションをモデルとして管理します。 ASP.NET Core Identityでは、Security Stampを更新することで既存の認証Cookieを失効させる仕組みがあります。ただし、失効の反映には検証間隔が関係します。 Better Authには、一括失効や個別失効の専用APIまで用意されています。 一方、GoのGinやPythonのFastAPIのような比較的軽量なフレームワークでは、採用する認証ライブラリやセッション管理方式によって事情が大きく異なります。 つまり、セッション切断の難易度は、言語そのものよりも、どのような認証基盤を採用しているかに左右されますが、ここで共通しているのは、フレームワークに失効機構が用意されていても、アプリケーションがそれを利用する経路を提供しなければ、ユーザーは使えないということです。 では、最低限どこまで実装すべきなのか では、すべてのWebアプリケーションに、ChatGPTのようなセッション管理画面が必要なのでしょうか。私は、そこまでは必要ないと思います。 例えば、セッションが短命で、機密情報を扱わず、ログイン状態も長期間維持しないような小規模なサービスであれば、セッション一覧画面まで実装する優先度は高くないかもしれません。一方、個人情報や業務情報を扱い、長期間ログイン状態を維持するWebアプリケーションであれば、少なくとも全セッション切断は用意しておきたいところです。 考えられる機能を整理すると、次のようになります。 機能 重要性 通常のログアウトでセッションを確実に失効 基本要件 セッションの有効期限管理 基本要件 アカウント停止・削除時の全セッション失効 基本要件 ユーザー自身による全セッション切断 強く推奨 パスワード変更・復旧時の既存セッション失効 強く推奨 管理者による強制切断 業務システムでは重要 セッション一覧・個別切断 リスクに応じて導入 失効操作前の再認証 高い保証水準では重要 ただし、これは実装上の優先順位を整理したものであり、OWASP ASVSの要求をそのまま分類した表ではありません。また、全セッション切断を設計するときには、いくつか注意すべき点があります。 まず、失効の対象を明確にすることです。 ブラウザのセッションだけなのか、Remember Meも含むのか、APIトークンやモバイルアプリの認証も含むのか。「すべての端末からログアウト」と表示しておきながら、実際には一部の認証経路が残っているなら、ユーザーに誤解を与えます。 次に、失効の即時性です。 セッションを削除しても、既に処理中のリクエストまで即座に停止できるとは限りません。認証バージョン方式などでは、次回の検証まで古いセッションが利用できる場合もあります。「全セッション切断」がどの時点で反映されるかは、認証方式によって異なります。 そして、全切断操作自体の保護です。 攻撃者が有効なセッションを持っている場合、攻撃者も全ログアウト操作を実行できる可能性があります。 全セッション切断などの重要操作には、セッションの存在だけに依存しない再認証が必要です。パスワード、パスキー、MFAなど、アプリケーションの認証方式に応じて実装します。 CSRF対策、操作頻度の制限、再認証、監査ログなどを、アプリケーションのリスクに応じて検討する必要があります。 おわりに:ログインを作るなら、追い出す方法も考えておきたい Webアプリケーションを開発するとき、ログイン機能は当然のように実装します。しかし、一度成立した認証を、本人や管理者がどう取り消すのかについては、意外と後回しになりがちですが、これは設計として少し不自然な気もします。認証情報が漏洩しないことを前提にするのではなく、漏洩する可能性を考え、その際に被害を止められる仕組みを用意する。セキュリティでは、ごく基本的な考え方でしょう。 全セッション切断は、そのための一つの手段です。 もちろん、全セッション切断があれば安全というわけではありません。認証情報の漏洩防止、MFA、適切な有効期限、再認証など、ほかの対策と組み合わせる必要があります。それでも、アカウントを侵害された可能性があるとき、ユーザーが自分で既存の認証状態を取り消せるかどうかは重要です。 LaravelやRailsなど、成熟したフレームワークには、そのための仕組みがかなり用意されています。しかし、実際にユーザーが使える機能にするには、アプリケーション側で処理を接続しなければなりません。反対に、独自実装のレガシーシステムでは、そのための基盤そのものが存在しないかもしれません。そう考えると、新規開発の段階でセッション失効の仕組みを考慮しておく意味は大きいと思います。 ログインできることだけでなく、必要になったら確実にログイン状態を取り消せること。 をWebアプリケーションの認証機能を設計するうえで、初期段階で考慮されるべきとは思います。

  2. The first of its kind: how one unbounded request body became a denial-of-service class across every major MCP SDK --- title: "The first of its kind: how one unbounded request body became a denial-of-service class across every major MCP SDK" published: true description: "In April 2026 I reported CVE-2026-39313. Six months later the same flaw had been found and patched in the official Python, Java, Go, Ruby, PHP and TypeScript MCP SDKs. Here is the full class, and why most scanners still cannot see the worst of it." tags: security, mcp, ai, devsecops --- The one-line version In April 2026 I reported CVE-2026-39313, a denial-of-service flaw in an MCP server framework. It was the first CVE of its kind: an unbounded HTTP request body, CWE-770, that lets a single unauthenticated request exhaust a Model Context Protocol server's memory and take it offline. Over the next six months the identical flaw was found and patched in at least nine more MCP projects, including the official Python, Java, Go, Ruby, PHP and TypeScript SDKs. A third-party analysis in July called it "a new vulnerability category." By October two of those CVEs sat in the SDKs that the whole ecosystem is built on, together serving close to half a billion downloads a month. This is the story of that class: how far it spread, who patched and who is still exposed, and why the two worst ones are effectively invisible to the scanners most teams rely on. Every claim below links to a primary source. What the bug actually is MCP servers speak over an HTTP transport: Streamable HTTP, Server-Sent Events, and OAuth routes. To handle a request, the server reads the request body into memory before it does anything else. The flaw is simple and brutal. The read loop has no size limit. It keeps appending chunks to a buffer until the client stops sending or the process dies. There is no authentication in front of it, because the body is read before any auth check runs. So an attacker who can reach the endpoint sends one large POST, or a slow endless stream, and the server allocates memory until it is killed by the OOM reaper. One request, one dead server, no credentials required. This is CWE-770, allocation of resources without limits. It is not exotic. That is exactly why it turned up everywhere. CVE-2026-39313: the first one The first public advisory of this class was in mcp-framework, a popular TypeScript framework for building MCP servers. In versions 0.2.21 and below, the readRequestBody() function in the HTTP transport concatenated body chunks into a string with no cap. The framework even had a maxMessageSize configuration value, but readRequestBody() never referenced it. The limit existed on paper and was never enforced in code. A single large POST to /mcp crashed the server. I reported it, it was fixed in 0.2.22, and the advisory published on 16 April 2026. - Advisory (GitHub, GHSA-353c-v8x9-v7c3): github.com/QuantGeekDev/mcp-framework/security/ad… - CVSS 4.0 8.7 (High), CWE-770 At the time it looked like one framework's mistake. It was not. It was not a bug. It was a pattern. Here is the timeline of the same unbounded-body denial-of-service turning up across the MCP ecosystem, as advisories and patches landed through 2026: - 16 April — mcp-framework, CVE-2026-39313 (the first). - April to June — Google's MCP Toolbox for Databases had the identical io.ReadAll with no limit, reported four days after my advisory and fixed in June. No advisory, no CVE. - July — the official Go SDK added a request-body cap, shipped as OOM protection in its release notes, with no advisory and no CVE. - 30 July — the Ruby SDK, CVE-2026-67432. A 512 MB POST grew a worker from 44 MB to 1.66 GB. Fixed with a 4 MiB default cap. - 19 August — the PHP SDK, CVE-2026-53965, the client-side version: an unbounded SSE buffer. The Java SDK shipped a matching client-side SSE fix the same day. - 16 September — rmcp, the Rust SDK, CVE-2026-63128. - 11 October — mcp-go, CVE-2026-108859. - 14 October — the official Python SDK, CVE-2026-109527, and the official Java SDK, CVE-2026-108395. Both credited to me among the reporters. - 20 and 27 October — the official TypeScript SDK, CVE-2026-111768 and a follow-up advisory. Nine-plus independent projects. The same root cause. The same fix every single time: a default body-size cap, almost always 4 MiB. In July an independent write-up looked at this and called CVE-2026-39313 the first documented denial-of-service against the MCP HTTP transport and "a new vulnerability category." That is the right framing. This was not a run of unrelated bugs. It was one design gap in how MCP transports read input, replicated across every language the protocol ships in. The two that carry the protocol Most of the class lived in frameworks and bindings. Two of them did not. They were in the reference SDKs that nearly every MCP deployment imports. CVE-2026-109527, the official Python SDK (mcp). In versions before 1.29.1, and in the 2.0 pre-releases through 2.0.1, the Streamable HTTP session manager, the SSE message endpoint, and the OAuth authorization-server routes all buffered complete request bodies with no maximum size. An unauthenticated remote client could send a large declared or streamed body that consumed several times its own size in process memory, and repeat it until the server died. - Advisory (GHSA-fmmv-w9g8-j3gc): github.com/modelcontextprotocol/python-sdk/securi… - Fixed in 1.29.1. CVSS 7.5 (High), CWE-770. - The mcp package serves over 235 million downloads a month on PyPI. CVE-2026-108395, the official Java SDK. Unbounded request-body reads in the mcp-core HTTP server transports, same class, same impact. - Advisory (GHSA-4x8c-5vv7-973f): github.com/modelcontextprotocol/java-sdk/security… - CVSS 7.5 (High), CWE-770. For scale: the official TypeScript SDK pulls around 257 million downloads a month, the Python SDK 235 million. When the flaw sits in the SDK rather than a single server, every server built on that SDK inherits it the moment it exposes an HTTP transport. Who patched, -> Red Hat rated CVE-2026-109527 Important, assessed 44 of its products, and issued three errata: - RHSA-2026:92510 (OpenShift AI 3.4), RHSA-2026:92666 and RHSA-2026:92667 (Satellite 6.19 and 6.18). - Of the 44 products assessed, 35 are affected, 6 not affected, 3 marked will-not-fix. - access.redhat.com Debian tracks the same CVE against python-mcp at severity grave, and at the time of writing the package in unstable is still unfixed. - bugs.debian.org Downstream products started bumping their pins through October: OpenMetadata merged its upgrades, Red Hat's Open Data Hub opened fix PRs, and several hundred automated "bump mcp" pull requests have landed across GitHub since the advisories went live. So the serious operators with security teams are moving. The question is everyone else. The specification still does not require this For all the patching, the root cause has never been closed at the design level. As of early November 2026 the MCP security best-practices document still contains no guidance on request-body size limits. Every SDK solved it independently, with its own default, because the specification never told them to. That is why the same fix had to be rediscovered six, seven, eight times over. The MCP server security guidance that does exist, including the National Security Agency and CISA information sheet on MCP, discusses resource-exhaustion denial of service as a general risk but points implementers at no concrete control for this. The one place that could stop the whole class at the design level still does not mention it. The blind spot: most scanners cannot see the worst two This is current as of 3 November 2026, and it may change the day the databases catch up. Check it yourself. CVE-2026-39313, the npm one, has a full global GitHub advisory. It is in OSV, it is in npm audit, and a scan of a vulnerable project flags it. The two SDK CVEs do not behave the same way. CVE-2026-109527 and CVE-2026-108395 exist only as repository-level advisories on the Python and Java SDK projects. They were never promoted into the global GitHub Advisory Database. The downstream effect is a chain of blindness: - They are absent from the global GitHub advisory mirror, so GitHub Dependabot does not alert on them. - They are absent from OSV, so osv-scanner and everything built on OSV misses them. Querying a vulnerable mcp version returns the other 2026 CVEs but not this one. - They have no record in the PyPA advisory database, so pip-audit finds nothing. - NVD lists both as "Awaiting Analysis" with no version data, so even NVD-driven scanners have no range to match on. The practical result: a server running a vulnerable mcp package can be scanned by pip-audit, osv-scanner, Dependabot, or a popular MCP-specific scanner that wraps pip-audit, and come back clean for the denial-of-service flaw. The patch shipped, the advisory was written, and the machine-readable plumbing that is supposed to warn people never carried it. The enterprise distribution trackers, Red Hat, Debian and SUSE, do carry it, because they ingest from their own CNA and NVD feeds. Red Hat has even published a machine-readable VEX file for it. But the developer-facing supply-chain tools that most teams actually run do not. If you depend on pip-audit or Dependabot to tell you about this, right now they will not. What an attacker gets, and who is at risk You are exposed if you run an MCP server that: - exposes an HTTP-based transport (Streamable HTTP or SSE), as opposed to stdio only, and - is reachable by any client you do not fully trust, which includes the public internet, a shared internal network, or a browser-reachable origin, and - runs a vulnerable version of the framework or SDK below. The attack needs no authentication, no credentials, and no user interaction. One oversized or endless request crashes the process. Repeat it and the service stays down. It is trivially scriptable. There is no data theft here, the impact is pure availability, but for an agent backend that other systems depend on, taking it offline on demand is the whole game. Stdio-only servers and deployments already sitting behind a reverse proxy with its own request-body limit are not exposed in the same way. That proxy limit is also your fastest mitigation while you patch. The fix Upgrade. The fixed versions: - mcp-framework (npm): 0.2.22 or later. - MCP Python SDK (mcp on PyPI): 1.29.1 or later. The fix adds max_request_body_size with a DEFAULT_MAX_REQUEST_BODY_SIZE of 4 MiB in the transport security layer. - MCP Java SDK: the patched mcp-core release. - MCP Go SDK: v1.7.0 or later, which enforces DefaultMaxRequestBodyBytes of 4 MiB. - Ruby SDK (mcp gem): 0.23.0 or later. - PHP SDK, Rust rmcp, mcp-go, TypeScript SDK: upgrade to the latest; all shipped the same body-size cap through the autumn. If you cannot upgrade immediately, put a reverse proxy in front with a client body limit (for example nginx client_max_body_size), and make sure your HTTP transport is not reachable from untrusted networks. Where your SDK exposes a configurable limit, set it explicitly rather than trusting the default, especially if you legitimately handle large payloads. How to find it in your estate - Inventory every MCP server you run and whether it exposes an HTTP transport or stdio only. - For Python, do not trust pip-audit alone for this one today. Check the installed mcp version directly: anything below 1.29.1 is vulnerable. - For npm, npm audit will catch mcp-framework below 0.2.22. - For Java and Go, check the SDK version against the fixed releases above, because the advisories are not yet in the global databases your SCA tooling reads. - Grep your own HTTP handlers for the pattern itself: a body read with no length cap, io.ReadAll(r.Body) in Go, request.body.read with no bound in Ruby, a string += chunk loop in Node, before any size check. If you wrote a custom transport, you may have reproduced the class yourself. The lesson The MCP ecosystem grew faster than its security guidance. A single gap in how transports read input became a denial-of-service class that reached every major SDK in the protocol, and the one control that prevents it is still not written into the specification. The fixes exist now. The specification guidance still does not. And for the two CVEs in the core SDKs, the automated warning system that the rest of us depend on is, as of today, silent. If you run MCP in production, do not wait for a scanner to tell you. Check the versions yourself. References - CVE-2026-39313, mcp-framework: github.com/QuantGeekDev/mcp-framework/security/ad… - CVE-2026-109527, MCP Python SDK: github.com/modelcontextprotocol/python-sdk/securi… - CVE-2026-108395, MCP Java SDK: github.com/modelcontextprotocol/java-sdk/security… - Red Hat, CVE-2026-109527: access.redhat.com - Debian tracker (grave), python-mcp: bugs.debian.org - OWASP AISVS, MCP transport payload-size control citing CVE-2026-39313: github.com/OWASP/AISVS/blob/main/1.0/research/cha… --- Raza Sharif, CyberSecAI Ltd. Reported CVE-2026-39313 and is credited on CVE-2026-109527 and CVE-2026-108395. All vulnerabilities were handled through coordinated disclosure and are fixed in the versions listed above. Contact: contact@agentsign.dev.

  3. Reddit · · r/pwnhub · u/_cybersecurity_ · OWASP/AISVS

    Auditing LLM Agents Against 214 OWASP AISVS Requirements: Rico Komenda and Jim Manico at Global AppSec USA 2026 OWASP's AI Security Verification Standard (AISVS) released version 1.01 on October 5, 2026, growing from 191 to 214 testable requirements, with most of the growth in its MCP security chapter. AISVS lists security requirements for applications built on LLMs, agents and retrieval-augmented generation (RAG). Writing "verify that" in a standard is easy, while checking it against a running AI system is not. In their Global AppSec USA 2026 workshop, "Hands-On AI Security Assessment with OWASP AISVS", on Friday, November 6 at 10:30 a.m. in Golden Gate, Rico Komenda and Jim Manico walk through practical assessment scenarios using the standard. Speakers: - Rico Komenda, Senior Product Security Engineer - Jim Manico, Founder, Manicode Security Participants work through real requirements from chapters on prompt injection defense, agentic action security, RAG and vector database hardening, as well as output safety controls. They learn to scope an AI security assessment and select a verification level. They then apply AISVS requirements to LLM-based applications, autonomous agents and MCP-connected tools, so a laptop is needed to follow along. AISVS has three levels. Level 1 is a baseline, Level 2 covers systems handling sensitive data or consequential decisions, and Level 3 is for high assurance. Version 1.01 includes requirements such as rejecting, rather than truncating, inputs that exceed token limits at Level 1. At Level 2, retrieved or tool content must never gain higher priority than the system's own instructions. The MCP security chapter grew from 23 requirements to 40 between versions. On October 20, 2026, the project deferred a planned 2.0 to focus on version 1.02. Rico Komenda is a Senior Product Security Engineer who works on the attack surface of AI-integrated systems. He co-leads AISVS with Jim Manico, Otto Sulin and Russ Memisyazici. Jim Manico founded Manicode Security, which trains developers in secure coding, and founded AISVS. He co-leads OWASP ASVS and wrote "Iron-Clad Java: Building Secure Web Applications." Both speakers also present the AISVS project showcase on Thursday at 10:30 a.m. in Seacliff CD. Komenda gives a talk on security chaos engineering for AI on Thursday at 1:45 p.m. The same team ran this workshop at Global AppSec EU 2026 in Vienna in June. The AISVS repository holds every released version, with requirement IDs that never get renumbered. To go deeper on the topic, start here: - ITSPmagazine podcast: Jim Manico on building AISVS (audio) - OWASP AISVS on GitHub (1.01 release and requirements) - OWASP AISVS project page - LRQA Cyber Labs: AISVS 1.0 chapter-by-chapter - VirtusLab: AISVS 1.0 requirement walkthrough Security testers asked to assess AI features without a defined test scope will practice building one from published requirements. Which AISVS verification level would your production AI features need to meet?

    2 points · 1 comment
  4. Reddit · · r/pwnhub · u/_cybersecurity_ · OWASP/Nettacker

    Recon, CVE Checks, Default-Credential Brute Forcing With 135 OWASP Nettacker Modules: Sam Stepanyan and Arkadii Yakovets at Global AppSec USA 2026 OWASP Nettacker, an open-source automated penetration testing framework written in Python, now ships 135 modules, 68 of which check for specific CVEs such as Log4Shell and Citrix Bleed. The name comes from "Network Attacker." Nettacker scans applications or networks, then reports on running services, bugs, vulnerabilities, misconfigurations and default credentials. It can chain different scan methods together. It has drawn interest from penetration testers in Europe and Asia. It is also included in a specialist Linux distribution for security researchers. In their Global AppSec USA 2026 project showcase, "Automated Security Testing with OWASP Nettacker", on Thursday, November 5 at 2:15 p.m. in Seacliff CD, Sam Stepanyan and Arkadii Yakovets run a live demo with practical examples of automated security testing. Speakers: - Sam Stepanyan, OWASP London Chapter Leader - Arkadii Yakovets, Cybersecurity Lead, OWASP Nest and OWASP Nettacker Nettacker's modules break down into 36 scan modules, 90 vulnerability checks and 9 brute-force modules. The brute-force modules test default or weak credentials over FTP, POP3, SMB, SMTP, SSH and Telnet, among others. The CVE checks cover recent targets such as Ivanti Connect Secure, Palo Alto PAN-OS, CrushFTP, Langflow and Next.js. Targets can be IP addresses, ranges, CIDR blocks, domains or URLs. Results come out as HTML, JSON, CSV or text reports. A built-in scan database detects drift between runs, so teams can use Nettacker in CI/CD to catch new exposures. Nettacker runs from the command line, a REST API or a web interface. It is released under the Apache 2.0 license, with version 0.4.1 published in August 2026. Sam Stepanyan is an independent application security consultant with more than 20 years in IT. He serves on the OWASP Global Board of Directors and has led the OWASP London Chapter since 2015. He is a project leader of Nettacker who has also contributed to the OWASP Top 10 and OWASP ZAP. He received the 2023 OWASP WASPY award for chapter leadership. He has presented Nettacker at Black Hat Europe Arsenal, Black Hat Asia, AppSec California and OWASP Global AppSec DC 2023. He has also consulted for City of London financial institutions on secure development and vulnerability management. Arkadii Yakovets joined OWASP in 2023, started contributing to Nettacker that year and became a co-leader. He also founded OWASP Nest, which he leads, as a platform for exploring OWASP projects, chapters and ways to contribute. He has mentored more than 10 Google Summer of Code students on OWASP and Python Software Foundation projects. He leads the open-source Python "holidays" library, which his board candidate page reports at more than 17 million monthly downloads. He holds CISSP, CCSP and CSSLP certifications. He co-presented Nettacker with Stepanyan at Global AppSec EU 2026 in Vienna. The Nettacker repository holds the full module list. The project documentation links recordings of past Nettacker talks going back to 2017. To go deeper on the topic, start here: - NDC Security 2026: Automated Security Testing with OWASP Nettacker (Sam Stepanyan, video) - The Application Security Podcast: Sam Stepanyan on the OWASP Nettacker Project - OWASP Nettacker on GitHub - Help Net Security: OWASP Nettacker open-source scanner - nettacker on PyPI Security teams looking for a free scanner they can run on a schedule against their own external footprint will see Nettacker set up end to end. How often does your team scan its own external footprint for default credentials and known CVEs?

    2 points · 1 comment
  5. Reddit · · r/pwnhub · u/_cybersecurity_ · OWASP/PIIHunter

    Finding Card Numbers Hiding in Your Postgres Columns or Jira Tickets: Nandan Gupta and Nayan Goel at Global AppSec USA 2026 OWASP PIIHunter scans PostgreSQL columns, Jira ticket comments and free-text notes fields for personally identifiable information that engineers rarely think to look for. Personally identifiable information (PII) includes Social Security numbers, card numbers, phone numbers and names. It often ends up in places no data inventory covers, such as a customer's card number pasted into a support ticket. PIIHunter detects it in three layers. Regular expressions with a Luhn checksum validate card numbers, Microsoft Presidio's machine learning recognizes named entities, and an optional self-hosted LLM handles ambiguous text. No data leaves the organization's perimeter during a scan. In their Global AppSec USA 2026 demo lab, "OWASP PIIHunter: AI-Powered PII Discovery in Databases and Jira", on Thursday, November 5 at 1:15 p.m. in Golden Gate, Nandan Gupta and Nayan Goel scan a real database alongside a live Jira instance. Speakers: - Nandan Gupta, Principal Application Security Engineer - Nayan Goel, Principal Application Security Engineer The demo surfaces SSNs, phone numbers and names from the database. It also catches a credit card number posted in a Jira ticket in real time. The PIIHunter repository shows how the scan stays contained. It connects to PostgreSQL through a read-only role, samples rows rather than reading every one, and stores results in a separate schema with redacted samples. Jira scanning works by polling or through real-time webhooks, which are checked with HMAC-SHA256 signatures. Every scan is written to an audit log. Nandan Gupta is a Principal Application Security Engineer at a fintech company, working on secure design, code review and threat modeling. He has presented at Black Hat Europe, the DEF CON AppSec Village and BSidesSF. He wrote PIIHunter's Jira integration, added in April 2026. Nayan Goel is a Principal Application Security Engineer at a fintech company and an AI security researcher, with more than seven years in application security. He wrote PIIHunter's first version in December 2025, then hardened it for its move to OWASP in October 2026. He created PromptInjector, a tool for testing AI systems for prompt injection that works with OpenAI, Anthropic or Ollama models. He contributes to the OWASP Agentic Security Guidelines. The two co-wrote GraphQL Security Tester, a Burp Suite Professional extension in PortSwigger's BApp Store. It uses Burp AI to generate GraphQL queries that test for SQL injection, authorization bypass, denial of service and information disclosure. To go deeper on the topic, start here: - OWASP PIIHunter source code - Microsoft Presidio documentation - GraphQL Security Tester by Nayan Goel and Nandan Gupta (BApp Store) - PromptInjector by Nayan Goel Privacy and security teams that have mapped PII in their main databases, but never in tickets or notes fields, will see what they may be missing. Has anyone at your company ever searched your Jira tickets for card numbers or Social Security numbers?

    2 points · 1 comment
  6. Reddit · · r/pwnhub · u/_cybersecurity_ · OWASP/ASVS

    Code Review Drills for Finding Bugs and Writing Fixes With OWASP ASVS 5.0: Eden Yardeni at Global AppSec USA 2026 The OWASP Application Security Verification Standard (ASVS) 5.0 contains about 350 security requirements across 17 chapters, and it was the standard's first major release since 2021. ASVS lists what a secure application must do, from input encoding to authentication to WebRTC. AppSec engineers can use those requirements to turn a code review finding into specific feedback a developer can act on. In her Global AppSec USA 2026 demo lab, "Life finds a way: Secure Coding with OWASP ASVS", on Thursday, November 5 at 1:15 p.m. in Golden Gate, Eden Yardeni runs guided code review exercises built on the standard. Speaker: Eden Yardeni, Senior AppSec Engineer Participants learn to identify security vulnerabilities in code, assess their impact and recommend fixes. The exercises cover vulnerabilities across a range of categories. Each exercise shows how to tie a finding to an ASVS requirement. That turns a vague "this is insecure" comment into feedback with a clear standard behind it. The lab needs nothing beyond a laptop with a browser. Eden Yardeni is a Senior AppSec Engineer who contributes to OWASP projects including ASVS. She worked as a full-stack developer before moving into security. She is listed in the working group for ASVS 5.0, alongside project leads Daniel Cuthbert, Elar Lang and Josh Grossman. Her work focuses on defining application security standards and putting them into practice across engineering teams. At SecAppDev 2026 in June, she taught "What's New in ASVS v5," an advanced lecture with code review demos on OAuth, WebSockets and race conditions. That lecture covers the main changes in version 5. Requirements are rewritten as verifiable properties, levels are rebalanced around risk, and CWE mappings give way to OpenCRE, a resource that links security standards to one another. Her lecture slides are published. The full standard, with a mapping back to version 4.0, is in the ASVS repository. To go deeper on the topic, start here: - What's New in ASVS v5, SecAppDev 2026 session page - What's New in ASVS v5 slides (Eden Yardeni) - OWASP ASVS 5.0 on GitHub - OWASP ASVS project page Developers and reviewers who want their code review comments backed by a standard will get practice doing exactly that. Do your code review comments cite a specific security requirement, or just say something is insecure?

    2 points · 1 comment
  7. Reddit · · r/pwnhub · u/_cybersecurity_ · OWASP/DockSec

    From 200 Container CVEs to the Few Dockerfile Lines Worth Fixing: Advait Patel at Global AppSec USA 2026 A container image scan typically returns more than 200 CVEs, most of them noise, with no indication of which few Dockerfile lines a developer should change. According to Advait Patel's session description, those reports get ignored. Someone spends half a day looking up each CVE, then files the rest as accepted risk. OWASP DockSec, which Patel created, sits on top of existing scanners rather than replacing them. It runs Trivy, Hadolint and Docker Scout locally. An LLM then correlates the results, removes duplicates, then ranks what matters for the specific setup. In his Global AppSec USA 2026 demo lab, "DockSec: Closing the Gap Between What Your Scanner Finds and What You Actually Fix", on Thursday, November 5 at 10:30 a.m. in Golden Gate, Advait Patel runs real Dockerfiles through the tool live. Speaker: Advait Patel, Senior Site Reliability Engineer, Broadcom The demo includes Dockerfiles that pass standard scanning clean. For each issue DockSec surfaces, it gives a plain-English explanation along with the exact line-level fix. DockSec produces a 0 to 100 security score for tracking posture over time. It exports HTML, PDF, JSON, CSV or Markdown reports, so security and development teams share one artifact. Only scan metadata leaves the machine; image contents never do. DockSec works with OpenAI, Anthropic or Google Gemini models, or fully locally through Ollama with no API key, and it runs in CI/CD on every build. Attendees can bring their own Dockerfiles. Patel also gives a 30-minute DockSec project showcase on Thursday at 2:45 p.m. in Seacliff CD. Advait Patel is a Senior Site Reliability Engineer at Broadcom in Chicago and a Docker Captain. He has more than eight years of experience in cloud-native architecture, container security and DevSecOps. He is a Google Developer Expert for Google Cloud and AI. He is a founding member of the OWASP AI Vulnerability Scoring System (AIVSS) project. He has co-authored two Springer books on Google Cloud security, along with Cloud Security Alliance guidance on securing LLM workloads. His speaking credits include QCon AI Boston, SANS CloudSecNext, OWASP SnowFROC, PlatformCon and the Linux Security Summit North America. The OWASP DockSec project page shows it reached OWASP Lab status in June 2026, with Arkadii Yakovets as co-leader. It also outputs SARIF and CycloneDX SBOM files. Secrets are redacted before any content reaches an AI provider. SC World reported about 17,000 PyPI downloads. It also described one startup that cut production CVEs by 78 percent, from about 22 to about 5 per month, while triage time per image fell from about 45 minutes to about 6. To go deeper on the topic, start here: - ISACA Podcast: Your Containers Are Probably Full of Holes: Fixing Docker Security with AI (Advait Patel) - OWASP/DockSec on GitHub - Help Net Security interview with Advait Patel on DockSec - SC World: DockSec adoption and triage-time results - docksec on PyPI Platform engineers who own container images, and who are tired of untriaged scanner output, are the audience for this demo. How many open container CVEs does your team currently carry as accepted risk?

    3 points · 1 comment
  8. That the American Osteopathic College of Radiology [aocr.org](aocr.org) have such an incredible interest in our main Cornucopia repository (owasp/cornucopia) on Github is a mystery to me. Does anyone care to elaborate? #appsec #security #osint

  9. When GitHub Went Dark: How OWASP BLT Found a New Home 50+ repositories went offline in the middle of Google Summer of Code. Here's how our community kept moving, and how an unexpected project became our new home. This one is a bit of a rollercoaster, so buckle up. 🎢 The calm before the storm It was the middle of Google Summer of Code (GSoC). OWASP BLT (Bug Logging Tool) had more than 50 repositories under a single GitHub organization. We had everything from the core application to Slack bots, a browser extension, a hackathon platform, a GSoC tracker, and a long list of tools built and maintained by our contributors. Things were moving along nicely. Mentors were reviewing. Contributors were shipping. Leaderboards were updating. The usual open-source chaos, but the good kind. Then we decided to do some housekeeping. Good security hygiene, right? We applied an organization-wide GitHub ruleset to enforce consistent repository protections across all our projects. A security-focused project enforcing security rules on its own organization. What could possibly go wrong? The morning after: everything was gone We woke up to find our GitHub repositories offline. All 50+ of them. And here's where things got confusing. At almost exactly the same time, GitHub itself was experiencing an outage. So for several hours, we genuinely had no idea what was happening. Was it our new ruleset? Was something wrong with the BLT organization? Was it GitHub's outage? Or was the timing just a coincidence? We contacted GitHub support. Then we followed up. And followed up again. Days passed, and we never received a clear explanation for what had happened to our organization. Mostly, we got silence. Meanwhile, Google Summer of Code wasn't going to pause for us. Contributors had active branches. Mentors had pull requests waiting for review. Projects had deadlines. When developers can't clone repositories or open pull requests, that's more than an inconvenience. It brings development to a halt. We needed another option. Plan B: moving to GitLab Rather than keep waiting for answers, we moved our repositories to GitLab. We pushed the code, redirected contributors to the new location, and worked on getting everything running again. Repositories were accessible. CI pipelines were migrated where possible. Contributors could get back to work. It wasn't the migration we'd planned. Actually, we hadn't planned a migration at all. But the community adapted, and development continued. We still wanted our original GitHub organization restored, of course. We kept reaching out to GitHub over the following months. Unfortunately, we still didn't get a clear answer. An unexpected plot twist: Kaif built a Git forge Here's where the story gets interesting. Some time later, we learned that one of our community members, Kaif, had built something of his own. While we had been dealing with the fallout of losing access to our GitHub organization, Kaif had turned the situation into a project. He built ForkMesh, a self-hosted Git forge. Think of it as having your own GitHub-like platform, with: - Git repositories and code hosting - Issues and pull requests - Actions-style CI/CD workflows - Support for AI agents as first-class collaborators - The ability to run your own instance The funny part? We hadn't set out to build or commission our own Git hosting platform. We had moved to GitLab to keep things going, and later discovered that someone in our community had built an entirely different option. So we gave ForkMesh a try. And it stuck. From 50+ repositories to one home Today, OWASP BLT has a very different setup. Our official source of truth is now git.owaspblt.org, running on ForkMesh. And we took the opportunity to do something we'd wanted to do for a while: consolidate our projects. <escape>###</escape> One repository, all our history Instead of maintaining 50+ separate repositories, BLT projects now live together in one repository, organized into their own folders. We preserved their commit histories along the way. That means: - 45,000+ commits preserved - 260+ contributors represented - Projects organized in one place - One central home for issues, contributions, and development That's a lot of community history, and we wanted to make sure it came with us. <escape>###</escape> GitHub is now our mirror Yes, you read that correctly. GitHub went from being our primary home to being our backup. Our repository at OWASP/BLT is now a read-only mirror, automatically synchronized from our forge. The source of truth is the forge we host. Funny how things turn around. <escape>###</escape> GitLab is archived, not forgotten We didn't just abandon our temporary GitLab home. Every open merge request was reviewed. Contributions worth bringing forward were merged into the new repository, with the original authors credited. Other merge requests were closed with explanations. Open issues were migrated to the forge, with references back to their original locations. The GitLab repositories remain archived so old links and project history are still accessible. <escape>###</escape> A little cleanup along the way We also used the migration as an opportunity to clean up some technical debt. For example, scheduled data jobs now write to Cloudflare storage instead of filling the Git history with automated bot commits. A bunch of little improvements that might not have happened otherwise. Sometimes an unexpected migration gives you a good excuse to fix things you've been putting off. What this taught us There are a few lessons we're taking away from the experience. 1. Don't put all your eggs in one platform GitHub is an important part of the open-source ecosystem, but relying entirely on one platform introduces risks. Your source code, issues, contributions, and project history represent years of community effort. Having a backup is inexpensive. Losing access without an explanation can be extremely costly. We now have much more control over where our work lives. 2. Test organization-wide changes on a smaller scope first We still don't know exactly what caused our GitHub organization to become unavailable. It would be unfair to claim the ruleset was responsible without confirmation. But we learned something important regardless. When making changes that affect more than 50 repositories, start small. Test the behavior, understand the impact, and expand gradually. Because when a large change goes wrong, the consequences can be just as large. 3. Open-source communities are remarkably resilient This is probably the biggest takeaway. What kept BLT going wasn't a particular platform. It was the people. Contributors continued working. Mentors kept supporting students. The community found alternatives. And one community member went a step further and built a Git forge that eventually became our new home. That's the part of open source we love most: people turning problems into opportunities to build something useful. Come build with us 🐝 If you already contribute to OWASP BLT, or you've been thinking about getting started, our new forge is where the action happens. 👉 Explore the OWASP BLT repository You can browse the projects, clone the repository, open issues, submit pull requests, and help us improve both BLT and the contributor experience. We're still learning what works best with our new setup, and we'd genuinely appreciate feedback. One more thing: we have a world 🌍 Because apparently moving 50+ repositories wasn't adventurous enough, there's also something fun to explore. The forge comes with its own virtual world. OWASP BLT has its own hex, complete with: - A bug terrarium filled with websites that people have reported bugs on. You can walk inside through the door. - A Hacker House you can enter and explore. - A road connecting the BLT world to the neighboring ForkMesh world. It's a playful little addition to what started as a pretty frustrating situation. 👉 Take a walk around the BLT World --- We started with more than 50 GitHub repositories, lost access to them in the middle of GSoC, moved to GitLab to keep development going, and eventually found a new home thanks to something a community member built. Not exactly the infrastructure roadmap we'd imagined. But here we are: 45,000+ commits, 260+ contributors, one forge, and a community still building. See you on the forge. 🐝

    18 reactions
  10. AI Security Testing 101: Prompt Injection and Indirect Prompt Injection This is the first post in a new series on AI application security testing, following the structure of the OWASP AI Testing Guide's AI Application Testing category (AITG-APP). Each post in the series will take one test from that category and turn it into something practical: what the vulnerability actually looks like, how testers approach it, and what "vulnerable" means in concrete terms. We're starting where the guide starts: prompt injection, one of the most well-known AI application vulnerabilities, and a class of attack that can underpin many other AI-specific security risks. --- Direct Prompt Injection (AITG-APP-01) Prompt injection happens when attacker-controlled input changes an AI application's behavior in a way that conflicts with its intended instructions or security constraints. The input may attempt to make the model ignore higher-priority instructions, reveal information it should not disclose, or perform an action it was not intended to perform. A useful, though imperfect, analogy is SQL injection: in both cases, attacker-controlled input can influence behavior that the application intended to control. The analogy has limits, however. SQL injection exploits the interpretation of data as executable syntax, while prompt injection arises from the way language models process natural-language instructions and contextual information. The AITG-APP-01 methodology characterizes a prompt injection in terms of three elements: - Instructions: what the attacker actually wants the model to do. - A trigger: the specific phrasing, framing, or encoding intended to cause the model to follow the attacker's instructions rather than its intended behavior. - Conflict with intent: the injected request conflicts with the application's intended instructions or constraints. Without that conflict, an unusual or adversarial-looking prompt may simply be a normal request rather than a security-relevant prompt injection. Prompt injection is also broader than jailbreaking. A jailbreak attempts to bypass safety restrictions, while prompt injection more generally involves attacker-controlled input changing model behavior in an unintended way. An injection can therefore be security-relevant even when it does not produce prohibited content. Whether an attack succeeds can depend heavily on how the trigger is constructed. That's one reason simple keyword filtering is insufficient on its own. Blocking the phrase "ignore previous instructions" does little against the same underlying idea expressed through role-play, another language, obfuscation, or an encoded representation. Attack Patterns Worth Knowing The OWASP guide catalogs a broad set of concrete payload techniques. They can be grouped into a handful of practical patterns: Persona and role-play framing Asking the model to "pretend" to be an unrestricted persona so that it treats otherwise disallowed behavior as being in character. A well-known example is the "DAN" jailbreak. The underlying technique is not limited to DAN. Attackers can construct fictional characters, simulated environments, alternate roles, or hypothetical scenarios intended to change how the model interprets its constraints. Context manipulation Telling the model to "forget" previous instructions, attempting to override higher-priority context, or gradually steering the conversation toward a prohibited behavior. This can include multi-turn approaches in which no individual request appears particularly harmful, but the sequence gradually changes the context presented to the model. "Crescendo" and "echo chamber" style attacks are examples of this broader pattern. Obfuscation and encoding Hiding or transforming the attack instruction using techniques such as base64, hexadecimal encoding, reversed text, unusual capitalization, deliberate typos, Unicode manipulation, or other transformations. The purpose is often to evade filters or exploit differences between what a security control recognizes and what the model can interpret. The important lesson is that filtering for a fixed set of phrases is not a sufficient defense against a language-based attack surface. Structural tricks Taking advantage of how the application or model handles structured inputs, including JSON or other formats, multi-message inputs, or instructions embedded within content that the application expects the model to process. Structured formats can create additional attack surfaces when applications treat model-generated or model-consumed fields as trusted simply because they conform to an expected schema. Contradiction and instruction-conflict framing Presenting multiple competing instructions or asking the model to produce both a normal response and an explicitly contrary response, with the goal of getting it to produce the latter. The exact payloads are less important than the general testing principle: don't assume that one known jailbreak or injection string represents the entire attack surface. These techniques are not permanent. Models, applications, and defenses evolve, so a payload that works against one model or configuration may become ineffective against another. That's why testing should combine techniques and repeat requests rather than relying on a single known payload. Response variability can also matter. In configurations where sampling introduces variability, the same prompt may produce different results across attempts. --- What Makes a Test Environment Different Before running tests against a real target, it's worth understanding what's actually in front of you. The architecture and model configuration can significantly affect which techniques are relevant and how the results should be interpreted. Temperature Lower temperature generally makes output more repeatable, while higher temperature generally increases variability and diversity. That matters during testing because a payload that succeeds once may not succeed consistently. Testers should therefore repeat relevant requests and record the configuration used rather than treating a single successful or unsuccessful attempt as definitive. Temperature does not by itself determine whether a system is secure, and a temperature of zero should not be treated as a universal guarantee of deterministic behavior. Fine-tuning vs. prompt tuning Safety and behavioral constraints can be implemented at different layers, including through model training or fine-tuning and through application-level instructions or other steering mechanisms. This distinction matters during testing because a successful bypass may target different layers of the system. A test might circumvent application-level instructions without demonstrating that the underlying model has changed, for example. The important question for a tester is therefore not just "did the model comply?" but also "which security control was bypassed?" Guardrails Guardrails can be implemented in several ways, including deterministic rules, classifiers, access controls, schema validation, filtering systems, or additional LLM-based checks. When an application uses an LLM as part of its guardrail system, that introduces another model and potentially another source of variability. Testers should evaluate the guardrail as part of the attack surface rather than assuming that adding another model automatically prevents prompt injection. Multi-agent setups When several agents hand work to each other, testers may only see the final output rather than the intermediate prompts, tool calls, and responses. That makes it harder to determine which agent or handoff an injection actually influenced. Testing therefore benefits from observability into agent-to-agent messages, tool calls, retrieved content, and intermediate decisions wherever possible. Tool access A model wired up to scripts, shells, databases, or external APIs can turn a successful injection from unwanted model output into an unauthorized action. Tool access can therefore substantially increase the potential impact of a prompt injection. However, tool access is not required for an injection to have security impact: unauthorized information disclosure or manipulation of important outputs can also be significant. --- Indirect Prompt Injection (AITG-APP-02) Direct injection assumes the attacker is the one providing the malicious input to the AI application. Indirect prompt injection works differently. The malicious instruction is planted somewhere the AI application will process as external content: a web page, PDF, email, uploaded document, database record, search result, or tool-related content. The model may then encounter that instruction as part of the context it receives. The important distinction is not that the model has literally "no way" to distinguish data from instructions. Rather, the model may fail to reliably distinguish untrusted external content from instructions when both are represented in the context it processes. That creates a different attack surface: the attacker may not need direct access to the AI application if they can influence content that the application will eventually retrieve or process. Indirect injection can be particularly concerning in applications that automatically retrieve external content, have access to sensitive information, or can take actions through tools. Concrete Surfaces This Shows Up On Hidden text in web pages or documents An attacker can place instructions in content that is difficult for a human reviewer to notice, such as HTML comments, invisible or visually obscured text, document metadata, or other content that is nevertheless extracted and passed to the model. The important security property is not that the text is literally invisible. It's that the application may process content that the user did not realize would be interpreted by the model. Structured data fields A JSON, XML, database record, API response, or other structured input may contain an attacker-controlled field whose value includes an instruction rather than the data the application expected. For example, a field intended to contain a document summary or description might contain language such as an instruction to ignore the application's task and perform another action. The fact that the content is valid JSON or XML does not make it trustworthy. Markdown-based exfiltration An indirect prompt injection can attempt to make the model include sensitive information in a URL or other externally observable location, including by generating a Markdown image reference or link containing attacker-controlled data. If the resulting content is rendered or fetched by a downstream component, this can create a data-exfiltration path. A related technique was demonstrated in the real-world EchoLeak vulnerability affecting Microsoft 365 Copilot. EchoLeak was a multi-stage attack involving indirect prompt injection and data exfiltration under particular conditions; it should not be treated as synonymous with every Markdown-based exfiltration technique. Encoded payloads External content can also contain encoded or otherwise obfuscated instructions. The same general filter-evasion issues that apply to direct prompt injection can therefore apply to indirect injection. Tool metadata and tool poisoning For AI systems using MCP or similar tool-calling protocols, tool names, descriptions, schemas, metadata, parameters, and outputs can become part of the model's context. In some client implementations, this information may not be prominently exposed to the user even though it is presented to the model. An attacker who can control a tool's metadata may therefore attempt to embed instructions into it, for example, instructions telling the model to retrieve information before using the tool. The security issue is not specific to one metadata field. The broader concern is that the model may treat untrusted tool-related content as instructions. The common thread is this: > Anywhere external content reaches the model without a reliable boundary between trusted instructions and untrusted data, there is a potential prompt-injection attack surface. That boundary is an architectural concern, not merely a question of finding the right payload string. --- What Counts as a Finding For both tests, a prompt injection becomes a security finding when attacker-controlled instructions cause behavior that violates the application's intended constraints or security boundaries. Examples include: - The model overrides or circumvents intended instructions in a security-relevant way. - The application discloses information that the model or user should not have access to, such as credentials, API keys, internal configuration, or another user's data. - The model or connected system performs an unauthorized or harmful action. - An indirect injection causes the application to treat attacker-controlled external content as an instruction and subsequently produce unauthorized disclosure or action. For indirect injection specifically, the distinguishing condition is that the security-relevant behavior originates in externally supplied content rather than the user's direct prompt. Simply following an instruction found in external content is not automatically a vulnerability. For example, if a webpage contains ordinary instructions that are relevant to the user's request and the model follows them as part of legitimately processing that page, there may be no security issue. The important question is whether attacker-controlled external content can change the application's behavior in a way that violates its intended security or operational constraints. --- Remediation, in Short Both tests point toward several overlapping defensive principles. Separate trusted instructions from untrusted content Clearly distinguish system/application instructions from user input and external data. Delimiters and structured context can help the model distinguish these sources, but they should be treated as mitigations rather than a guarantee that prompt injection will never succeed. Treat external content as untrusted Validate and sanitize external content before it reaches the model where appropriate. Consider hidden text, encoded instructions, unusual Unicode, metadata, and other forms of content that a human reviewer may not recognize as instructions. But don't rely on sanitization alone. Natural language is too flexible to make exhaustive filtering a reliable security boundary. Restrict model privileges Give the model only the access and capabilities it actually needs. If a model does not need access to credentials, private files, sensitive databases, or administrative functions, those capabilities should not be available to it merely because the model might request them. Authorization should be enforced outside the model wherever possible. Require approval for high-impact actions Sensitive, high-impact, or irreversible actions should require appropriate authorization or human approval rather than relying entirely on the model to decide whether an action is safe. The model should not be the sole security boundary protecting a privileged operation. Treat tool metadata as untrusted input Tool descriptions, schemas, metadata, parameters, and outputs should be treated as potentially untrusted content. Applications should avoid assuming that a tool definition is safe simply because it was supplied through an otherwise trusted tool-calling protocol. Add monitoring and observability Where practical, log and monitor retrieved content, model inputs, tool calls, authorization decisions, and significant outputs. This is particularly important in multi-agent systems, where a prompt injection may enter through one component and only become visible much later in the execution chain. --- Tools for Testing This Several tools can help automate or structure prompt-injection testing: - Garak: includes probes relevant to prompt injection and other LLM security testing. - Promptfoo: provides adversarial testing and evaluation capabilities for LLM applications, including prompt-injection testing. - Prompt Security Fuzz (ps-fuzz): a fuzzer focused on prompt-level attacks. Tools are useful for generating and repeating attacks, but they should complement application-specific testing. A generic payload that causes an unusual model response is not necessarily a vulnerability; the tester still needs to establish what security boundary was crossed and what the resulting impact is. --- What's Next in This Series This post covered the two prompt-manipulation tests. Coming up: - AITG-APP-03 / 04 / 07 — sensitive data leaks, input leakage, and system prompt disclosure - AITG-APP-05 / 10 / 11 / 12 — unsafe outputs, harmful-content bias, hallucinations, and toxic output - AITG-APP-06 / 13 — agentic behavior limits and over-reliance on AI - AITG-APP-08 / 09 — embedding manipulation and model extraction - AITG-APP-14 — explainability and interpretability --- Official Resources - AITG-APP-01: Testing for Prompt Injection - AITG-APP-02: Testing for Indirect Prompt Injection - OWASP Top 10 for LLM Applications — LLM01: Prompt Injection --- Final Thoughts Prompt injection isn't a vulnerability that can necessarily be "patched once." It is a recurring security problem for systems that allow language models to process instructions alongside user-controlled or externally sourced content. Direct injection tests what happens when a user actively attempts to change the application's behavior. Indirect injection tests whether attacker-controlled external content can influence the system even when the attacker never interacts with the AI interface directly. The important security question is therefore broader than: > "Can I make the model ignore its system prompt?" A useful test asks: > "Can attacker-controlled input or external content cause the application to violate an intended security or operational constraint?" That framing also makes the impact easier to assess. A successful jailbreak that produces harmless text is different from an injection that exposes confidential information, bypasses authorization, or causes a connected system to perform an unauthorized action. Prompt injection techniques will continue to evolve as models, applications, and defenses change. Effective testing therefore needs to combine different attack patterns, repeat tests under representative configurations, and most importantly evaluate the actual security boundaries around the model rather than treating the model itself as the only control.

    2 reactions · 1 comment

Achievements

Awards earned by the repositories owasp owns. Select an award to embed its badge.

Gold
11st place finishes
Silver
22nd place finishes
Bronze
13rd place finishes
Awarded repositories
1Owned by owasp now

Repositories

Ordered by gold, then silver, then bronze.

  1. owasp-summit-2017Best: 1st by PR authors, 43 PR authors121

Every award

Top-three finishes of these repositories in completed trending days and weeks, newest first.

  1. owasp-summit-2017
  2. owasp-summit-2017
  3. owasp-summit-2017
  4. owasp-summit-2017

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.