PR

ゼロ幅スペース (ZWSP) U+200B でハマった話

whoami サーバ
この記事は約6分で読めます。

※ この記事は 2024/03/16 に投稿され、 2024/03/17 に内容が更新されています

わけわからん

久々に業務で冷汗、脇汗をかいた話。
DKIM 署名の有効化作業で、あらかじめ仕込んでいた設定ファイルをアンコメントするだけの簡単なお仕事。
のはずなのに、、
有効化しようとしたところ、なぜか秘密鍵ファイルが見つからず「そのようなファイルやディレクトリは存在しません」というエラーになってしまい、わけわからん状態に。

何が起きていたのか

あるはずのファイルが存在しないと言われる

秘密鍵ファイルが存在しているのに、なぜか読込めない。
存在しないファイルになってる。

$ ll /etc/opendkim/keys/exsample.com/hoge.private: 
'/etc/opendkim/keys/exsample.com/hoge.private' にアクセスできません: そのようなファイルやディレクトリはありません

$ cd /etc/opendkim/keys/exsample.com​/
$ ll                                        
合計 8
-rw------- 1 opendkim opendkim 1704  1月 28 15:36 hoge.private
-rw------- 1 opendkim opendkim  508  1月 28 15:36 hoge.txt

いや、あるんですが? あるよね?
うーん、、

解決した

そういえば、前にもあったな、と。
忌しき、ゼロ幅スペース (ZWSP)Zero Width SPace Unicode のコードポイント U+200B 問題を思い出した。

そもそもゼロ幅スペースとは?

Wikipedia 先生お願いします。

ゼロ幅スペース(ゼロはばスペース、: zero width space, ZWSP)は、コンピュータの組版に用いられる非表示文字で、文書処理システムに対して語の切れ目を示すのに用いる。通常、英語などのわかち書きをする言語において、文の途中で改行を入れる場合はスペースの位置で行われる。しかし、スラッシュなどの記号の後などスペースは入らないが改行をしても良い箇所や、日本語などのわかち書きをしない言語において、改行できる位置を明示するためにゼロ幅スペースが用いられる。

ゼロ幅スペース – Wikipedia より

存在しているのに、非表示文字なので見えないというのが厄介ですね。

ゼロ幅スペースの検出

まずは grep コマンドを使用してディレクトリ内にゼロ幅スペースがあるかどうかを確認してみましょう。
ターミナルで以下のコマンドを入力。

$ grep -r -l -I $'\xE2\x80\x8B' /path/to/DIRECTORY

-r オプションで再帰的に検索し、 -l オプションで該当するファイルのパスを表示します。 -I オプションはバイナリファイルを無視します
/path/to/DIRECTORY は適切なパスを指定してください

$ sudo grep -r -l -I $'\xE2\x80\x8B' ./
exsample.com​​/hoge.txt

はい、いました。確定ですね。
やっぱりお前か!

ゼロ幅スペースの削除

ゼロ幅スペース見つかったら、そいつを駆逐する必要があります。
とはいえ、対応は簡単で、単に mv コマンドを使用して、新しいディレクトリ名にゼロ幅スペースを含まないように変更するだけです。
※ TAB キー補完だとゼロ幅スペースを含んだ状態で補完されるので注意!

mv /path/to/DIRECTORY​ /path/to/NEW-DIRECTORY

以上により、ゼロ幅スペースを含まないディレクトリ名に変更できます。
今回はディレクトリに混入していたので、以上で無事に問題が解決され、秘密鍵ファイルを読込むことができました。

まとめ

今回は以下の流れでした。

  1. お客様から Power Point 資料でドメイン名の指定が来る
  2. 別部署にて Power Point 資料にあるドメイン名をそのままコピー (Power Point の余計な機能のせいで、ここでゼロ幅スペースが混入)
  3. 気がつかずに依頼どおりに作業準備 (ゼロ幅スペースが混入したディレクトリが作成される)

ゼロ幅スペースは組版などで利用するらしいが、我々インフラエンジニアにとっては悩みの種でしかない。Unicode はマジでカオス。

恒久対策

毎回変な汗をかきたくないし、恒久対策を考えてみた。
見えないのであれば、見えるようにすればいいだけのこと。

Last Resort (失敗)

最初に考えたのが、フォントで可視化してしまう方法。

Last Resort とは Unicode 規格を管理する非営利団体 The Unicode Consortium が提供するフォールバック用のフォント。
GitHub のリポジトリ からダウンロードすることができる。

ブラウザでそのままフォント指定すると、今度は見える文字が読めなくなってしまうため、 CSS でコードスペースを指定して、通常フォントよりも先に記載する。

/* ZWSP */
@font-face {
  font-family: zwsp;
  src: local("Last Resort");
  unicode-range: U+200B,
    /* Unicode には他にも見えない文字があるので書き連ねる */
  ;
}

/* Apply */
body {
  font-family: zwsp, "Myriad Pro", HiraginoSans;
}

→ ダメでした!
フォントが用意されてても、そもそもゼロ幅なので描画されずに、不可視のままということのようだ。

detect-zero-width-characters (成功)

Chrome ウェブストアを探していたら、まんまな名前の Detects zero-width characters という拡張機能を発見。


利用者が 600 名に満たないというマイナー過ぎる拡張機能だが、GitHub でソースが公開されており、読んでみたところ悪意はないということがわかった。

早速インストールして適用。

適用前

before_addon

適用後

after_addon

見える! 見えるぞ!! 作者に感謝。
ただ、今のところゼロ幅スペースのみの対応で、他の不可視 Unicode 文字には対応していない。
シンプルなつくりなので、後で他の不可視文字にも対応できるようにプルリクを出そうと思う。

コメント