👏
漏洩リスクのある情報を持たないようにする
概要
生成AIの普及により、プログラミング知識が浅くても短時間でアプリケーションを構築できるようになりました。一方で、セキュリティの観点がおろそかになり、漏洩リスクの高いデータを扱う設計・実装が大量に生まれています。
もちろん適切なポリシー設定など正規の対応もありますが、ここでは個人的に最強の対策である「そもそも危険なデータを持たない」という対応を考えてみたいと思います。
具体的には以下4点を扱いますが、他にも良い案があればぜひ、教えてください。
- メールアドレスを持たずに認証する
- 生年月日を入力させず統計データを得る
- 画像に隠れる個人を特定しうる情報の削除
- とにかくなんでも入力可能を避ける
1.メールアドレスを持たずに認証する
課題:メールアドレスを直接保持すると、運用中のDB流出やメール誤送信時にユーザー情報が漏洩するリスクが高まる。
対策
- OAuth/OIDCで Google, Apple, Twitter など信頼できるアイデンティティプロバイダーを利
- ユーザーには「○○アカウントでログイン」だけを提示し、メールアドレスはプロバイダー側で管理
2.生年月日は「生まれ年」のみ取得
課題: フルの生年月日を保持すると、個人が特定できるうえ、誕生日認証や二要素認証の裏口になりうる。
対策
- 生まれた「年」のみを入力させ、データベースには整数(例:birth_year: 1985)で保存
- 年齢確認が必要な場合は「満◯歳以上かどうか」の判定にとどめ、詳細データは非保持
3.画像のEXIF情報を削除
課題: スマホで撮影した写真には緯度経度、撮影日時、端末情報などプライバシーを侵害するEXIFメタデータが含まれる。
対策
- アップロード前にクライアント側(JavaScript)またはサーバー側でEXIF削除処理を実装
ライブラリ例:piexifjs
import React from 'react';
import piexif from 'piexifjs';
export default function CompactExifStripper({ file }: { file: File }) {
const upload = async () => {
// 1. File→DataURL
const dataUrl = await new Promise<string>((res, rej) => {
const r = new FileReader();
r.onload = () => res(r.result as string);
r.onerror = () => rej(r.error);
r.readAsDataURL(file);
});
// 2. piexifjs で除去
const stripped = piexif.remove(dataUrl);
// 3. DataURL→Blob
const blob = await fetch(stripped).then(r => r.blob());
// 4. アップロード
const form = new FormData();
form.append('image', blob, file.name);
await fetch('/api/upload', { method: 'POST', body: form });
};
return <button onClick={upload}>アップロード(EXIF除去)</button>;
}
4.自由入力欄に入力させない
課題:自由入力欄にユーザーが誤って以下のような個人情報を入れてしまうことがある。
対応
- PII検出(ブラックリスト方式)あらかじめ定義した正規表現で「これは個人情報っぽい」と見つけたらエラー/警告
// src/utils/detectPii.js
export const piiPatterns = {
email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
phone: /0\d{1,4}-\d{1,4}-\d{4}/, // 090-1234-5678 等
postal: /\d{3}-\d{4}/, // 123-4567
address: /(東京都|北海道|.{2,3}県).+(市|区|町|村).+/, // 簡易的な日本の住所検出
};
export function detectPII(text) {
return Object.entries(piiPatterns)
.filter(([, regex]) => regex.test(text))
.map(([key]) => key);
}
import React, { useState } from 'react';
import { detectPII } from './utils/detectPii';
export function FreeTextInput() {
const [error, setError] = useState('');
const handleBlur = (e) => {
const value = e.target.value;
const found = detectPII(value);
if (found.length) {
setError(`${found.join('、')} が入力されています。個人情報は入力しないでください。`);
} else {
setError('');
}
};
return (
<div>
<textarea
placeholder="ご意見・ご要望など"
onBlur={handleBlur}
rows={4}
style={{ width: '100%' }}
/>
{error && <p style={{ color: 'red', marginTop: 4 }}>{error}</p>}
</div>
);
}
5.最後に
安全で楽しい開発をしましょう!
Discussion