0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIで社内ツールは作れた。問題は、それを会社に置けるかだった

0
Last updated at Posted at 2026-09-22

自分のいないところで、止まっていた

社内向けのWebツールを、半年かけて作った。Claudeとチャットで対話しながら、少しずつ。
私は現場の人間で、専門の開発者ではない。

機能は一通り揃い、あとは使ってもらうだけ、という段階まで来ていた。
私は関係者に、説明会を開きますという連絡のメールを出した。

そのメールが、自分の知らないところで上へ流れていった。

やがて、指示が降りてきた。
DXを担当している部署と、内容を精査すること。
予定していた説明会は、中止になった。

本社からは、こういう指摘が出ていたらしい。

情報管理が厳しく叫ばれている中、この様な脆弱な管理で進めることは許容できません

私は、直接言われたわけではない。伝え聞いただけだ。
だから、何がどう「脆弱」なのかは、分からないままだった。

分かっていたのは、説明できる材料を自分で用意するしかない、ということだけだった。

精査の相手は、元情シスの管理職で、いまの基幹システムを社内に入れた人だという。
社内で、システムにいちばん詳しい人である。

私は説明資料を作り始めた。そこに、こう書いた。

外部へのアクセスは一切ありません。

嘘をつくつもりはなかった。社内のネットワークの中だけで動かすつもりで作ったし、外に何かを送っている覚えもなかった。

ただ、書き終えたあとで引っかかった。

「一切ありません」と言い切れる根拠を、自分は持っているだろうか。

思い当たる節はあった。住所の自動入力だ。
郵便番号を入れると住所が出てくる、あの機能。あの住所は、どこから来ているのか。

Claudeに聞くと、外部のサービスに問い合わせていた。
「一切ありません」は、その時点で嘘になった。

そして、同時にこうも思った。

1つあったということは、他にもあるのではないか。

コード全体を調べさせた。あと2か所あった。

どちらも、私が意図して入れたものではない。
便利だから、という理由で組み込んだ部品が、勝手に外を向いていた。
そしてこの2つは——自分では、一生気づけなかったと思う。

資料を出す前だったのは、運がよかった。

AIを使えば、動くものは作れる。私のような現場の人間でも作れる。
けれど——動くことと、会社に置いていいことは、別の話だった。


「取りに行くだけ」でも、情報は出ている

見つかった3か所は、どれも外から情報を取りに行く通信だった。
住所データを取ってくる。ライブラリを読み込む。フォントを読み込む。
社内の情報を外へ送っているわけではない。

だから最初、私はこう考えた。実害はないのではないか。

これは、間違いだった。

取りに行く通信でも、相手側には必ず記録が残る。

  • 何を調べたか — 郵便番号を送って住所を受け取る仕組みなら、送った郵便番号は相手のログに残る。それは「これから発送する先」の情報の一部だ
  • いつ調べたか — アクセスの時刻。件数の増減からは、業務の繁閑まで見える
  • どこから調べたか — 会社のIPアドレス。固定回線なら、そこから会社名が分かることもある

つまり相手側には、「どこの会社が、いつ、どの郵便番号を調べたか」が残りうる。
一件ずつなら断片でも、積み上がれば業務の動きになる。

フォントも同じだ。見た目のために読み込むだけの通信に見えるが、画面を開くたびにアクセス元の情報が渡っている。
実際、Webフォントの外部読み込みが個人情報保護の規則に違反すると判断された海外の判例もある。

そして厄介なのは、それが問題かどうかを判断するのは、私ではないということだ。
「たいした情報ではない」は、自分の感覚でしかない。

もう一つ、実務的な理由がある。

説明のとき、いちばん時間がかかるのは「一部だけ出ています」という状態だ。
この通信は何を送っているのか。なぜそれなら許されるのか。他に同じものはないのか。
問いが際限なく続く。

ゼロなら、一行で終わる。

だから私は、相談に行く前に全部潰すことにした。
指摘されてから直すのと、自分で見つけて直したうえで報告するのとでは、そのあとの話の進み方がまったく違う。


見つかった3か所

① 郵便番号から住所を引く、外部のAPI

依頼を入力する画面に、郵便番号を入れると住所が自動で入る欄をつけていた。
便利だし、入力ミスも減る。実装も簡単だった。
郵便番号を外部のサービスに投げると、住所が返ってくる。無料で使える。

問題は、投げているのが「これから発送する先の郵便番号」だということだ。

置き換え先は、すぐに見つかった。
日本郵便が、全国の住所データをCSVで無償公開している。
これをプログラムの中に持ってしまえば、外に問い合わせる必要はなくなる。

全国で約12万件。多く見えるが、辞書として持てば検索は一瞬で終わる。
やったことは、CSVを読んで、辞書ひとつだけのファイルを書き出すこと。それだけだ。

# make_zip_data.py : 公開CSVを、辞書1つだけのPythonファイルに変換する
import csv

table = {}
with open("source.csv", encoding="cp932", newline="") as f:
    for row in csv.reader(f):
        code = row[2]                    # 郵便番号
        addr = row[6] + row[7] + row[8]  # 都道府県 + 市区町村 + 町域
        table.setdefault(code, addr)     # 重複コードは1件目を採用

with open("zip_data.py", "w", encoding="utf-8") as f:
    f.write("# 自動生成ファイル。手で編集しないこと\n")
    f.write("# 生成元: 日本郵便の公開CSV / 生成日: YYYY-MM-DD\n")
    f.write("ZIP_TABLE = {\n")
    for code, addr in sorted(table.items()):
        f.write(f"    {code!r}: {addr!r},\n")
    f.write("}\n")

つまずきやすいのは文字コードくらいで、公開CSVは utf-8 ではないことが多い。

置き換えそのものは、半日で終わった。

詰まったのは、そのあとだった。この話は後半に書く。

② CDNから読み込んでいたライブラリ

画面からExcelを出力するために、外部のCDNからJavaScriptのライブラリを読み込んでいた。
<script> を一行書くだけで使える。よくあるやり方だ。

これも外部通信である。しかも問題は3つある。

  1. 社外への通信が発生する
  2. CDN側が落ちたら、社内システムなのに機能が止まる
  3. バージョンの指定が緩いと、ある日中身が変わる

対処は単純で、ライブラリのソースをHTMLに直接貼り付ける。それだけ。
作業は数分で終わり、困ったことは何もなかった。

一つだけ守ったのは、ライセンス表記を消さないこと。
MITやApache-2.0は、埋め込んで使う場合でも著作権表示を残す義務がある。
冒頭のコメントごと貼るのが確実だ。

③ Webフォント

これが、いちばん怖かった。

外部のWebフォントを読み込む記述が、HTMLに入っていた。

私は、それを入れた覚えがなかった。

見た目にこだわった記憶もない。
おそらく作り始めのどこかで生成されたコードにそのまま入っていて、半年間、一度も疑わなかった。

やったことは、パソコンに最初から入っているフォントを指定し直しただけだ。

body {
  font-family: "Yu Gothic UI", "Yu Gothic", "Meiryo", sans-serif;
}

見た目は特に変わらなかった。困ったことも何もない。

つまり、何の必要もない通信が、半年間ずっと発生していたことになる。


3つのうち2つは数分で終わった。残る1つも半日だ。

技術的には、たいした作業ではない。
それでも私は、半年間、一度も気づかなかった。

外部通信は、自分で入れるものではない。気づいたら入っているものだ。


1つ見つかったら、他にもある

見つけ方の順番は、こうだった。

  1. 住所の自動入力が気になり、自分で疑った
  2. Claudeに聞いて、外部通信だと確認した
  3. 「1つあるなら他にもあるはず」と考え、コード全体を調べさせた
  4. あと2か所出てきた
  5. 潰したあと、もう一度確認させた

振り返って思うのは、2番と3番のあいだが一番大事だったということだ。

1つ見つかった時点で、たいていは「見つかってよかった」で終わる。
そこで止めていたら、フォントとライブラリはそのまま残っていた。

AIに調べさせるときに、気をつけたほうがいいこと

うまくやれたという話ではない。あとから知って「危なかった」と思ったことを書いておく。

  • 「外部通信はありますか」だけでは足りない。通信の入口はいくつもある。fetch、<script src>、<link href>、CSSの url() ——それぞれを名指しで調べさせたほうが、漏れは減る
  • URLの文字列で検索しても見つからないことがある。接続先が定数にまとめられていると、http で検索してもかからない
  • AIは、見せられた範囲しか見ていない。「全部見た」と返ってきても、それは「渡された全部」でしかない

そして、私の確認は十分ではない

正直に書いておく。
私がやった確認は、Claudeに見せて「無い」と言われた、それだけだ。

本来なら、ブラウザの開発者ツールを開いて、実際に全部の機能を操作しながら、自分のサーバー以外へのリクエストが1本も出ていないことを目で見るべきだ。
コードを読むのと、動かして見るのは別の確認だから。

これは、これからやる。


消したあとに、残るもの

置き換えは半日で終わった。それなのに、終わった気がしなかった。

理由は、あとから分かった。

外部のサービスを使っていたとき、住所データを最新に保っていたのは向こうだった。
郵便番号が増えても、町名が変わっても、私は何もしなくてよかった。

自分のプログラムの中に12万件を持った瞬間、その役目が私に移った。

外部依存を消すというのは、外部がやってくれていた運用を、自分が引き取るということだった。

作業が減ったわけではない。運用のほうに移っただけだった。

悩んでいるのは、3つ

そして、この3つが今も片付いていない。

  1. いつ更新するのか — 元データは毎月更新される。毎月やるのは現実的ではない
  2. どうやって更新するのか — 手順を、誰が読んでも分かる形でどこに残すか
  3. どうやって忘れないようにするのか — これがいちばん難しい

3つ目が本質だと思っている。

年に1回のタスクは、必ず忘れる。
しかも自分が異動したら、後任はそんな作業があること自体を知らない。
何年か経って、誰も気づかないまま古い住所を返し続ける——というのが、最悪の形だ。

いま考えているのは、年度初めにアラートを出す仕組みを組み込んでおくことだ。
人の記憶にも、引き継ぎ資料にも頼らない。プログラムのほうから声を上げさせる。

ただ、まだ決めていない。

「不便だから戻す」は、起きなかった

外部依存を消すと、後任者が「不便だから」と元に戻してしまう——という心配は、しなくてよさそうだった。

いま検証してもらっている人たちからは、「早く導入してほしい」という声が来ている。
使う側にとって、外から取っているか中に持っているかは、そもそも見えない。
住所が出れば、それでいい。

不便になっていないから、戻す理由がない。

もし使い勝手が落ちていたら、話はまったく違っただろう。
削るなら、使う人に見えない場所を削る。


「10段階で言えば、今いくつですか」

外部通信をゼロにして、私は相談に行った。

外部通信は全廃しました、と私は説明した。
用意していたのは、そういう話だった。暗号化はどうするべきか。
データベースにしたほうがいいか。情シスのサーバーに移すべきか。

返ってきたのは、まったく別の問いだった。

どのレベルのセキュリティで情報管理をしなければならないのか、そこが重要。
それがなければセキュリティ方針は立てられない。
10段階で言えば今2か3ですわ、というのであれば、今のままでもええんかな。

最初、意味が分からなかった。

しばらくして分かった。私が持って行った問いは、全部その次の話だったのだ。

暗号化すべきかどうかは、扱っている情報がどれだけ重いかで決まる。
サーバーに移すべきかどうかも同じ。
守るべき水準が決まっていないのに、対策の要否は判断できない。

私はずっと「何を足すか」を考えていた。聞かれたのは「どこまで守るべきか」だった。

表を作った

宿題として出されたのは、扱っている情報の重要度を、自分たちで決めることだった。

私は表を作った。情報の種類ごとに、5つの欄を並べた。
何が入るか。どこに保存されているか。今は誰が見られるか。
漏れたときに困ること。そして重要度。

同時に、10段階の目盛りの意味も自分で定義した。
「1〜2は社外に出ても実害がほとんどない」
「5〜6は取引先に迷惑がかかる、信用に関わる」——というふうに。
目盛りの意味を決めないと、数字を書いても伝わらない。

出した答えは、5〜6だった。

理由は明快で、取引先の名前と住所、そこへ何をいくつ出したかが、1件のデータにまとまって残っているからだ。

水準を決めると、「やらないこと」が決まった

ここが、いちばん大きな発見だった。

5〜6という水準を置いた瞬間、やらなくていいことが決まった。

暗号化。データベース化。情シスのサーバーへの移管。
どれも、7〜8の水準で必要になるものだった。5〜6では必須にならない。

代わりに必要なのは、3つだけだった。

  1. 共有フォルダのアクセス権を、業務に必要な人に限定する
  2. 画面を通さずにデータを直接読み書きできる状態を塞ぐ
  3. 操作ログを、業務に必要な人だけが読める状態にする

費用はゼロ。業務への影響もほぼない。

「対策をどこまでやるか」で悩んでいたときは、終わりが見えなかった。
水準を決めたら、やることが3つに絞れた。

守る水準を決めるというのは、やることを決める作業ではなく、やらないことを決める作業だった。

もう一つ言われたこと

同じ打ち合わせで、こうも言われた。

漏洩を100%防ぐことはできない。漏洩した際に調査できる体制を持つことが重要。

これも、私の発想にはなかった。私は「防ぐ」ことしか考えていなかった。

これを受けて、操作ログを実装した。誰が、いつ、どの依頼を扱ったか。

このとき一つだけ気をつけたのは、依頼の中身をログに残さないことだ。
品目名も数量も取引先名も書かない。受付番号だけを残す。

ログ自体が第2のデータベースになってしまえば、ログが漏れたときに同じことが起きる。
守るために作ったものが、守るべきものになっては意味がない。

できていないことを、自分から書いた

資料の「現状」の欄には、評価を4種類だけ書いた。
できている/意図してそうしている/一部できている/できていない。

そして、できていないものは、そう書いた。
共有フォルダのアクセス権は未設定です、誰でも開けます、と。

操作ログについても、限界を書いた。
Windowsのログオン名を借りているだけで、パスワードの照合はしていない。
だから「識別」であって「認証」ではない。名乗りを偽ることは技術的には可能だ、と。

隠したくなる気持ちはあった。
でも、隠したところで、相手はその道の専門家である。
自分から出せば、話は「その限界を許容できるか」だけに絞られる。
指摘されてから出すと、そこから先の話が全部疑われる。


おわりに

AIを使えば、動くものは速く作れる。私のような現場の人間でも作れる。

けれど、AIは外部依存も一緒に足してくる。
しかも、こちらが頼んだ覚えのないものまで。

半年かけて作ったものに、3か所あった。
1つは自分で気づいた。残る2つは、気づけなかった。

だから、作り終わってから探すのでは遅い。
機能を1つ足したら、通信が1本増えていないかを見る。

そして、消したあとには運用が残る。
外に任せていたものを自分で持つというのは、そういうことだった。

正直に言えば、伝え聞いた形で止められたときは、もやもやした。
何が「脆弱」なのか、直接聞けたわけではない。説明会も流れた。

ただ、いま振り返ると——あの指摘がなければ、私は資料を作らなかった。
資料を作らなければ、「一切ありません」と書くこともなかった。
書かなければ、確かめもしなかった。

外部通信は3か所とも残ったまま、本運用に入っていたはずだ。

いま、システムは検証の段階にある。
使ってもらっている人からは、「早く導入してほしい」と言われている。
更新の仕組みは、まだ決まっていない。

続きは、また書きます。


この記事は Zenn にも掲載しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?