セキュリティモデル: 脅威ごとの sim の対処

sim の出発点は、自分で書いていないファイル、フォルダ、リポジトリに、何をされうるのかという問いです。このページは脅威モデルと、脅威ごとの sim の対処をまとめています。

脅威モデル

自分で書いていないファイルやリポジトリを開く場面を想定します。クローン、展開したアーカイブ、プルリクエストのチェックアウト、別のプロセスが書くファイルです。攻撃者が握っているのは中身であって、あなたのマシンではありません。sim は、その中身がユーザーから隠れられず、エディタの設定を書き換えられず、エディタにコードを実行させられないようにします。

前提

  • 自分の端末、自分のユーザーアカウント、自分のグローバルな git 設定は信頼できる。
  • 攻撃者は、リポジトリ内のあらゆるファイルを変更できる。.git/config や、開くファイルの隣にあるファイルも含む。
  • 攻撃者は、sim 本体やホームディレクトリは変更できない。

脅威と、sim の対処

  • 双方向制御文字(Trojan Source)

    脅威

    Unicode の制御文字は、コードの表示順を並べ替えます。そのため、レビューする人が読むコードと、コンパイラが読むコードが食い違います(CVE-2021-42574)。研究者がエディタに勧めているのは、これらの文字を知覚できるようにすることです。[1] [2] [3]

    sim の対処

    U+200E–200F、U+202A–202E、U+2066–2069、U+061C は、マゼンタのブロックの <U+202E> のように描かれ、端末にそのまま送られることはありません。ブロックは、選択中、検索のマッチ、カーソル行、外部からの変更の中、遠くの行のフォグの中、見出しやコードブロックの上など、セルがどんな状態でも保たれます。ファイルに書かれた文字列 <U+202E> は普通のテキストで、ブロックはつきません。

    仕様: SAFE-8, UI-15

  • 見えない文字と空白

    脅威

    Unicode には、何も描かない文字がたくさんあります。ASCII を写したタグ文字の並びは、ファイルを読み込む AI アシスタントへの隠れた指示になりえます(「ASCII スマッグリング」)。タグ文字を知らない描画側は「display any sequence of tag characters as invisible」(タグ文字の並びを不可視として表示する)と、規格自身が述べています。異体字セレクタの並びは、プログラムを運べます。公開された VS Code 拡張機能にペイロードを隠した例があります(GlassWorm)。フィラー、ソフトハイフン、ジョイナー、行区切りは、識別子やコメントの中にあっても、見た目を何も変えません。ゼロ幅スペース、ファイル途中のバイトオーダーマーク、ノーブレークスペース、行末の空白も、見た目を変えないまま、ファイルの意味や差分の読み方を変えます。[4] [5] [6] [7] [8] [9]

    sim の対処

    U+200B と、ファイル先頭以外の U+FEFF は、<U+200B>、<U+FEFF> と描きます。ノーブレークスペースは ⍽、行末の空白は ·、タブは » です。

    何も描かない文字はすべて、同じように、マゼンタのブロックの上に <U+E0041> のような形で表示します。本文、ステータス行、メッセージ、コマンドラインのほか、ファイル由来の名前や行(ツリー、タブ、パンくず、検索結果)でも同じです。対象は、書式文字、タグ文字、異体字セレクタ、ハングルのフィラー、ソフトハイフン、結合書記素連結子、U+2028 と U+2029、そして Unicode 18.0.0 が割り当てていないすべてのコードポイントです。次のものは、そのまま描きます。2 つの絵文字のあいだのゼロ幅ジョイナー、絵文字の直後の異体字セレクタ、イングランド・スコットランド・ウェールズの 3 つの旗、私用領域の文字(Nerd Font のアイコン)です。同じ文字でも、それ以外の場所にあれば表示します。代償もあります。漢字の後ろに、字形を指定する異体字セレクタ(漢字の字形を 1 つ選ぶために登録された仕組み)がつくと、葛<U+E0100> のようにセレクタを表示します。同じ文字がデータを隠す経路になるためで、影響は主に日本語の文章に及びます。Unicode のソースコード向けの指針は、エディタに「an option to make visible any default ignorable code points」(既定で無視される文字を可視にするオプション)を勧めています。sim にそのオプションはなく、常に表示します。[10] [6] [11] [12] [13]

    仕様: SAFE-8, SAFE-10, SAFE-11, UI-6

  • ファイルやファイル名に含まれる端末エスケープシーケンス

    脅威

    ファイルの中身やファイル名に含まれる制御文字は、エスケープシーケンスとして端末に届くことがあります。

    sim の対処

    C0 文字と DEL は ^[ のように、C1 文字は <U+0085> のように描きます。端末にはそのままの文字を一切書き出さず、テストで実際に送ったバイト列を検査しています。

    ファイル名の制御文字と双方向制御文字は、ツリー、タブ、パンくず、検索結果、ピッカーのどこでも、同じ形の ^[ や <U+202E> で描きます。v0.1.0 は U+FFFD で描いていました。

    仕様: SAFE-8, SAFE-10, TREE-1, GREP-7

  • ファイルに仕込まれた設定(モードライン)

    脅威

    ファイル中のコメントでエディタのオプションを設定でき、この仕組みの不具合がコード実行につながったことがあります。CVE-2019-12735(Vim と Neovim)、CVE-2026-34982(Vim)です。[14] [15] [16]

    sim の対処

    設定やコマンドをファイルの中身から読むことは決してありません。すり抜けられるモードラインがそもそもありません。

    仕様: SAFE-9

  • プロジェクト固有の設定

    脅威

    プロジェクトのディレクトリが、エディタが読み込んで実行する設定を持てます。Vim と Neovim の exrc ファイル、Helix の .helix/config.toml です。[17] [18] [19]

    sim の対処

    sim には設定ファイルも、プラグインも、読み込むべきプロジェクト固有の設定もありません。記憶するのは見た目、アイコン、Markdown の表示方法の選択だけで、どれも 1 語として sim のステート用ディレクトリに保存します。

    仕様: SAFE-9, LOOK-1

  • コマンドを実行するリポジトリ設定

    脅威

    git は、リポジトリ自身の .git/config に書かれたコマンドを実行します。core.fsmonitor はフックのコマンドを指定し、git status などのコマンドが呼び出します。フィルタドライバは、ファイルの中身に対して動くプログラムを指定します。展開したばかりのリポジトリで、エディタが git にステータスを尋ねると、これらが実行されることがあります。[20] [21] [22]

    sim の対処

    sim はまず git にリポジトリの設定を尋ねます。コマンドラインで止められるもの(core.fsmonitor、フック、フィルタ、外部 diff、テキスト変換)は無効にして、git に答えさせます。リポジトリ自身のスコープに、ほかにコマンドを持ちうるもの(core.sshCommand、それを持ち込みうる include)が定義されていれば、git は実行しません。実行するときも、シェルを通さず、--no-optional-locks をつけ、取得を止める環境で動かします。sim は git の書き込み系のコマンドを一切実行しないので、フックは動きません。ツリーには n git settings off か git not run が出て、ステータス行には原因のキーと場所が出ます。

    仕様: MARK-1, GIT-1, GIT-2, GIT-3, GIT-5

  • 外部から書き換えられるファイル

    脅威

    ビルド、フォーマッタ、ツールが、開いているファイルを書き換えます。そこで保存すると、相手の作業を上書きしてしまい、あるいは相手の作業があなたの作業を上書きします。

    sim の対処

    sim は変更に気づいて変更箇所に印をつけ、rename の直前に、ディスク上のファイルのハッシュを読み込み時のものと比べます。違っていれば、何も書き込みません。

    保存の書き込み中に届いた変更は、保存の応答を待つようになりました。そのため、保存中のテキストの上に合流してしまうことはありません。2026-10-18 に見つかったまれな競合状態により、v0.1.0 では 1 行が失われる可能性がありました。

    仕様: DISK-1, DISK-2, SAFE-5, SAFE-7

  • クラッシュと、閉じられた端末

    脅威

    クラッシュ、kill -9、端末を閉じることで、未保存のテキストが失われます。

    sim の対処

    未保存のテキストは、最短で 1 秒おきにステート用ディレクトリへスナップショットされ、取り消し 1 回分として復元を提案します。そのディレクトリは、あなたが所有し、他者のアクセス権がない実ディレクトリでなければならず、そうでなければスナップショットはオフになり、sim がそれを知らせます。

    仕様: SAFE-6

  • テキストでないファイル

    脅威

    バイナリや UTF-8 でない内容をテキストとして見せると、ファイルの中身が隠れ、保存で壊れることもあります。

    sim の対処

    そうしたファイルは、理由を示して読み取り専用で開きます。不正なバイトは U+FFFD で描き、あらゆる書き込みを拒否します。

    仕様: SAFE-4

sim がしないこと

  • sim はサンドボックスではありません。ユーザー自身の権限で動きます。隠れた文字を見せても、それが隠しているコードをあなたが実行することは止められません。
  • 対象とする文字は、Unicode 18.0.0 の表で固定されています。後のバージョンが割り当てたコードポイントは、表を作り直すまで隠れた文字として表示されます。Unicode の紛らわしい文字(UTR #36)をすべて調べるものではなく、ほかの文字体系の似た文字(ホモグリフ。Trojan Source のもう一方の手口)は、sim のドキュメントが述べる範囲に入っていません。
  • 保存前の最後の確認では、ファイルのスタンプを比べ、スタンプが動いていたときだけハッシュを比べます。同じマイクロ秒の書き込みや、タイムスタンプの刻みが粗いファイルシステムで 1 刻み以内に起きた同じサイズの書き換えは、すり抜ける可能性があります。
  • このページの内容はすべて、プロジェクト自身の仕様とテストに基づきます。第三者による監査は、ドキュメントでは言及されていません。
  • 言語サーバーはまだありません。サンドボックスつきのものを、下のロードマップに載せています。

ロードマップ: 言語サーバー

予定

言語サーバーは、プロジェクトがエディタに起動を求められるプログラムで、リポジトリがコードを実行できる最大の入り口のひとつです。sim にはまだありません。計画しているのは、サンドボックスつきのクライアントと、プロジェクトのルートが信頼されているかをステータス行に出す表示です。予定であり、まだ提供していません。

出典

  1. NVD: CVE-2021-42574 (bidirectional control characters, “Trojan Source”)
  2. Boucher and Anderson, Trojan Source: Invisible Vulnerabilities (USENIX Security 2023)
  3. Unicode Standard Annex #9: Unicode Bidirectional Algorithm
  4. Unicode Technical Report #36: Unicode Security Considerations
  5. Johann Rehberger, ASCII Smuggler Tool: Crafting Invisible Text and Decoding Hidden Codes (Embrace The Red, 14 January 2024)
  6. Unicode Technical Standard #51: Unicode Emoji, revision 31 (ZWJ sequences, emoji tag sequences, Annex C)
  7. Paul Butler, Smuggling arbitrary data through an emoji (8 February 2025)
  8. Koi Security, GlassWorm: First Self-Propagating Worm Using Invisible Code Hits OpenVSX Marketplace (18 October 2025; the original address now redirects elsewhere, so this is the Internet Archive's copy)
  9. Endor Labs, Invisible Threats and the Blind Spots of Security (an analysis of GlassWorm)
  10. The Unicode Standard 18.0, chapter 23, Special Areas and Format Characters (§23.4 Variation Selectors, §23.9 Tag Characters)
  11. Unicode Technical Standard #55: Unicode Source Code Handling, revision 5 (§4.2 Blank and Invisible Characters)
  12. Unicode Technical Standard #37: Unicode Ideographic Variation Database, revision 16 (ideographic variation sequences)
  13. Unicode Ideographic Variation Database: the registered collections (Adobe-Japan1, Hanyo-Denshi, Moji_Joho and others)
  14. NVD: CVE-2019-12735 (Vim before 8.1.1365 and Neovim before 0.3.6, modeline)
  15. NVD: CVE-2026-34982 (Vim before 9.2.0276, modeline sandbox bypass)
  16. Vim security advisory GHSA-8h6p-m6gr-mpw9 (modeline sandbox bypass)
  17. Vim 9.2.1202, runtime/doc/options.txt ('modeline', 'modelinestrict', 'exrc', 'isprint', 'fsync')
  18. Neovim 0.12.6, runtime/doc/options.txt ('modeline', 'modelineexpr', 'exrc', 'isprint', 'fsync')
  19. Helix 25.07.1, book/src/configuration.md (a config.toml local to a project)
  20. git-config documentation (core.fsmonitor, filter.<driver>.*)
  21. githooks documentation (fsmonitor-watchman, post-index-change)
  22. Justin Steven, Git honours embedded bare repos, and exploitation via core.fsmonitor affects IDEs (2022)
  23. ripgrep user guide (the config file named by RIPGREP_CONFIG_PATH, --pre)