FessのZIP抽出でバイナリーのごみが検索本文に入る問題の修正案

ZIPのクロールで、展開を拒否したはずのファイルがバイナリーのごみとして検索本文へ入る問題に対し、fess-crawlerのPR #228が提案されています。

原因の例外にあるZIP爆弾の検出結果を拾う

Tikaが過大な展開を検出すると、外側の例外はTIKA-237: Illegal SAXExceptionとなり、Suspected zip bombという情報が原因の例外にだけ入ることがあります。従来の抽出処理は外側のメッセージしか確認せず、このケースを見逃していました。

標準の抽出設定ではxmlExtractorが登録されています。そのため、通常のXML抽出への代替処理へ進み、ZIPの生のバイト列が本文として返ることがありました。PRには、約0.3MBのファイルから展開後300MB相当となるZIPで、約305KBのごみが登録された例が記載されています。Tika 3.3.2でも同じ挙動と報告されており、Tika 4だけに起因する問題ではありません。

修正案の適用条件と初期値

修正案は原因の例外を順にたどり、メッセージにzip bombがあれば、既存のreason=zipBombDetectedを含む抽出エラーとして拒否します。他のSAXExceptionでは従来どおりXML抽出への代替処理を残します。

新しい有効化スイッチや初期値の変更はありません。確認した標準extractor.xmlではmaxCompressionRatio=1、maxUncompressionSize=10000000が設定されていますが、今回のPRはこれらの閾値を変更しません。実際の判定はTikaと環境の抽出設定にも依存するので、この値をすべてのアーカイブの安全性を保証する上限として扱わないでください。

利用には修正を含むcrawlerを組み込んだ対応Fessビルドが必要です。PR番号だけを根拠に、本番環境のjarを単独で差し替える手順にはしません。

運用で確認すること

取り込み後の本文に読めないバイト列が並ぶ場合は、元のファイル、抽出ログ、原因の例外を併せて確認します。修正を含む検証環境では、疑わしいファイルが本文として返らず、reason=zipBombDetectedの抽出エラーになることを確認します。実運用のファイルを検証する際も、隔離した環境で扱います。

既に登録されたごみを自動削除する処理は含みません。対象文書を特定し、運用上の削除・再クロール方針を決める必要があります。失敗した再クロールだけで古い文書が必ず消えるとは判断しません。また、例外メッセージを調べる修正であり、すべての圧縮爆弾を検出する新しい仕組みではありません。

PRではxmlExtractorを登録したコンテナーと生成ZIPを使う回帰テストが追加されています。テスト成功はPR作者の報告で、こちらでFessの実クロールを再実行したものではありません。

関連PR

FessのStaticテーマでログイン用パスワード欄が出ない場合の確認

FessのStaticテーマで、ログインダイアログは開くのにパスワード欄が表示されず、ログインできない問題の修正が提案されています。

11テーマ共通のダイアログを確認する

対象はBootstrapの代わりにcompat.jsのModalを使う11種類のStaticテーマです。PR #83でパスワード欄を必要な場面だけ生成する方式へ変えた後、生成のきっかけとなるshow.bs.modalイベントが発生しないため、欄がフォームへ追加されなくなっていました。

修正案では、ダイアログを開く前にshow.bs.modal、開いた後にshown.bs.modalを発生させます。最初のイベントがキャンセルされた場合は開きません。認証方式やパスワードポリシーを変更するものではなく、利用者に新しい有効化設定を求める変更でもありません。

ログイン必須の環境で特に影響が出ますが、認証必須設定を解除して回避する手順にはしません。標準Bootstrapテーマを含むすべてのログイン障害の原因がこの問題である、という説明でもありません。

Fess本体とテーマの対応を分けて選ぶ

main向けの修正案ではテーマのバージョンは15.10.1、最小Fessバージョンは15.10です。Fess 15.9で確認する場合は15.9.x向けのPR #88を含むソースを使います。たとえばDocSearchは15.9.12から15.9.13へ上がり、最小Fessバージョンは15.9のままです。全テーマが同じ15.9系パッチ番号になるわけではありません。

修正を含むチェックアウトで./scripts/package.sh docsearchを実行し、生成したZIPを管理画面「テーマ」(/admin/theme/)でアップロードして選択します。仮想ホストを使う場合は、そのテーマ割り当ても確認します。テーマの自動切り替えや新しい初期値の追加はありません。PRが未マージのため、ブランチ名や版番号だけで修正入りと判断しないでください。

更新後の確認と制限

独自に編集したテーマのファイルを控え、対応する検証環境で、ダイアログを開くとパスワード欄が出ること、ログインできること、閉じると欄が取り除かれることを確認します。ブラウザに古いJavaScriptが残る場合は再読み込みも行います。

PR #87ではFess 15.10.0-SNAPSHOTとsemanticlensでのログイン確認が報告されています。PR #88では自動テストと11テーマのバンドル検証が報告されていますが、こちらで全テーマの稼働確認を行ったものではありません。配布ZIPの公開も別途確認が必要です。

先の11テーマの記事はパスワード変更などの移植を紹介しました。今回はその後に分かったパスワード欄生成の不具合に絞った補足です。

関連PR

Fessのデータストアでroleとvirtual_hostの書き方を確認する

データストアのクロールが成功と記録されているのに、文書が検索できないことがあります。JavaScriptスクリプトでroleやvirtual_hostへ文字列・配列を渡した際、文書ID生成前に型の不一致が起きる問題への修正がマージされました。

スクリプトでは検索用のロール値を指定する

Boxの設定例も訂正され、固定ロールのスクリプトは次の形になりました。

role="Rbox-users"

管理画面の「パーミッション」欄や、対応プラグインのdefault_permissionsでは{role}box-usersのような表記を使います。一方、データストアスクリプトのroleは値がそのままインデックスへ入ります。初期の接頭辞はロールがR、グループが2、ユーザーが1です。独自に接頭辞を変更している環境では、その設定に合わせます。

role=['Rbox-users', 'Roperators']
virtual_host=['portal-a', 'portal-b']

上記はスクリプト欄の記述例です。ロールや仮想ホスト自体の登録、検索リクエスト側の設定も必要です。

文字列は1要素として扱う

修正後は、文字列を1要素のリストへ変換し、コレクション・配列・スクリプトエンジンが返すインデックス付きMapを文字列リストへそろえてから文書IDを作ります。roleとvirtual_hostの両方が対象です。新しい有効化スイッチはありません。

"Rbox-users,Roperators"という1本の文字列は、2つへ分割されません。複数指定は配列にします。null要素は除外しますが空文字列は保持し、対応しない型はフィールド名と型を含むDataStoreExceptionとして失敗処理へ渡します。既存のリスト指定は同じIDを維持します。

既存データを自動では直さない

従来はClassCastExceptionがWARNに残り、ジョブ全体の成功表示だけでは文書単位の失敗を見逃す場合がありました。修正の取り込みを確認した環境で、少量のデータから再クロールし、登録件数と実際の利用者による検索を確かめます。

誤ったロールで登録済みの文書や、登録に失敗した文書を修正だけで自動再処理する機能ではありません。再取り込みと、必要に応じた古い文書の整理が必要です。

関連PR