見出し画像

【IT】ソースコード用簡易個人情報マスキングツール(Svelte+Tailwind CSS)

皆さま
こんにちは

最近では、ChatGPTやGeminiなどのAIチャットを使って、プログラムの作成や修正を行う方も多いと思います。

こうしたやり取りでは、ソースコードやエラーログをそのまま貼り付ける場面が多くありますが、その中に APIキー・メールアドレス・ユーザー名 などの個人情報が含まれていることがあります。
これらを投稿前に毎回手作業で置き換えるのは、正直かなり手間です。

そこで今回は、PCローカル(スタンドアロン)で動作する「簡易マスキングツール」 を作成します。インターネット接続不要で、送信リスクをゼロにしながら、一発でコードやログを安全な形に変換できます。

本記事は、以下の2パート構成です。
無料パート:最小構成での作り方(誰でも試せる)
有料パート:より多くのケースに対応した拡張版コード & 編集可能なマスク設定ファイル
ご注意:本ツールは“漏れを最小化”する学習用サンプルです。完全な匿名化を保証するものではありません。 重要情報の外部共有前には目視確認社内ポリシーに従ったレビューを必ず実施してください。

💡こんな人におすすめ
AI にソースコードを貼る前に一発で個人情報を消したい
インターネットに送信しないオフライン処理を求めている
・自分用にマスクルールを簡単に編集したい


1. 環境準備

🖥 開発環境

  • PC:MacBook Air (M1, macOS 14.5)

  • フレームワーク:Svelte v5

  • 言語:TypeScript

  • 実行方法:ブラウザで動作するオフラインアプリ(サーバ不要)

※ 本記事の手順は macOS(Apple Silicon)環境でのみ検証済み です。
WindowsやLinuxでも動作する可能性はありますが、未検証のため動作保証はできません。

a. 前提条件

npm と nodeがインストールされていること確認します。
未導入の場合は、過去記事をご参照ください。

$ npm -v
11.3.0

$ node -v
v22.12.0

b. Svelteのインストール

以下のコマンドでインストールします。
今回は、Svelte単体をTypeScriptを選択します。

$ npm create vite@latest

> npx
> create-vite

│
◇  Project name:
│  mask-app-log-svelte1
│
◇  Select a framework:
│  Svelte
│
◇  Select a variant:
│  TypeScript
│
◇  Scaffolding project in /Users/user/info_remval/mask-app-log-svelte1...
│
└  Done. Now run:

  cd mask-app-log-svelte1
  npm install
  npm run dev

$ cd mask-app-log-svelte1

$ npm install

c. Svelteのクリーンアップ

src/app.cssは空に
src/lib/Counter.svelteは削除します。

src/App.svelteは、元々のコードを削除して以下の通りとします。
(最小構成)

<script lang="ts">

</script>

<main>
  <h1 class="text-3xl font-bold underline">
    Hello world!
  </h1>


</main>

<style>
  /* 必要に応じて Tailwind CSS の代わりにここに通常の CSS を追加してもOK */
</style>

d. Tailwind CSSの導入

今回、viteで導入しておりますのでTailwind CSSのサイトの案内通りに
導入します。

プロジェクトディレクトリに移動してらインストールします。

$ cd mask-app-log-svelte1

$ npm install tailwindcss @tailwindcss/vite

added 84 packages, and audited 129 packages in 3s

19 packages are looking for funding
  run `npm fund` for details

次にvite.config.tsにtailwindcssの設定を追加します。
※合わせてbuild時の相対パスの設定を行います。

project-dir/vite.config.ts

import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import tailwindcss from '@tailwindcss/vite'  // →追加

// https://vite.dev/config/
export default defineConfig({
  base: './',                      // ← 相対パスに強制
  plugins: [
    svelte(),
    tailwindcss(),                 // →追加
 ], 
})

app.cssにtailwindcssの呼び出し設定を挿入します。
※元のCSSは、削除してから挿入ください。

src/app.css

@import "tailwindcss";

2.マスキングツール作成(学習用サンプル)

1.  🧼 sanitizeText.ts の追加

src/sanitizeText.ts にマスク処理のロジックを定義します。
(学習用のサンプルコードです。)

// 学習用のサンプルコードです。

// src/lib/sanitizeText.ts

/**
 * 個人情報や機密情報を含む可能性のある行を自動でマスクします
 * チャットや掲示板投稿前の事前チェックに使用します
 * 実際のマスクパターンをこのファイルに追加していきます。
 */
export function sanitizeText(input: string): string {
  return input
    // ✅ メールアドレス
    .replace(/[\w.-]+@[\w.-]+\.\w+/g, '[email masked]')

    // ✅ パスワード代入っぽい行
    .replace(/(password\s*=\s*)['"].+?['"]/gi, '$1"[masked]"')

    // ✅ ファイルパス(Linux/macOS/Windows)
    .replace(/\/home\/\w+|\/Users\/\w+|C:\\Users\\\w+/gi, '/[user]')

    // ✅ GitHubユーザー名入りURL
    .replace(/https:\/\/github\.com\/[\w-]+\//gi, 'https://github.com/[user]/')

    // ✅ コメントや署名(簡易)
    .replace(/#\s*by\s+\w+/gi, '# by [user]')

    // ✅ IPアドレス(IPv4)
    .replace(/\b\d{1,3}(?:\.\d{1,3}){3}\b/g, '[ip masked]');
}

2. 💻src/App.svelte の編集

src/sanitizeText.tsを呼び出して、入力用のテキストエリアを追加します。
(学習用のサンプルコードです。)

<!-- 学習用のサンプルコードです。 -->

<script lang="ts">
  import { sanitizeText } from './lib/sanitizeText';
  let input = '';
  let output = '';

  function handleSanitize() {
    output = sanitizeText(input);
  }

  function handleClear() {
    input = '';
    output = '';
  }
</script>

<main class="p-6 max-w-3xl mx-auto">
  <h1 class="text-2xl font-bold mb-4">SanityPaste</h1>

  <!-- 入力欄 -->
  <label for="inputText" class="block mb-2 font-semibold">入力</label>
  <textarea
    id="inputText"
    bind:value={input}
    rows="10"
    class="w-full border p-2 mb-4 rounded"
  ></textarea>

  <!-- 実行ボタン -->
  <button
    onclick={handleSanitize}
    class="bg-blue-600 text-white px-4 py-2 rounded"
  >
    マスク実行
  </button>

  <button 
    onclick={handleClear} 
    class="bg-gray-400 hover:bg-gray-500 text-white px-4 py-2 rounded"
  >
    クリア
  </button>

  <!-- 出力欄 -->
  <label for="outputText" class="block mt-6 mb-2 font-semibold">出力(マスク後)</label>
  <textarea
    id="outputText"
    readonly
    value={output}
    rows="10"
    class="w-full border p-2 bg-gray-100 rounded"
  ></textarea>
</main>

<style>
  /* 必要に応じて Tailwind CSS の代わりにここに通常の CSS を追加してもOK */
</style>

3. 🚀 ビルド

ビルドするとdist/ フォルダにビルド成果物(index.html + assets)一式が出力されます。

$ npm run build

> mask-app-log-svelte1@0.0.0 build
> vite build

vite v7.0.6 building for production...
✓ 104 modules transformed.
dist/index.html                  0.48 kB │ gzip: 0.31 kB
dist/assets/index-xxxx.css       5.67 kB │ gzip: 1.92 kB
dist/assets/index-xxxx.js       23.06 kB │ gzip: 9.68 kB

3.動作テスト

1. プレビューにて確認

$ npm run preview

> mask-app-log-svelte1@0.0.0 preview
> vite preview

  ➜  Local:   http://localhost:4173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

メールアドレスやパスワードがマスクされていることを確認
※http://localhost:4173/ で確認

2. buildしたindex.htmlを直接起動

file://index.htmlは、
エラーとなり画面は真っ白となる。
CORS(Cross-Origin Resource Sharing、クロスオリジン・リソース・シェアリング)のため、ファイルから起動の際は、エラーとなる。

CORS(Cross-Origin Resource Sharing、クロスオリジン・リソース・シェアリング)とは、異なるオリジン(ドメイン、ポート、またはプロトコルが異なる)間でのリソース共有を許可・制御するための仕組みです。主にWebブラウザが関与するセキュリティ機構であり、JavaScriptで外部のAPIやリソースにアクセスする際に関係してきます。

🔒 なぜCORSが必要か?

ブラウザには「同一オリジンポリシー(Same-Origin Policy)」というセキュリティ制限があります。これは、あるWebページが自分と異なるオリジンのリソースに自由にアクセスすることを防ぐための仕組みです。

例:https://example.com にあるWebページのJavaScriptは、通常、https://api.example.com や http://anotherdomain.com にあるAPIには直接アクセスできません。

これでは、毎回サーバを起動するか、VSCodeのGo Liveで使用するかになり、利便性がおちます。
かと言ってVercel等にアップするのは、個人情報をマスクする意味合いで
いただけません。
次項で対策を行なって行きます。
※セキュリティを弱めた方法でChromeを起動すると確認できますが、おすすめではありません。

<<ご参考>>セキュリティを無効化したChromeの起動方法

open -na "Google Chrome" --args --disable-web-security --user-data-dir="/tmp/chrome"

4.対策

1. 原因と対策方針

原因:
CORSポリシーにより、file:// から読み込もうとすると拒否されます。

  • index.html の中で <script type="module" src="/assets/index-xxxx.js"> のようにビルドされた JavaScript を読み込んでいます。

  • しかし、file:// では相対パスやモジュール解決がうまく機能しないため、JSの読み込みに失敗し、結果として真っ白になります。

対策:
index.htmlへJavaScriptもCSSも組み込むこととします。

2. 対策(index.htmlへ集約)

  • dist/index.html を読み込み

  • dist/assets/*.css を取得 → <head> に <style>…</style> を挿入

  • dist/assets/*.js を取得 → </body> 直前に <script>…</script> を挿入

  • 出力先:dist/index_standalone.html(単一ファイル

  • 実行:bash make-standalone.sh(購入者向けに配布)

※file:// ではビルド後の分割ファイル解決に失敗しやすいため、依存を1枚にまとめて読み込みエラーを避けます。

$ ./make-standalone.sh
🔧 スタンドアロンHTMLを生成中...
✅ favicon付きスタンドアロンHTMLを生成しました: dist/index_standalone.html

3. 再確認

出力された「dist/index_standalone.html」をダブルクリックして
ページを表示します。
マスクされるか確認します。


⭐️ここまでのまとめ(無料部分)

・Svelte + Vite + Tailwind の最小プロジェクトが構築
簡易マスキングがローカルで動作することを確認
・スタンドアロンHTML化の流れ理解
となります。
この続きを(有料版:500円)では、実運用向けの完成コード設定例を提供します。

アプリ概要

このツールは、開発や運用の現場で扱うコードやログ内の特定パターンの個人情報を自動的にマスク(置き換え)するスクリプトです。
環境変数、APIキー、メールアドレス、住所、電話番号、法人名、IPアドレスなど、事前に定義されたパターンに基づき検出し、安全な形式に変換します。

開発者やチームがソースコードや共有ログを外部に渡す際、情報漏洩のリスクを減らすことを目的としています。

主なマスク対象とルール

このツールは、スクリプト内で設定された関数と外部JSON(mask-config.json)で設定されたルールに基づき、以下の情報を自動マスクします。

  • 環境変数(.env形式・コード内)
    APIキーやアクセストークンなど
    除外パターンに記載されたものはマスク対象外

  • メールアドレス
    一般的な形式(user@example.comなど)を検出してマスク

  • 郵便番号と住所
    都道府県名のみ残して市区町村以下をマスク(漢字のみ対応)
    スペース入りの住所は未対応
    除外住所リストにある固有名詞(大学名など)はマスク対象外

  • 氏名(漢字・カタカナ)
    sensitiveWords に登録された名前のみマスク対象
    JSON形式で外部管理(mask-config.json)

  • 電話番号
    固定電話・携帯電話の形式を検出してマスク

  • 法人名
    「株式会社」「有限会社」などの前株・後株を除き、企業名部分をマスク

  • IPアドレス
    IPv4形式を検出してマスク

  • コメント内の特定キーワード
    author, reviewer, updated などのキーワードを含むコメントをマスク
    除外パターンに記載された場合は対象外

  • JSON形式のキーと値
    JSON構造内で、mask-config.json に定義されたキー(例:email, phone, password など)に該当する場合、その値をマスク
    除外パターンに一致するキーや値は対象外

注意事項(必ずお読みください)

  • 対象範囲:本コードは作者が把握している一部パターンのみをマスクします。完全な匿名化は保証しません

  • 運用前確認:機微情報の外部共有前に、目視確認社内ポリシーに沿ったレビューを必ず実施してください。

  • カスタマイズ:不足分は mask-config.json の編集やコード修正で拡張可能です(サポート/個別改修は行いません)。

  • 利用条件:購入者の個人利用に限る。再配布・販売は禁止です。

  • 免責:本コードの利用により生じたいかなる損害やトラブルについて、作者は一切責任を負いません。

  • 検証環境:macOS(Apple Silicon)。Windows/Linux は挙動差の可能性あり。

ここから先は

1,597字 / 7ファイル

¥ 500

この記事が気に入ったらチップで応援してみませんか?