- AI ⚙️
AI生成コードの確認チェックリスト|品質とセキュリティ
AIが書いたコードは、動かす前の5分で「実在しない関数やパッケージ」「秘密情報の直書き」「入力の検証」「エラー処理」「テストの有無」の5点を先に見ると、受け入れてよいかを早く判断できます。 この5点は、見た目が整っていても起こりやすく、しかもツールと短いコマンドで確かめられるものです。
この記事は、AIが生成したコードを自分のリポジトリに取り込む前の確認だけを扱います。観点・確認方法・コマンド例・合否欄を持つ15項目のチェックリスト(Markdown と CSV)、人が読む項目とツールに任せる項目の対応表、pip と npm でパッケージの実在とバージョンを確かめるコマンドを、実際に動かした出力つきで載せました。AIにレビューを頼むプロンプトや、人が書いたコード全般のレビュー観点は対象外です。
確認環境:Ubuntu 24.04.4、Python 3.11.15、pip 24.0、Node.js 22.22.2、npm 10.9.7、git 2.43.0、ruff 0.15.11、mypy 1.20.2、bandit 1.9.4、detect-secrets 1.5.0、pip-audit 2.10.1、pytest 9.1.1(確認日 2026-10-06)。掲載したコマンドの出力は、この環境で実行したものです。題材のコードは、AIの出力に起こりやすい点を1ファイルに集めて手で書いた見本で、特定のモデルの出力ではありません。
この記事の結論
- 最初の5分で見る5点:実在しない関数・パッケージ/秘密情報の直書き/入力の検証/エラー処理/テストの有無。
- ツールに任せられるものは先にツールで:型チェックが「無い関数」を、シークレット検出が「直書きのトークン」を、脆弱性検査が「依存パッケージの既知の問題」を見つけます。
- 人が読むのは3つ:頼んでいない変更が混ざっていないか、仕様どおりか、ライセンスに問題がないか。
- 「エラーなく読み込める」と「正しい」は別:今回の見本は構文チェックを通りましたが、型チェックでは2件、セキュリティ検査では5件の指摘が出ました。
AI生成コード確認の早見表
| 順番 | 最初の5分で見る点 | 何が起きるか | いちばん早い確かめ方 |
|---|---|---|---|
| 1 | 実在しない関数・パッケージ | 実行時に止まる。名前の似た別パッケージを入れてしまう | mypy ファイル名、pip index versions 名前、npm view 名前 version |
| 2 | 秘密情報の直書き | トークンやパスワードがリポジトリに残る | detect-secrets scan ファイル名 |
| 3 | 入力の検証 | 想定外の文字列がSQLやコマンドにそのまま入る | bandit ファイル名 と、入力を受ける関数を目で読む |
| 4 | エラー処理 | 例外を握りつぶして、止まった理由が分からなくなる | ruff check ファイル名(E722)、except を検索 |
| 5 | テストの有無 | 動いたように見えても確かめた証拠が無い | pytest -q の件数を見る |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「AI生成コードの確認チェックリスト|品質とセキュリティ」
なぜ「動かす前」に確認するのか
AIが書いたコードは、インデントも命名も整っていて、読みやすく見えます。そのぶん、存在しない関数を呼んでいる、トークンを例として書き込んでいる、といった点が目に留まりにくくなります。
公式の資料も、人による確認を前提にしています。GitHub Docs は、Copilot が生成するコードについて「一見正しく見えても、意味や構文が正しくないことがある」「セキュリティ上の弱点などを含むことがある」と説明し、提案を注意深く確認してテストするよう求めています。OWASP の「LLM09:2025 Misinformation」は、よくある例として、モデルが安全でない、または存在しないライブラリを提案することを挙げ、生成された内容を独立に確かめることを勧めています。
特にパッケージ名は、確かめずに pip install や npm install を実行すると、その時点でコードが手元の環境で動くため、動かす前の確認が向いています。
題材:確認する見本のコード
架空の備品貸出ツールの一部として、次の lend.py を受け取ったとします。AIの出力に起こりやすい点を、わざと1ファイルに集めた見本です。
import json
from typing import List
import subprocess
import sqlite3
import requests_cache_plus
API_TOKEN = "ghp_x7Kq2mVb9TtWm4RrPp7QaZ3cLd8eFh1GjN5s"
def load_items(path: str) -> List[dict]:
with open(path) as f:
return json.load_file(f)
def find_item(conn: sqlite3.Connection, name: str):
cur = conn.execute(f"SELECT id, name FROM items WHERE name = '{name}'")
return cur.fetchall()
def export(dirname: str) -> None:
try:
subprocess.run("tar czf backup.tgz " + dirname, shell=True)
except:
pass
トークンの文字列は、形だけをまねた架空の値です。まず、構文として読み込めるかを確かめます。
python3 -m compileall -q lend.py; echo "exit=$?"
exit=0
構文チェックは通りました。 ここから先の5点は、構文チェックでは見つからないものです。
最初の5分で見る5点(コマンドと実際の出力)
1. 実在しない関数・パッケージ
型チェックの mypy は、標準ライブラリやインストール済みパッケージの定義と突き合わせて、無い属性・無いモジュールを報告します。
mypy lend.py
lend.py:5: error: Cannot find implementation or library stub for module named "requests_cache_plus" [import-not-found]
lend.py:5: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
lend.py:12: error: Module has no attribute "load_file" [attr-defined]
Found 2 errors in 1 file (checked 1 source file)
json.load_file という関数は標準ライブラリにありません(正しくは json.load)。Python で直接確かめることもできます。
python3 -c "import json; print(hasattr(json, 'load_file'), hasattr(json, 'load'))"
False True
次に、requests_cache_plus というパッケージが公開されているかを、インストールせずに確かめます。
pip index versions requests_cache_plus
WARNING: pip index is currently an experimental command. It may be removed/changed in a future release without prior warning.
ERROR: No matching distribution found for requests_cache_plus
実在するパッケージなら、公開されているバージョンの一覧が返ります(長いので一部を省略しています)。
pip index versions requests
requests (2.34.2)
Available versions: 2.34.2, 2.34.1, 2.34.0, 2.33.1, 2.33.0, 2.32.5, 2.32.4, 2.32.3, 2.32.2, …(省略)…
INSTALLED: 2.33.1
LATEST: 2.34.2
npm の場合は npm view を使います。公開されていない名前は 404 になります。
npm view left-pad-utils-plus version
npm error code E404
npm error 404 Not Found - GET https://registry.npmjs.org/left-pad-utils-plus - Not found
npm error 404
npm error 404 'left-pad-utils-plus@*' is not in this registry.
実在する場合は、バージョン・ライセンス・最初の公開日をまとめて見られます。
npm view express version license time.created
version = '5.2.1'
license = 'MIT'
time.created = '2010-12-29T19:38:25.450Z'
名前が見つかっただけで終わりにせず、公開日・ライセンス・配布元のページもあわせて見ます。 名前がよく似た別のパッケージが公開されていることがあるためです。OWASP の LLM09:2025 は、AIがよく提案する実在しない名前を先回りして公開する手口があることを説明しています。
2. 秘密情報の直書き
detect-secrets scan lend.py
出力は JSON です。該当した行と種類だけを抜き出すと、次のとおりでした。
lend.py 7 Base64 High Entropy String
lend.py 7 GitHub Token
7行目の文字列が、トークンの形として検出されました。値は環境変数などコードの外から読む形に直し、もし本物の値だった場合は、コードから消すだけでなく発行元で無効にして作り直します。
リポジトリ側の備えとして、GitHub にはプッシュ保護があります。GitHub Docs の説明では、シークレットを含むプッシュを、リポジトリに届く前に止める機能です。
3. 入力の検証
bandit -q lend.py
出力から、指摘・重大度・位置の行を抜き出したものです。
>> Issue: [B404:blacklist] Consider possible security implications associated with the subprocess module.
Severity: Low Confidence: High
Location: ./lend.py:3:0
>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: 'ghp_x7Kq2mVb9TtWm4RrPp7QaZ3cLd8eFh1GjN5s'
Severity: Low Confidence: Medium
Location: ./lend.py:7:12
>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction.
Severity: Medium Confidence: Medium
Location: ./lend.py:16:23
>> Issue: [B602:subprocess_popen_with_shell_equals_true] subprocess call with shell=True identified, security issue.
Severity: High Confidence: High
Location: ./lend.py:22:8
>> Issue: [B110:try_except_pass] Try, Except, Pass detected.
Severity: Low Confidence: High
Location: ./lend.py:23:4
16行目は入力をそのままSQL文に連結し、22行目は入力をそのままシェルのコマンドに連結しています。どちらも、OWASP Top 10:2025 の「A05:2025 Injection」にあたる書き方です。SQLはプレースホルダ、外部コマンドは引数のリストで渡す形に直します。
ツールが見つけるのは「連結している」という形までです。文字数の上限、空文字、想定する文字の種類といった入力の決まりは仕様から来るので、人が読んで確かめます。
4. エラー処理
ruff check lend.py --output-format concise
lend.py:5:8: F401 [*] `requests_cache_plus` imported but unused
lend.py:23:5: E722 Do not use bare `except`
Found 2 errors.
[*] 1 fixable with the `--fix` option.
23行目の except: と pass の組み合わせは、圧縮がうまくいかなくても何も知らせずに先へ進みます。OWASP Top 10:2025 には「A10:2025 Mishandling of Exceptional Conditions」(例外的な状況の扱い)という分類があります。捕まえる例外の種類を絞り、捕まえたら記録するか呼び出し元に伝える形にします。
5. テストの有無
python3 -m pytest -q; echo "exit=$?"
no tests ran in 0.00s
exit=5
テストが1件も無いとき、pytest の終了コードは 5 でした。「エラーが出ていない」ではなく「何件通ったか」を見ます。
直した後のコードと再確認
5点を直したものが次のコードです。
import json
import os
import sqlite3
import subprocess
from pathlib import Path
API_TOKEN = os.environ.get("LEND_API_TOKEN", "")
def load_items(path: str) -> list[dict]:
with open(path, encoding="utf-8") as f:
return json.load(f)
def find_item(conn: sqlite3.Connection, name: str) -> list[tuple]:
if not name or len(name) > 50:
raise ValueError("name は1〜50文字で指定してください")
cur = conn.execute("SELECT id, name FROM items WHERE name = ?", (name,))
return cur.fetchall()
def export(dirname: str) -> None:
if not Path(dirname).is_dir():
raise ValueError(f"フォルダがありません: {dirname}")
subprocess.run(["tar", "czf", "backup.tgz", dirname], check=True)
テスト(test_lend.py)も足します。引用符を含む入力が、SQLの一部ではなくただの文字列として扱われることを確かめるテストを入れています。
import sqlite3
import pytest
from lend import find_item
def make_conn() -> sqlite3.Connection:
conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT)")
conn.execute("INSERT INTO items (name) VALUES ('プロジェクター')")
return conn
def test_find_item_hit():
assert find_item(make_conn(), "プロジェクター") == [(1, "プロジェクター")]
def test_find_item_quote_is_data():
assert find_item(make_conn(), "' OR '1'='1") == []
def test_find_item_empty_is_rejected():
with pytest.raises(ValueError):
find_item(make_conn(), "")
同じコマンドをもう一度流した結果です。
ruff check .
mypy lend.py
detect-secrets scan lend.py # results が空の {} になる
python3 -m pytest -q
All checks passed!
Success: no issues found in 1 source file
3 passed in 0.01s
bandit は、直した後も重大度 Low の指摘を3件返しました(B404・B607・B603。いずれも外部コマンドを呼んでいることへの注意)。Medium と High が消えたことを確かめ、Low は「入力を確かめてから引数のリストで渡している」ことを人が読んで判断します。指摘を0件にすること自体が目的ではありません。
AI生成コードに特有の4つの確認
ここまでの5点に加えて、AIが書いたコードで起こりやすい点が4つあります。
存在しない API・引数
関数名は実在しても、引数名や戻り値が違うことがあります。型チェックで見つからない場合は、公式ドキュメントの該当ページを開いて、関数名・引数・戻り値の3つを突き合わせます。AIに「根拠の URL を添えて」と頼んだ場合も、その URL を自分で開いて確かめます。
以前の書き方
学習した時点の書き方が出てくることがあります。Python なら、ruff の UP ルールが、現在のバージョンで置き換えられる書き方を知らせてくれます。
ruff check lend.py --select UP --target-version py311 --output-format concise
lend.py:2:1: UP035 `typing.List` is deprecated, use `list` instead
lend.py:10:30: UP006 [*] Use `list` instead of `List` for type annotation
Found 2 errors.
[*] 1 fixable with the `--fix` option.
依存パッケージのバージョンも同じです。AIが書いた requirements.txt に requests==2.19.1 とあった場合、脆弱性検査にかけると次のようになりました(先頭だけ掲載)。
pip-audit -r requirements.txt
Found 37 known vulnerabilities in 3 packages
Name Version ID Fix Versions
-------- ------- --------------- -------------
requests 2.19.1 PYSEC-2018-28 2.20.0
requests 2.19.1 PYSEC-2018-28 2.20.0
requests 2.19.1 PYSEC-2023-74 2.31.0
requests 2.19.1 PYSEC-2023-74 2.31.0
…(省略)…
指定を requests==2.34.2 に変えると No known vulnerabilities found になりました。依存パッケージの確認は、OWASP Top 10:2025 の「A03:2025 Software Supply Chain Failures」に対応します。npm では npm audit が同じ役割で、lodash の 4.17.15 を指定した package-lock.json に対して実行すると「1 high severity vulnerability」と報告されました。
指示していない変更
「この関数だけ直して」と頼んでも、ほかのファイルや設定が書き換わっていることがあります。差分の一覧を先に見て、頼んだ範囲と一致するかを確かめます。
git diff --stat
git status --short
lend.py | 2 +-
requirements.txt | 1 +
settings.py | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
M lend.py
M requirements.txt
A settings.py
この例では、lend.py の1行だけを頼んだのに、依存パッケージが1つ増え、設定ファイルが1つ新しくできています。増えた依存は「1. 実在しない関数・パッケージ」の手順で確かめ、頼んでいないファイルは取り込むかどうかを分けて判断します。
ライセンス
確認するのは2つです。追加された依存パッケージのライセンスと、生成されたコードそのものが公開されているコードとよく似ていないかです。
依存パッケージのライセンスは、次のコマンドで見られます。
pip show requests | grep -E '^(Name|Version|License)'
npm view express license
Name: requests
Version: 2.33.1
License: Apache-2.0
license = 'MIT'
生成されたコードが公開コードと似ているかどうかは、使っているツールに一致を知らせる機能があればそれを使い、長いまとまりがそのまま出てきたときは出どころを調べます。利用してよいかどうかの最終判断は、自社の規程と法務の確認に従ってください。この記事は法律上の助言ではありません。
AI生成コードの確認チェックリスト15項目
受け入れ前に上から順に埋める表です。コマンド例は Python と npm のものなので、言語に合わせて置き換えてください。
| No | 区分 | 観点 | 確認方法 | コマンド例 | 合否 |
|---|---|---|---|---|---|
| 1 | 最初の5分 | 呼んでいる関数・属性が実在する | 型チェックを通す。出なければ公式ドキュメントで関数名・引数・戻り値を突き合わせる | mypy ファイル名 |
□ |
| 2 | 最初の5分 | import・依存のパッケージが実在する | インストール前にレジストリへ問い合わせる | pip index versions 名前 / npm view 名前 version |
□ |
| 3 | 最初の5分 | 秘密情報が直書きされていない | シークレット検出を通す。値は環境変数などから読む | detect-secrets scan ファイル名 |
□ |
| 4 | 最初の5分 | 入力を検証している | 入力を受ける関数を読み、長さ・空・文字の種類の確認があるかを見る | bandit -q ファイル名 |
□ |
| 5 | 最初の5分 | 例外を握りつぶしていない | 範囲の広い except と pass の組み合わせを探す | ruff check ファイル名 |
□ |
| 6 | 最初の5分 | テストがあり、通っている | 通った件数を見る。0件は合格にしない | python3 -m pytest -q |
□ |
| 7 | AI特有 | 引数名・戻り値が公式ドキュメントと一致する | 該当ページを開いて突き合わせる | (公式ドキュメントを開く) | □ |
| 8 | AI特有 | 以前の書き方が残っていない | 言語のバージョンを指定してリンターを通す | ruff check --select UP ファイル名 |
□ |
| 9 | AI特有 | 依存のバージョンに既知の脆弱性がない | 脆弱性検査を通す | pip-audit -r requirements.txt / npm audit |
□ |
| 10 | AI特有 | 頼んでいない変更が混ざっていない | 変更されたファイルの一覧を、頼んだ範囲と比べる | git diff --stat |
□ |
| 11 | AI特有 | 追加された依存のライセンスを確認した | ライセンス名を見て、自社の規程と照らす | pip show 名前 / npm view 名前 license |
□ |
| 12 | AI特有 | 公開コードとよく似た長いまとまりがない | ツールの一致通知を見る。出どころを調べる | (ツールの設定を確認) | □ |
| 13 | 受け入れ前 | SQL・外部コマンドに入力を連結していない | プレースホルダ、引数のリストになっているかを読む | bandit -q ファイル名 |
□ |
| 14 | 受け入れ前 | 仕様どおりに動く | 仕様の例と境界の値を自分で1つ以上動かす | python3 -m pytest -q |
□ |
| 15 | 受け入れ前 | 自分の言葉で説明できる | 各関数が何をするかを1行ずつ言えるか確かめる | (なし) | □ |
表計算ソフトに貼るための CSV です。
No,区分,観点,確認方法,コマンド例,合否
1,最初の5分,呼んでいる関数・属性が実在する,型チェックを通す。出なければ公式ドキュメントで関数名・引数・戻り値を突き合わせる,mypy ファイル名,□
2,最初の5分,import・依存のパッケージが実在する,インストール前にレジストリへ問い合わせる,pip index versions 名前 / npm view 名前 version,□
3,最初の5分,秘密情報が直書きされていない,シークレット検出を通す。値は環境変数などから読む,detect-secrets scan ファイル名,□
4,最初の5分,入力を検証している,入力を受ける関数を読み、長さ・空・文字の種類の確認があるかを見る,bandit -q ファイル名,□
5,最初の5分,例外を握りつぶしていない,範囲の広い except と pass の組み合わせを探す,ruff check ファイル名,□
6,最初の5分,テストがあり、通っている,通った件数を見る。0件は合格にしない,python3 -m pytest -q,□
7,AI特有,引数名・戻り値が公式ドキュメントと一致する,該当ページを開いて突き合わせる,(公式ドキュメントを開く),□
8,AI特有,以前の書き方が残っていない,言語のバージョンを指定してリンターを通す,ruff check --select UP ファイル名,□
9,AI特有,依存のバージョンに既知の脆弱性がない,脆弱性検査を通す,pip-audit -r requirements.txt / npm audit,□
10,AI特有,頼んでいない変更が混ざっていない,変更されたファイルの一覧を、頼んだ範囲と比べる,git diff --stat,□
11,AI特有,追加された依存のライセンスを確認した,ライセンス名を見て、自社の規程と照らす,pip show 名前 / npm view 名前 license,□
12,AI特有,公開コードとよく似た長いまとまりがない,ツールの一致通知を見る。出どころを調べる,(ツールの設定を確認),□
13,受け入れ前,SQL・外部コマンドに入力を連結していない,プレースホルダ、引数のリストになっているかを読む,bandit -q ファイル名,□
14,受け入れ前,仕様どおりに動く,仕様の例と境界の値を自分で1つ以上動かす,python3 -m pytest -q,□
15,受け入れ前,自分の言葉で説明できる,各関数が何をするかを1行ずつ言えるか確かめる,(なし),□
人が読む項目とツールに任せる項目の違いと選び方
| 項目 | 人が読んで確かめる | ツールに任せる |
|---|---|---|
| 向いている確認 | 仕様との一致、頼んだ範囲との一致、入力の決まり、ライセンスの判断 | 型の不一致、無い属性、書式、既知の脆弱性、トークンの形 |
| 強み | 目的や背景を踏まえて判断できる | 毎回同じ基準で、短時間に全部を見られる |
| 見落としやすい点 | 量が多いと細部を読み飛ばす | 仕様の誤り、意図と違う動きは対象外 |
| かかる時間 | 差分の量に比例する | 数秒〜数十秒 |
ツールの種類ごとに、今回の見本で何が見つかったかをまとめます。
| ツールの種類 | 今回使ったもの | 見本で見つかったもの | 見つからなかったもの |
|---|---|---|---|
| 構文チェック | python3 -m compileall |
なし(通った) | 5点すべて |
| 型チェック | mypy | 無いモジュール、無い関数 | トークン、SQLの連結 |
| リンター | ruff | 使っていない import、範囲の広い except、以前の書き方(UP 指定時) | 無い関数、無いモジュール |
| セキュリティ検査 | bandit | SQLの連結、シェルへの連結、except と pass、直書きの文字列 | 無い関数 |
| シークレット検出 | detect-secrets | トークンの形をした文字列 | それ以外 |
| 依存関係の脆弱性検査 | pip-audit | 依存のバージョンにある既知の脆弱性 | コード本体の問題 |
どちらで確かめるかは、次の基準で決めます。
| 条件 | 選ぶもの |
|---|---|
| 正解が機械的に決まる(名前がある・ない、形が合う・合わない) | ツール |
| 既知の一覧と突き合わせれば分かる(脆弱性、トークンの形) | ツール |
| 仕様や依頼の内容を知らないと判断できない | 人 |
| ツールが指摘を出したが、重大度が低く文脈しだい | ツールの出力を人が読む |
| 利用条件や権利に関わる | 人(自社の規程と法務の確認に従う) |
順番は「ツール→人」が効率的です。 機械的に分かることを先に片づけておくと、人は仕様と範囲の確認に時間を使えます。
受け入れ前の手順
- 差分の一覧を見る(
git diff --stat)。頼んだ範囲と違う変更は分けておく。 - パッケージの実在を確かめる(
pip index versions、npm view)。 - ツールを通す(型チェック、リンター、シークレット検出、セキュリティ検査、脆弱性検査)。
- 指摘があれば直す。自分で直すか、指摘の文面をAIに渡して直させ、1 からやり直す。
- テストを動かし、通った件数を見る。
- 仕様の例を自分で1つ動かす。
- チェックリストの合否を埋めて取り込む。
まとめて流すときのコマンド例です。上から順に実行し、指摘が出たところで止めて直します。
git diff --stat
pip index versions パッケージ名
mypy lend.py
ruff check lend.py
detect-secrets scan lend.py
bandit -q lend.py
pip-audit -r requirements.txt
python3 -m pytest -q
確かめて分かったこと
- 構文チェックは5点のどれも見つけませんでした。
python3 -m compileallは終了コード 0 で、無い関数も無いパッケージもそのまま通りました。 - リンター(ruff の既定のルール)は、無い関数
json.load_fileを指摘しませんでした。 指摘したのは型チェックの mypy です。リンターと型チェックは見るものが違うので、両方を通します。 - テストが0件のとき、pytest は「no tests ran」と表示し、終了コードは 5 でした。 自動実行の設定によっては見逃すので、件数を見ます。
- 見本にテストだけを足して実行すると、テストは1件も実行されませんでした。 無いパッケージの import で読み込みが止まり、
ModuleNotFoundError: No module named 'requests_cache_plus'が表示されました。 - 直した後も bandit は Low の指摘を3件返しました。 指摘0件を合格条件にすると、外部コマンドを使うコードは通せなくなります。重大度で線を引き、残りは人が読みます。
pip showの License 欄が空のパッケージがありました(今回は ruff)。空のときは、配布元のページやリポジトリのライセンスファイルで確かめます。pip index versionsは実行のたびに「experimental(試験的な)コマンド」という注意を表示しました。 見つからないときの終了コードは 1 だったので、スクリプトから判定に使えます。
よくある質問
Q. AIが書いたコードはそのまま使ってもよいですか? A. 確認してから使います。GitHub Docs も、生成されたコードは注意深く確認してテストするよう求めています。最初の5分で5点を見て、チェックリストの合否を埋めてから取り込むと、判断の記録も残ります。
Q. 存在しないパッケージかどうかを確認するには?
A. インストールする前に、pip index versions 名前 または npm view 名前 version で問い合わせます。見つからなければエラーになります。見つかった場合も、公開日・ライセンス・配布元のページを見て、目的のパッケージかどうかを確かめます。
Q. リンターと型チェックの違いは? A. リンターは書き方の決まりや使っていない変数などを見て、型チェックは関数や属性が定義と合っているかを見ます。今回の見本では、無い関数を見つけたのは型チェックだけでした。
Q. AIにレビューさせれば人の確認は省けますか? A. 省けません。GitHub Docs は、Copilot のコードレビューについて、問題をすべて見つけられるとは限らないこと、実際には無い問題を指摘することがあることを説明しています。AIのレビューは観点を増やす手段として使い、取り込む判断は人が行います。
Q. チェックリストの項目が多くて見きれないときは? A. No.1〜6(最初の5分)と No.10(頼んでいない変更)を先に見ます。ここで指摘が出たら、残りを見る前に直すか、AIに直させてやり直すほうが早く済みます。
まとめ
- 動かす前の5分で5点:実在しない関数・パッケージ、秘密情報の直書き、入力の検証、エラー処理、テストの有無。
- パッケージはインストール前に実在を確かめる:
pip index versionsとnpm view。公開日とライセンスもあわせて見る。 - ツールは役割が違う:無い関数は型チェック、トークンはシークレット検出、依存の脆弱性は脆弱性検査、連結はセキュリティ検査。
- 人が読むのは、範囲・仕様・ライセンス:
git diff --statで頼んでいない変更を先に見つける。 - 「通った」ではなく「何件通ったか」:テスト0件は合格にしない。
- チェックリスト15項目の合否を埋めてから取り込む:判断の記録として残せる。
参考・出典
- OWASP「OWASP Top 10:2025」(A03:2025 Software Supply Chain Failures、A05:2025 Injection、A10:2025 Mishandling of Exceptional Conditions)https://top10.owasp.org/2025/ (2026-10-06 閲覧)
- OWASP GenAI Security Project「LLM09:2025 Misinformation」https://genai.owasp.org/llmrisk/llm092025-misinformation/ (2026-10-06 閲覧)
- GitHub Docs「Responsible use of GitHub Copilot code review」https://docs.github.com/en/copilot/responsible-use/code-review (2026-10-06 閲覧)
- GitHub Docs「About push protection」https://docs.github.com/en/code-security/secret-scanning/introduction/about-push-protection (2026-10-06 閲覧)
- pip documentation「pip index」https://pip.pypa.io/en/stable/cli/pip_index/ (2026-10-06 閲覧)
- npm Docs「npm-view」https://docs.npmjs.com/cli/v11/commands/npm-view (2026-10-06 閲覧)
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「AI生成コードの確認チェックリスト|品質とセキュリティ」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。