Obsidian書き込みを安全にする—固定パス・競合検出・監査ログ
ObsidianはMarkdownファイルなので書き込み自体は簡単です。しかし簡単だからこそ、別Vaultへの誤保存、パストラバーサル、手動編集の上書きが起こり得ます。最初の実装では、安全な日次ノート専用MCPを作りました。
Vaultをパスと識別子で確認する
設定されたフォルダが存在するだけでは不十分です。次をすべて確認してから接続成功とします。
- 期待する固定パスにVaultが存在する
- `.obsidian`ディレクトリがある
- 独自のVault識別マーカーが一致する
- Vaultや管理フォルダがシンボリックリンクではない
- 保存先を解決した実パスがVault内にある
外付けディスクが外れている時に同名フォルダを自動作成すると、別の場所へ記録してしまいます。Vaultルートは自動作成せず、安全に停止します。
日付から保存先を決める
Tool利用者から任意パスを受け取らず、`YYYY-MM-DD`だけを受け、サーバー側で保存先を導出します。不正日付、拡張子付き、`../`を含む入力は拒否します。
“`text
Daily/YYYY/YYYY-MM-DD.md
“`
機能を日次ノートへ限定することで、Vault全体を書き換える権限を与えずに済みます。
revision競合を検出する
prepare時に既存ファイルのSHA-256を取得し、write時に再確認します。prepare後に人がObsidianで編集していればrevisionが変わるため、上書きを拒否します。
書き込みは同じディレクトリの一時ファイルへ出し、flushとfsync後に原子的に置換します。途中でプロセスが落ちても、半分だけ書かれた本番ファイルを残しにくくなります。
probeと監査ログ
本番の日次ノートへ触れる前に、一時ファイルの作成、読み戻し、削除を行うwrite probeを用意しました。成功条件には後片付け完了も含めます。
監査ログには日時、対象日、相対パス、操作、前後のハッシュ、バイト数、結果を残します。要約本文や文字起こしを複製しないことで、ログ自体の機密性を下げます。
再現チェック
- [ ] Vaultを固定パスと識別子で確認する
- [ ] シンボリックリンクを拒否する
- [ ] 任意パスを受け取らない
- [ ] prepare後のrevision競合を検出する
- [ ] 一時ファイルから原子的に置換する
- [ ] probeの後片付けまで確認する
次回は、PLAUD、ニュース、同日メモ、ChatGPT資料を一つの日次ノートへまとめます。
参考にした一次情報
- [Obsidian—Manage vaults](https://help.obsidian.md/Files+and+folders/Manage+vaults)
- [Python os.replace](https://docs.python.org/3/library/os.html#os.replace)
- [Python hashlib](https://docs.python.org/3/library/hashlib.html)
