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?

ブラウザのJavaScriptバンドルに漏洩したシークレットを検出する方法

0
Posted at

ブラウザのJavaScriptバンドルに漏洩したシークレットを検出する方法

問題

シングルページアプリケーションやライブラリをバンドルすると、開発中にハードコードされたAPIキー、トークン、署名鍵などがそのままソースコードに残ることがあります。これらのシークレットは、公開されたバンドルファイルから容易に抽出され、不正利用のリスクとなります。

メカニズム

バンドル内のシークレットを検出する典型的なフローは次の通りです。

  1. バンドルの取得
    ビルドアーティファクト(例: main.js, chunk.vendors.js)をHTTP経由またはCIアーティファクトから取得します。
  2. トークン化とパターンマッチ
    ファイルをUTF‑8テキストとして読み込み、正規表現や構文解析で以下のようなパターンをスキャンします。
    • AKIA[0-9A-Z]{16} (AWSアクセスキー)
    • sk_live_[0-9a-zA-Z]{24} (Stripeライブシークレットキー)
    • eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 (JWTのヘッダー)
    • -----BEGIN PRIVATE KEY----- (PEM形式の秘密鍵)
  3. コンテキストフィルタ
    マッチした文字列がコメントや文字列リテラル内にあるか、実際にコードで使用されているかを判定します。たとえば、"API_KEY": "sk_test_…" のようなオブジェクトリテラルは使用されている可能性が高く、単なるコメント内の例は除外します。
  4. エントロピー評価
    高いシャノンエントロピー(例: 4.0以上)を持つトークンは、ランダム性が高く本物のシークレットである可能性が高いため、スコアリングに利用します。
  5. 結果の報告
    ファイル名、行番号、マッチした文字列、そして推定リスクレベルを出力します。

例

以下は、Webpackで生成されたバンドルからAWSシークレットキーを検出する簡単なNodeスクリプトです。

const fs = require('fs');
const path = require('path');

const AWS_SECRET_REGEX = /[A-Za-z0-9\/+]{40}/; // 簡略化された例

function scanBundle(filePath) {
  const content = fs.readFileSync(filePath, 'utf8');
  const lines = content.split('\n');
  const findings = [];

  lines.forEach((line, idx) => {
    const match = line.match(AWS_SECRET_REGEX);
    if (match) {
      // ここでは単純にマッチを報告。実際はコンテキストフィルタを追加
      findings.push({ file: filePath, line: idx + 1, secret: match[0] });
    }
  });

  return findings;
}

// 使用例
const bundleDir = './dist';
const bundleFile = path.join(bundleDir, 'main.js');
const results = scanBundle(bundleFile);
if (results.length > 0) {
  console.log('潜在的なシークレットが見つかりました:');
  results.forEach(r => console.log(`${r.file}:${r.line} → ${r.secret}`));
} else {
  console.log('シークレットは検出されませんでした。');
}

このスクリプトは、バンドルファイルを1行ずつ読み込み、正規表現で疑似的なAWSシークレットキーを抽出します。実際の運用では、キーの前後にある変数名やオブジェクトキーをチェックし、エントロピーを計算して偽陽性を減らします。

注意点

  • ミニファイと難読化
    本番バンドルはミニファイされ、変数名が短縮されるため、単純な文字列検出では漏れが生じます。AST(抽象構文木)を使ってリテラル値を取得すると、ミニファイ後でも検出しやすくなります。
  • ソースマップの利用
    ソースマップが公開されている場合、元のソースコードに戻してシークレットを探すと精度が向上します。ただし、ソースマップ自体も機密情報を含む可能性があるため、公開しない方が安全です。
  • ライセンスとサードパーティコード
    node_modules 内のライブラリにもシークレットが含まれていることがあります。自分のコードだけでなく、依存関係のバンドルも対象に含めるか、別途スキャンする必要があります。
  • 頻度とトリガー
    プルリクエストごと、または夜間バッチでバンドルアーティファクトをスキャンする仕組みをCIに組み込むと、漏洩を早期に検出できます。

Learn more about detecting exposed secrets in client bundles.

Details, and a free check: https://keydrift.dev/scan?utm_source=qiita&utm_campaign=socialhat&utm_medium=social&vsr=a39abf9e46308bbf7e82

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?