Windows版OpenSSHクライアント実行後にコードページが壊れるようになった

 私の環境で気付いたのは2021年5月11日頃なのですが、DOSプロンプト(cmd.exe)で一部のコマンド実行後に英語でメッセージが表示されるようになりました。
 特に気にしていなかったのですが、一部のバッチファイルの処理結果で文字化けの発生が確認され、こりゃ不味いと思って調べてみました。
 その結果、OpenSSHクライアント(SCP含む)を実行した後にこの事象が発生することを特定しました。
 

前提環境

OS
Windows10 Pro 20H2 19042.985
SSHクライアント
OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2 *1

 関連性無さそうですが、タイミング的にはWindowsUpdateでKB5003173がインストールされた後から発生しているような感じがします。
support.microsoft.com

 

発生事象

再現手順

 コマンドプロンプトを実行し、任意のコマンドを実行します。

C:\>dir C:\Windows\System32\OpenSSH\ssh.exe
 ドライブ C のボリューム ラベルがありません。
 ボリューム シリアル番号は XXXX-XXXX です

 C:\Windows\System32\OpenSSH のディレクトリ

2021/05/12  15:29           946,176 ssh.exe
               1 個のファイル             946,176 バイト
               0 個のディレクトリ  43,242,856,448 バイトの空き領域

 普通に日本語が表示されています。ここまでは正常です。
 続いて、SSHを実行します。どこかのサーバに接続してもしなくても関係ないので、とにかくssh.exeを実行します。ここではバージョン情報を表示させます。

C:\>ssh -V
OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2

 バージョン情報には日本語を含まないので、一見すると特に何も異常は無いように見えます。
 ここで、もう一回先と同様にコマンドを実行してみます。

C:\>dir C:\Windows\System32\OpenSSH\ssh.exe
 Volume in drive C has no label.
 Volume Serial Number is XXXX-XXXX

 Directory of C:\Windows\System32\OpenSSH

2021/05/12  15:29           946,176 ssh.exe
               1 File(s)        946,176 bytes
               0 Dir(s)  43,245,072,384 bytes free

C:\>dir C:\Windows\System32\OpenSSH\scp.exe
 Volume in drive C has no label.
 Volume Serial Number is XXXX-XXXX

 Directory of C:\Windows\System32\OpenSSH

2021/05/12  15:29           307,712 scp.exe
               1 File(s)        307,712 bytes
               0 Dir(s)  43,245,072,384 bytes free

 はい、何か英語表示に変わってます(意図しない挙動)。
 この状態でコードページを確認すると以下のように表示されます。

C:\>chcp
Active code page: 932

 コードページがMS932であることは期待通りですが、"Active code page: 932"という英語表示は想定外です。
 改めて、明示的にMS932に切り替えてみます。

C:\>chcp 932
現在のコード ページ: 932

 「現在のコード ページ: 932」という表示で、正常に日本語表示に戻ったようです。
 念のため、他のコマンドを叩いてみると、日本語表示に戻ったことが確認できます。

C:\>dir C:\Windows\System32\OpenSSH\ssh.exe
 ドライブ C のボリューム ラベルがありません。
 ボリューム シリアル番号は XXXX-XXXX です

 C:\Windows\System32\OpenSSH のディレクトリ

2021/05/12  15:29           946,176 ssh.exe
               1 個のファイル             946,176 バイト
               0 個のディレクトリ  43,242,856,448 バイトの空き領域

 メッセージが英語表示になるだけなら実害は無いのですが、実はそうではないのです。"Active code page: 932"と表示されるときは、MS932ではなくUTF-8(Code Page: 65001)に切り替わっているようなのです。そのため、プログラムによっては文字化けが発生することがあります。
 

実はUTF-8

 "Active code page: 932"のとき、UTF-8に切り替わっていると考えられる根拠は以下の通り。
 通常時は問題無く日本語マルチバイト文字がMS932(≒SJIS)で取り扱われます。以下のように、環境変数での取り扱いや、コンソール出力、ファイルへのリダイレクトなど一貫して正常に処理できます。

C:\>chcp
現在のコード ページ: 932

C:\>SET VAR=テスト

C:\>echo %VAR%
テスト

C:\>echo %VAR% > c:\temp\temp.txt

C:\>type c:\temp\temp.txt
テスト

 ところが、"Active code page: 932"状態ではぶっ壊れます。

C:\>ssh -V
OpenSSH_for_Windows_8.1p1, LibreSSL 3.0.2

C:\>chcp
Active code page: 932

C:\>echo %VAR%
テスト

C:\>echo %VAR% > c:\temp\temp.txt

C:\>type c:\temp\temp.txt
テスト

 一見すると、正常な挙動に見えます。が、"Active code page: 932"環境で生成されたファイル(この例ではc:\temp\temp.txt)を「現在のコード ページ: 932」と表示される正常なMS932環境で確認すると、文字化けしていることが確認できます。

C:\>chcp 932
現在のコード ページ: 932

C:\>type c:\temp\temp.txt
繝・せ繝・

 そしてこのファイルをダンプしてみると、E38386, E382B9,E38388と、UTF-8で"テスト"と書かれていることが判ります。

C:\>wsl hd /mnt/c/temp/temp.txt
00000000  e3 83 86 e3 82 b9 e3 83  88 20 0d 0a              |......... ..|
0000000c

C:\>wsl nkf --ic=utf8 /mnt/c/temp/temp.txt
テスト

 以上のことから、"Active code page: 932"環境ではコードページがMS932ではなくUTF-8として処理されていると考えられます。
 

雑記

 [オプション機能の管理] - [機能の追加]からインストールしたOpenSSHについて、どこにバグレポート出せばいいのか判らないので、ここに書いてます。
 蛇足ながら、類似事象でcmd.exeとWSLを組み合わせてパイプ処理を行うと同様の問題が発生することがありました。
cmdからWSLを使って日本語文字列をパイプで扱うとcmdのコードページが壊れる - 記憶は人なり
 今回の事象も、sshやscpを実行したらchcp 932を明示的に叩くようにすれば、とりあえずは文字化け問題は回避できそうです。バッチファイルからsshやscpを叩いていて、その後に日本語を含む何らかの処理があるならchcp 932を一行追加すれば文字化け回避できると思われます。
 



以上。

*1:[システム設定] - [オプション機能の管理] - [機能の追加] からインストールした [OpenSSH クライアント]