タグアーカイブ Rust

Astro 6.4リリース。プラグ可能なMarkdownパイプラインとRust製プロセッサーSätteriが登場

Astro 6.4リリース。プラグ可能なMarkdownパイプラインとRust製プロセッサーSätteriが登場

Astro 6.4が2026年5月28日にリリースされた。Markdown処理パイプラインを自由に差し替え可能にする新API「markdown.processor」、Rustで書かれた高速MarkdownプロセッサーSätteriの試験的導入、そしてCloudflare環境向けのルーティングヘルパーが追加された。

これまでの設定方法は非推奨となり、将来的なAstro 8.0では完全に廃止される予定だ。今回のアップデートで、静的サイト構築におけるMarkdown処理の柔軟性とパフォーマンスが大幅に向上する。

プラグ可能なMarkdownプロセッサーAPI

プラグ可能なMarkdownプロセッサーAPI

AstroのMarkdownパイプラインはこれまで、unified(remark/rehype)エコシステムを中心に構築されてきた。強力で数千ものプラグインが利用できる一方、特定のプロジェクトの要求に合わない場合もあった。今回追加されたmarkdown.processor設定オプションでは、そのパイプライン全体を丸ごと差し替えられる。

設定の変更方法

デフォルトのプロセッサーは従来通りunified()が使われるため、既存プロジェクトは何も変更せずにそのまま動き続ける。remark/rehypeプラグインも同じ挙動を保つが、設定場所がトップレベルのmarkdownからプロセッサー内に移行した。

import { defineConfig } from 'astro/config';
import { unified } from '@astrojs/markdown-remark';
import remarkToc from 'remark-toc';

export default defineConfig({
  markdown: {
    processor: unified({
      remarkPlugins: [remarkToc],
    }),
  },
});
従来の設定 (Before)
import { defineConfig } from ‘astro/config’; import remarkToc from ‘remark-toc’; export default defineConfig({ markdown: { remarkPlugins: [remarkToc], }, });
新APIでの設定 (After)
import { defineConfig } from ‘astro/config’; import { unified } from ‘@astrojs/markdown-remark’; import remarkToc from ‘remark-toc’; export default defineConfig({ markdown: { processor: unified({ remarkPlugins: [remarkToc], }), }, });

従来のトップレベルオプション(markdown.remarkPlugins, markdown.rehypePlugins, markdown.remarkRehype, markdown.gfm, markdown.smartypants)も引き続き動作するが非推奨となり、Astro 8.0で完全に削除される予定だ。

移行の注意点

既存プロジェクトの移行は比較的簡単だ。unified({...})内にプラグインをまとめて記述するだけでよい。ただし、マークダウン処理をカスタマイズした複雑な設定を行っている場合は、コードの再構成が必要になる。公式ドキュメントのMarkdownガイドが更新されているため、詳細はそちらを参照してほしい。

Rust製MarkdownプロセッサーSätteri

Rust製MarkdownプロセッサーSätteri

プラグ可能なプロセッサーAPIの追加により、Astroは標準とは異なるMarkdownプロセッサーも同梱できるようになった。今回導入された@astrojs/markdown-satteriパッケージは、Rustで書かれた高速なMarkdown/MDXパイプライン「Sätteri」をベースにしている。

パフォーマンスの劇的な向上

Sätteriはデフォルトのunifiedベースのパイプラインよりも大幅に高速で、多くのMarkdown機能をプラグインなしでネイティブ実装している。Astroの公式ブログによれば、自社のドキュメントサイトをSätteriに切り替えたところ、ビルド時間が1分以上短縮されたという。

npm install @astrojs/markdown-satteri
import { defineConfig } from 'astro/config';
import { satteri } from '@astrojs/markdown-satteri';

export default defineConfig({
  markdown: {
    processor: satteri({
      features: { directive: true },
    }),
  },
});
従来のunifiedパイプライン
ビルド時間 約2分
※大規模ドキュメントサイトの例
Sätteri使用時
ビルド時間 約1分
約1分短縮。Rustネイティブの恩恵

この数値はあくまで一例だが、コンテンツ量の多いサイトでは特に効果が大きい。Rustで記述されているため、CPUバウンドな処理が高速化される仕組みだ。

プラグイン互換性と今後のデフォルト化

Sätteriはremark/rehypeプラグインを実行しない。unifiedエコシステムのプラグインに依存している場合は、当面unified()を使い続けるか、SätteriのMDAST/HASTプラグインに移植する必要がある。Astroチームは、将来のメジャーバージョンでSätteriをデフォルトのMarkdownプロセッサーにすることを目指している。

Rustプロセッサーや新APIに関するフィードバックは、公式のRFCDiscussionで受け付けている。興味がある開発者はぜひ参加してほしい。

Cloudflare向け高度ルーティングヘルパー

Cloudflare向け高度ルーティングヘルパー

Astro 6.3で導入された実験的な高度ルーティング機能をCloudflare環境で使いやすくするため、@astrojs/cloudflareパッケージにcf()ヘルパーが追加された。SESSION KVバインディングの注入、ASSETSバインディングによる静的アセット配信、クライアントIPアドレスやwaitUntilの処理など、Cloudflare特有の面倒な設定を一手に引き受ける。

Fetchハンドラでの利用

import { astro, FetchState } from 'astro/fetch';
import { cf } from '@astrojs/cloudflare/fetch';

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext) {
    const state = new FetchState(request);
    const asset = await cf(state, env, ctx);
    if (asset) return asset;
    return astro(state);
  },
};

Honoミドルウェアでの利用

import { Hono } from 'hono';
import { actions, middleware, pages, i18n } from 'astro/hono';
import { cf } from '@astrojs/cloudflare/hono';

const app = new Hono<{ Bindings: Env }>();
app.use(cf());
app.use(actions());
app.use(middleware());
app.use(pages());
app.use(i18n());

export default app;
Cloudflare Workersルーティングの簡略化フロー
cf() SESSION KV ASSETS配信 IPアドレス解決 waitUntil
開発者はcf()ミドルウェアを適用するだけで、Cloudflare固有の設定が自動注入される

このヘルパーにより、Cloudflare上で高度なルーティングを実装する際のボイラープレートコードが大幅に削減される。実験的機能ではあるが、実用段階に入りつつあると言えるだろう。

その他の改善とアップグレード手順

その他の改善とアップグレード手順

細かなバグ修正と今後のロードマップ

今回のリリースには、上記の主要機能以外にも多数のバグ修正と小さな改善が含まれている。詳細は公式の変更履歴を確認してほしい。また、Astroコアチームは活発に開発を続けており、コミュニティからのコントリビュートも盛んだ。

アップグレードの手順

既存のAstroプロジェクトをアップグレードするには、自動アップグレードツールを使うのが推奨だ。

# 推奨
npx @astrojs/upgrade

# 手動の場合
npm install astro@latest
pnpm upgrade astro --latest
yarn upgrade astro --latest

自動ツールは非推奨設定の移行などもサポートする。手動で行う場合は、設定ファイルの変更点を確認しながらアップデートしよう。

この記事のポイント

  • Markdown処理を差し替え可能にするmarkdown.processor APIが追加された
  • RustベースのSätteriプロセッサーによりビルド時間を大幅に短縮できる
  • Cloudflare向けcf()ヘルパーで高度ルーティングの設定が簡略化された
  • 従来の設定方法は非推奨となり、Astro 8.0で廃止予定。早めの移行が望ましい
  • アップグレードはnpx @astrojs/upgradeで簡単に行える
Pingora OSSの脆弱性とリクエストスマグリング対策——Cloudflareが修正した3つの欠陥

Pingora OSSの脆弱性とリクエストスマグリング対策——Cloudflareが修正した3つの欠陥

Cloudflareは2026年3月9日、オープンソースのプロキシフレームワーク「Pingora(ピンゴラ)」に複数の脆弱性が存在することを公表した。対象となるのはPingoraをイングレスプロキシとして独自にデプロイしている環境だ。修正版となるPingora 0.8.0が同日にリリースされている。

発見された脆弱性は、HTTP/1.xにおける「リクエストスマグリング」に関連するものが中心だ。これはプロキシサーバーとバックエンドサーバーの間で、リクエストの終端解釈が食い違うことで発生する。最悪の場合、セキュリティ制御の回避や他ユーザーのセッション奪取につながる恐れがある。

Cloudflareの調査によれば、同社のCDNサービスや顧客トラフィックへの影響は確認されていない。Pingoraは同社ネットワーク内で広く利用されているが、インターネットからの直接的なトラフィックを受けるイングレスプロキシとしては使用されていないためだ。しかし、Pingoraを独自に公開サーバーとして運用しているユーザーは、速やかなアップデートが求められる。

Pingora OSSで発見された3つの脆弱性とリクエストスマグリングの脅威

Pingora OSSで発見された3つの脆弱性とリクエストスマグリングの脅威

今回のアップデートで修正されたのは、CVE-2026-2833、CVE-2026-2835、CVE-2026-2836の3件だ。これらはいずれも、HTTP/1.xの通信においてリクエストの境界を誤認させる「リクエストスマグリング(Request Smuggling)」を可能にする欠陥である。

リクエストスマグリングとは何か

リクエストスマグリングとは、1つのTCP接続の中で複数のHTTPリクエストを送る際、サーバー間で「どこまでが1つ目のリクエストか」の認識がズレる攻撃手法だ。例えるなら、レストランの注文票で「ハンバーグ1つ。あと、隣のテーブルの会計を私につけて」と巧妙に書き込み、店員に2つの指示を1つとして誤認させるような行為に近い。

プロキシサーバーが「これは1つのリクエストだ」と判断して通したデータの中に、バックエンドサーバーだけが「これは2つ目のリクエストだ」と解釈するデータが含まれている場合に発生する。これにより、プロキシ側のセキュリティチェックを素通りした不正なリクエストが、バックエンドで実行されてしまう。

独自展開のPingoraに潜むリスク

PingoraはRustで書かれた高速なプロキシフレームワークであり、Nginxの代替として注目されている。しかし、今回の脆弱性は、Pingoraをインターネットの窓口(イングレスプロキシ)として直接配置している場合に牙をむく。

攻撃が成功すると、攻撃者はPingoraのアクセス制御(ACL)を回避したり、共有バックエンドから取得したキャッシュを汚染したりすることが可能になる。また、他人の通信に自分のリクエストを割り込ませる「デシンク(非同期)攻撃」により、他ユーザーの認証情報を盗み出すリスクも指摘されている。

脆弱性1:101レスポンスを待たない不適切なプロトコル移行

脆弱性1:101レスポンスを待たない不適切なプロトコル移行

1つ目の脆弱性(CVE-2026-2833)は、HTTPの「Upgrade」ヘッダーの処理に関するものだ。通常、WebSocketなどのプロトコルに切り替える際、クライアントはUpgradeヘッダーを送信し、サーバーが「101 Switching Protocols」を返した時点で切り替えが完了する。

Upgradeヘッダーの誤用によるバイパス

修正前のPingoraは、バックエンドからの「101」レスポンスを確認する前に、後続のデータを「アップグレード後のストリーム」としてそのまま流し込む(パススルーする)挙動を示していた。

GET / HTTP/1.1
Host: example.com
Upgrade: foo

GET /admin HTTP/1.1
Host: example.com

このコードのように、Upgradeリクエストの直後に別のリクエストを連結して送信すると、Pingoraは最初の部分だけを解析し、残りを「アップグレードされた通信」と見なしてバックエンドに丸投げする。たとえバックエンドがアップグレードを拒否して「200 OK」を返したとしても、Pingoraはすでに通信を素通しするモードに入ってしまっている。

バックエンドとの同期ずれ(Desync)の仕組み

この挙動により、プロキシとバックエンドの間で「Desync(デシンク / 同期ずれ)」が発生する。プロキシは1つの通信だと思っているが、バックエンドは「拒否したはずのアップグレードの後に、なぜか別のGETリクエストが届いた」と認識する。

結果として、プロキシ側のWebアプリケーションファイアウォール(WAF)や認証チェックを一切受けずに、`/admin` などの機密性の高いパスへのアクセスがバックエンドに到達してしまう。これは、検問を「工事車両です」と偽って通過し、ゲートが開いた瞬間に後ろに隠していた別の車を侵入させるような手口だ。

脆弱性2:HTTP/1.0とTransfer-Encodingの不適切な解釈

脆弱性2:HTTP/1.0とTransfer-Encodingの不適切な解釈

2つ目の脆弱性(CVE-2026-2835)は、古い規格であるHTTP/1.0のリクエストに「Transfer-Encoding: chunked」が含まれていた場合の処理に起因する。HTTP/1.0は本来、チャンク形式の転送をサポートしていない。

リクエストボディの終端判定ミス

Pingoraの従来のロジックでは、HTTP/1.0リクエストにTransfer-Encodingが含まれている場合、ボディの終端を「コネクションの切断(close-delimited)」で判断していた。しかし、最新のRFC(仕様書)では、リクエストボディにおいてコネクション切断を終端判定に使うことは明確に禁止されている。

攻撃者が以下のようなリクエストを送信した場合、問題が顕在化する。

GET / HTTP/1.0
Host: example.com
Connection: keep-alive
Transfer-Encoding: chunked
Content-Length: 29

0

GET /admin HTTP/1.1
X:

Pingoraはこれを「1つの長いボディを持つリクエスト」と誤認するが、バックエンド(Node.jsやuvicornなど)は「チャンク形式の終わり(0)」でリクエストが終了したと判断する。その結果、後ろに続く `/admin` へのリクエストが、次にそのコネクションを利用する別ユーザーのリクエストとして処理されてしまう。

RFC準拠の厳格化による修正

Cloudflareはこの問題に対し、PingoraのHTTP解析ロジックを大幅に強化した。具体的には、HTTP/1.0とTransfer-Encodingの組み合わせを拒否し、無効なContent-Lengthを持つリクエストも遮断するように変更されている。

RFC(Request for Comments)とはインターネット技術の標準仕様書であり、これに厳格に従うことがセキュリティの基本となる。Pingoraはこれまで、レガシーなシステムとの互換性のために一部の仕様を緩く解釈していたが、今回の修正で「安全な厳格さ」へと舵を切った形だ。

脆弱性3:デフォルトCacheKeyによるキャッシュ汚染のリスク

脆弱性3:デフォルトCacheKeyによるキャッシュ汚染のリスク

3つ目の脆弱性(CVE-2026-2836)は、Pingoraのアルファ版機能である「プロキシキャッシュ」のデフォルト設定に関するものだ。キャッシュの識別子となる「CacheKey(キャッシュキー)」の生成ロジックが不十分であった。

URIパスのみに依存するキャッシュキーの危険性

修正前のデフォルト実装では、キャッシュキーの生成に「URIパス」のみを使用していた。ここにはホスト名(Hostヘッダー)や通信プロトコル(HTTPかHTTPSか)が含まれていなかった。

これにより、例えば `site-a.com/index.html` と `site-b.com/index.html` が、同じキャッシュとして扱われてしまう。攻撃者が自分の管理するドメインで不正なコンテンツをキャッシュさせれば、同じサーバーを共有する全く別ドメインの利用者にその不正コンテンツを表示させることが可能になる。

現在、Pingoraはこの「不完全なデフォルト設定」自体を削除している。利用者は自身のアプリケーションの特性に合わせ、ホスト名やスキームを含めた適切なキャッシュキーを明示的に設計する必要がある。

独自の分析:Rust製プロキシにおけるRFC準拠と「寛容さ」のトレードオフ

独自の分析:Rust製プロキシにおけるRFC準拠と「寛容さ」のトレードオフ

今回の脆弱性公表は、Rustというメモリ安全な言語で開発されていても、プロトコルの解釈という論理的なレイヤーでの脆弱性は避けられないことを改めて示した。PingoraはCloudflareが数千台のサーバーで運用する実績あるコードだが、それでもなお、リクエストスマグリングのような古典的な攻撃手法が有効な隙間が存在していた。

モダンなスタックでも避けられないHTTPの複雑性

HTTP/1.1は1990年代から続く仕様であり、長年の拡張によって解釈の余地が非常に多い。プロキシ開発者は「どんなに壊れたリクエストでも、可能な限りバックエンドに届ける」という「寛容さ」と、「不正なリクエストを厳格に弾く」という「安全性」の板挟みにあう。

今回の事例では、Pingoraがレガシーなクライアントをサポートするために持たせていた「解釈の柔軟性」が、攻撃者に悪用される結果となった。Cloudflareのような巨大なインフラを支える技術であっても、OSSとして一般公開され、多様な環境(イングレスプロキシとしての利用など)に置かれることで、新たなリスクが浮き彫りになる点は興味深い。

今後のプロキシ開発においては、Rustによるメモリ安全性だけでなく、仕様(RFC)への「形式的な厳格さ」をいかに自動テストや静的解析で担保するかが、次なるセキュリティの焦点となるだろう。

この記事のポイント

  • Pingora 0.8.0がリリースされ、3つのリクエストスマグリング脆弱性が修正された。
  • 脆弱性は、不適切なUpgrade処理、HTTP/1.0の誤認、不十分なキャッシュキー生成に起因する。
  • CloudflareのCDNサービス自体には影響がなく、独自にPingoraを構築しているユーザーが対象となる。
  • 攻撃を受けると、セキュリティ制御のバイパスや他ユーザーのセッション奪取の恐れがある。
  • Pingoraを運用しているエンジニアは、速やかに最新版へのアップグレードを推奨する。

出典

  • Cloudflare Blog「Fixing request smuggling vulnerabilities in Pingora OSS deployments」(2026年3月9日)
  • GitHub「cloudflare/pingora Release v0.8.0」(2026年3月2日)
  • CVE MITRE「CVE-2026-2833 / CVE-2026-2835 / CVE-2026-2836」(2026年3月4日)