AIに作業させるとき、セキュリティで見るのは5箇所だった

#AI#セキュリティ

AIと一緒にサイトを作っていて、公開の直前に点検した。

そうしたら、設定のままだと内部メモが全部ネットに出るところだった。収益化のTODO、未公開の記事の下書き、内部ツール。どれもリンクは張っていないが、URLを直接叩けば読める状態になる。

危ないのは、これがエラーにならないことだ。サイトは正常に表示されるし、ビルドも通るし、どこにも警告は出ない。気づかなければ、気づかないまま公開されていた。

静かに事故る。

その日に見た5箇所を、叩いたコマンドごと残しておく。

1. 公開ディレクトリに何が入っているか

静的サイトのホスティングは、指定したフォルダの中身を全部配信する。HTMLだけを選んで出す、という動きはしない。

つまりそのフォルダに .md のメモを置いていれば、それも配信される。

$ find projects/game-graphics -type f
projects/game-graphics/NEXT.md          ← 収益化のTODO
projects/game-graphics/DEPLOY.md        ← 内部の手順書
projects/game-graphics/articles/….md    ← 未公開の記事下書き
projects/game-graphics/tools/gen-cards.js
projects/game-graphics/index.html
projects/game-graphics/about.html

上4つは出したくない。とくに1つ目には、何をいくらで売るつもりか、どのSNSにいつ投稿するつもりかまで書いてある。なので公開するものだけ site/ に分けて、ホスティング側の指定をそこに変えた。

site/          ← ここだけ配信する
  index.html
  about.html
  econ.html
  news.html
NEXT.md        ← 配信されない
DEPLOY.md      ← 配信されない
articles/      ← 配信されない

判断は簡単で、公開してよいものだけ site/ に入れる。迷ったら外に置く。外に置いて困るのは自分だけだが、中に置いて困るのは取り返しがつかない。

2. リポジトリが公開か非公開か

これは思い込みで間違える。私が間違えた。

私は自分のリポジトリを公開だと思っていて、スクリプトをGitHubのリンクで配ろうとした。確認したら非公開だった。

逆のパターンのほうが怖い。非公開のつもりで公開になっていると、中に入れた全部が読まれる。私のリポジトリには個人的な文章と仕事のルールが入っているので、公開になっていたら事故だった。

作った直後に1回確認して、あとは触らない。それだけでいい。

3. 鍵がコミットに入っていないか

AIにコードを書かせると、動かすためにAPIキーを直接書き込むことがある。動いてしまうので、そのまま通る。

$ grep -rIlE '(api[_-]?key|secret|token|BEGIN [A-Z ]*PRIVATE KEY|sk-[A-Za-z0-9]{20})' \
    --exclude-dir=node_modules --exclude-dir=.git .

$ git ls-files | grep -i secret

引っかかった行は1つずつ中身を見る。変数名だけなら問題ない。値が入っていたら手遅れだ。その場合は、点検して安心する話ではなくなって、鍵を無効にして作り直すところから始めることになる。

私のところでは、鍵は環境変数と .secrets.env から読む形になっていて、そのファイルは無視の設定に入っていた。git ls-files でも1件も出なかった。

一度コミットしてしまうと、あとで消しても履歴に残る。消したから大丈夫、にはならない。

4. AIに渡してよい情報かどうか

これはツールの設定ではなく、こちらの運用の話だ。

原価、仕入先の名前、取引先、個人情報。この辺りは渡す前に一度止まったほうがいい。渡した情報がどこに残るかは、こちらからは見えないので。

私は自分のルールとして、書かないものを決めて文書にしてある。

記録しない: 原価・仕入価格 / 仕入先名・取引先名
公開しない: 店舗名・店舗URL・品番・ブランド名・仕入先システム名

決めておくと、判断が要らなくなるのが利点だ。毎回考えると、疲れているときに間違える。

書いたものが本当に守れているかも、機械で見たほうがいい。

$ for w in 原価 仕入先 取引先; do
    echo -n "$w: "; grep -ril "$w" 公開するフォルダ/ | wc -l
  done

全部0であることを、公開前に確認する。目視では抜ける。人間は、自分が書いたものを読むときに、書いたつもりの文章を読んでしまうので。

5. 勝手に外部と通信していないか

いちばん見つけにくいのがこれだ。目で追っても分からない。

AIは頼んでいないことを、気を利かせてやる。ファイル名を分かりやすく変えたり、値の表記を揃えたり、便利そうな部品を足したりする。整った形で出てくるので、見ただけでは気づけない。

セキュリティの文脈だと、外部サービスの読み込みが勝手に増えるのが怖い。フォントやアイコンを外部から読むコードは、書かせれば普通に出てくる。それ自体は一般的なやり方だが、読み込んだ先に閲覧者の情報が渡ることになる。

なので、作ったものが外と通信していないかを確認している。

$ grep -ohE '(src|href)="https?://[^"]+' *.html
(何も出なければ、外部リソースの読み込みは無い)

私が作っているツールは、全部これが空になるように作ってある。入力した内容もブラウザの中にしか保存しない。維持費がかからないのと、他人の情報を預からずに済むのが理由だ。

預かっていない情報は漏らせない。個人が作って長く置いておくものは、この形がいちばん強いと思っている。


見るのは、公開フォルダの中身、リポジトリの公開設定、鍵の混入、渡してよい情報の線引き、外部通信の有無。この5つだった。

全部やっても10分かからない。今日かかったのも、それくらいだ。

そして5つのうち3つは、AIが悪いのではなく設定と運用の問題だった。AIに作業させるから危ないというより、作るのが速くなったぶん、確認が追いついていないというのが実際のところだと思う。

作る速さは10倍になっても、確認する速さは変わらない。だからコマンドにして、毎回同じものを叩くようにしている。

← 記事一覧へ