行ストリーム処理で複数行パターンを一致させる(begin/end マーカーのバッファリング)

一言まとめ

行単位で即フラッシュするストリーム処理に PEM 秘密鍵のような複数行ブロックの検出を足すには、開始マーカーを見た行からバッファリングに入り、終了マーカーか安全上限(100 行 / 64KB)で抜ける。上限超過時は無加工でフラッシュする(fail-open)。単一行パターンの遅延は変わらない。

作成 · 更新 · #streaming#regex#cli#buffering
目次 6 sections
  1. 01 問題
  2. 02 決定: begin/end マーカーによる条件付きバッファリング
  3. 03 結果
  4. 04 採らなかった案
  5. 05 関連
  6. 06 更新履歴

調査時点: 2026-04。公開 OSS の mask-pipe(github.com/c12o-dev/mask-pipe)が PEM(秘密鍵や証明書を開始・終了マーカー付きのテキストで表す形式) 秘密鍵のマスクを足したときの ADR から。

問題#

ストリーミング用のフィルタは「入力 1 行ごとに出力をフラッシュする」ことを保証したい(tail -f | filter が EOF まで止まらないため)。一方、PEM 秘密鍵のブロックは 20〜50 行にまたがり、ブロック全体を見ないとマスクするか決められない。99% 以上の行は複数行の秘密情報を含まないので、それらの遅延を増やさないことが制約になる。

決定: begin/end マーカーによる条件付きバッファリング#

  1. パターン定義に省略可能な Multiline bool / BeginMarker / EndMarker を足す。
  2. エンジンが BeginMarker に一致する行を見たらバッファリングモードに入り、行を溜める。
  3. EndMarker に一致するか、安全上限(100 行または 64KB の早いほう)を超えるまで続ける。
  4. EndMarker で抜けたら、溜めたブロックを結合して本来の正規表現を適用し、一致すれば置換文字列(例: [REDACTED PRIVATE KEY])に置き換える。
  5. 安全上限で抜けたら、溜めた行を無加工でフラッシュし(fail-open)、stderr に警告を書く。入力が壊れていてもデータは失わない。
  6. 単一行パターン(既定)は一切影響を受けない。

結果#

  • PEM ブロック内の行だけ、ブロック全体を読む時間ぶんの遅延が乗る(2KB の鍵で 10ms 未満)。
  • BEGIN だけあって END が来ない入力では、最大 100 行ぶん遅れてからフラッシュされる。
  • 同じ仕組みで、後から YAML の秘密ブロックや複数行 JSON にも対応できる。
  • パターン構造体に、大半のパターンでは nil / false のフィールドが 3 つ増える。

採らなかった案#

案棄却理由
入力全体をメモリに溜めてから一致ストリーミング保証が壊れる。tail -f が EOF まで出力しない
N 行のスライディングウィンドウPEM ブロックの長さはばらつく(RSA-2048 で約 27 行、RSA-4096 で約 52 行)。固定幅は大きい鍵を取りこぼすか、全行でメモリを無駄にする
複数行パターンを見送るPEM 鍵は明示的なマーカーがあり偽陽性ゼロで、最も漏れやすい秘密情報の 1 つ。外すと価値が落ちる

関連#

更新履歴#

  • 2026-04-17: 初版(mask-pipe ADR-0004)
  • 2026-10-17: Wiki へ移植、概念ページとして再構成

同じトピック — CLI