codex-plugin-cc,可以在 Claude Code 的工作階段中請 Codex 進行程式碼審查。/code-review,Codex 端則有 /codex:review 與 /codex:adversarial-review,可以改變審查的提問方式。n=2 的小型驗證,不能用來下結論判定模型能力高下。檢出數(2 次中至少 1 次檢出 / 共 15 個):
條件方式檢出數Claude 自由描述有明確觀點的自由描述提示詞14Claude /code-review專用指令12Codex /codex:review專用指令11Codex /codex:adversarial-review專用指令(敵對式審查)6另外,/codex:adversarial-review 不是一般的 bug 全面檢查,而是會深入實作方針、設計判斷、信任邊界的審查,因此單純用檢出數來評價並不容易。
環境:Claude Opus / effort high、Codex gpt-5.5 / effort high。
codex-plugin-cc 是 OpenAI 官方 的外掛,可以把 Codex 接進 Claude Code,讓你不用離開 Claude Code 的工作階段,就能把程式碼交給 Codex 做審查與分析。
核心想法是:讓不同供應商、不同模型來審查,藉此比較不容易受到 sycophancy(俗稱「拍馬屁」)偏誤影響,更接近第三方審查。
這次我就借這個機會,實測一下「Claude 和 Codex 的審查到底有什麼差別」。
在 Claude Code 內依序執行:
/plugin marketplace add openai/codex-plugin-cc
/plugin install codex@openai-codex
/reload-plugins
/codex:setup
/codex:setup 會偵測本機的 Codex CLI,並把驗證與設定(~/.codex/config.toml)綁定起來。它不是另外安裝一個新程式,而是直接呼叫機器上既有的 Codex,使用相同的驗證資訊。
主要指令:
/codex:review一般審查/codex:adversarial-review挑戰實作方針與設計判斷的敵對式審查/codex:status / /codex:result / /codex:cancel背景工作管理/codex:transfer把工作階段交接給 Codex 執行緒驗證方法這次以「URL 縮短服務」為題,刻意埋入 15 種不同的 bug。設計上涵蓋正確性、並行性、安全性、隱私與設計等類別。
// shortener.ts
// URL 縮短服務。POST /shorten 進行縮短,GET /:code 重新導向回原始 URL。
import express from "express";
import { Pool } from "pg";
const app = express();
app.use(express.json());
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const ADMIN_TOKEN = "YOUR_ADMIN_TOKEN"; // 管理 API token(範例)
const ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
const cache = new Map<string, string>();
function encode(id: number): string {
let s = "";
while (id > 0) {
s = ALPHABET[id % ALPHABET.length] + s;
id = id / ALPHABET.length;
}
return s;
}
app.post("/shorten", async (req, res) => {
try {
const { url } = req.body;
console.log(`shorten ip=${req.socket.remoteAddress} url=${url}`);
const row = await pool.query(`SELECT MAX(id) as max FROM links`);
const nextId = Number(row.rows[0].max) + 1;
const code = encode(nextId);
pool.query(
`INSERT INTO links (id, code, url, hits) VALUES (${nextId}, '${code}', '${url}', 0)`
);
cache.set(code, url);
return res.json({ ok: true, code });
} catch (e) {
res.json({ ok: true, code: "xxxxxx" });
}
});
app.get("/:code", async (req, res) => {
const code = req.params.code;
let url = cache.get(code);
if (!url) {
const row = await pool.query(`SELECT url FROM links WHERE code = '${code}'`);
url = row.rows[0].url;
cache.set(code, url);
}
const hits = await pool.query(`SELECT hits FROM links WHERE code = '${code}'`);
pool.query(`UPDATE links SET hits = ${Number(hits.rows[0].hits) + 1} WHERE code = '${code}'`);
return res.redirect(url);
});
app.listen(3000);
埋入的 bug(節錄):
encode 少了 Math.floor、INSERT 少了 await、SELECT MAX(id)+1 編號競爭條件、hits 的 lost update、code 不存在時的 rows[0] 當機、Number 的 2^53 精度問題埋入的 15 個 bug
ID位置內容類別S1encode() id = id / ALPHABET.length 沒有 Math.floor,導致變成非整數。code 會壞掉正確性S2各查詢把 url / code 直接插入模板字串 → SQL Injection安全性S3ADMIN_TOKEN 機密直接寫在原始碼中(而且未使用)安全性S4console.log 印出客戶端 IP + 完整 URL(PII)隱私S5SELECT MAX(id)+1 沒有原子性 → 併發請求時 id/code 重複並行性S6INSERT 少了 await 的 fire-and-forget。沒有順序保證 + 可能出現 unhandled rejection正確性S7cache (Map) 沒有失效機制也沒有大小上限 → 過期資料 + 記憶體無限成長正確性/設計S8hits = read+1 非原子 UPDATE → 併發時 lost update並行性S9catch (e) 吞掉錯誤並回傳 { ok: true },偽裝成功可靠性S10res.redirect(url) 未驗證 URL → Open Redirect / 釣魚安全性S11rows[0] 在 code 不存在時會拋例外。GET 端沒有 try/catch正確性S12採編號/端點的連號 code 可被枚舉,且沒有驗證與 rate limit設計/領域S13整個 handler 沒有分層、也沒有交易邊界設計S14全域 catch-all route、magic number、錯誤格式不一致等小問題輕微S15Number(...max) 使用 JS Number,超過 2^53 會喪失精度(未使用 bigint)正確性### 4 種審查方式
條件指令測量項目A. Claude 自由描述觀點明示提示詞明確指定審查觀點,請求較廣泛的審查B. Claude /code-review``/code-review shortener.tsAnthropic 內建的審查流程C. Codex /codex:review``/codex:reviewCodex 的一般審查D. Codex 敵對式審查/codex:adversarial-review深入實作方針、設計判斷與信任邊界A 的固定提示詞如下:
請從正確性 / 安全性 / 並行性 / 隱私 / 設計 的角度審查 shortener.ts,並以帶有 file:line 的條列式方式提出具體指摘。
因此,A 不是單純的「對 Claude 自由提問」,而是更精確地說:「明確指定審查觀點,請求較廣泛的審查」。
但如後文所述,Codex 端有時會注意到整個工作樹的內容,因此它所看到的範圍,和只針對 shortener.ts 的 Claude 自由描述並不完全相同。這一點是本次驗證的限制之一。
類別埋入ABCD正確性/並行處理76665安全性33331隱私11110設計/領域22000可靠性/其他22210總計1514**12116**### 代表性指摘差異
所有人都抓到的項目
encode 的小數除法 bug,四種條件都正確指出為「id = id / ALPHABET.length 沒有 Math.floor,會因為小數索引而混入 undefined」。SQL Injection、編號競爭條件、await 漏掉也同樣都被抓到。
這一類核心的正確性與並行處理 bug,幾乎沒有明顯差異。
只有 Claude 自由描述抓到的項目
差異出現在設計/領域相關的指摘。
將連號 ID 直接轉成 base62,因此「只要枚舉 code 就能偷看別人的 URL」的枚舉攻擊,以及「路由、DB 存取、編號、快取全部在同一個檔案中緊密耦合,缺乏分層」這個設計指摘,只有 Claude 自由描述有提出。
/code-review、/codex:review、/codex:adversarial-review 都沒有提到這兩點。
在埋入項目之外找到的實際問題
/codex:review 的第 2 次與 /codex:adversarial-review 的兩次,除了 shortener.ts 之外,還指出本機設定(例如 .claude/settings.local.json)的 Read 權限過寬,屬於「信任邊界越界」。
這不在埋入的 15 個 bug 內,但對實際運作來說是相當有意義的發現。
從這次結果可以看出,重點不是單純比較「Claude 和 Codex 哪個模型比較會審查」,而是不同審查方式會影響它們容易抓到的問題。
正確性/並行處理(encode、編號競爭條件、await 遺漏、lost update、null crash)在所有條件下都差不多,至少這次測試中看不出明顯的模型差距。
差異出現在設計/領域,而能抓到這些的是只有 Claude 自由描述。
不過,這與其說是「Claude 模型比較擅長設計」,不如說是明確觀點的自由描述審查 vs 專用指令的範圍限制審查 這種方式差異造成的。理由有三點:
/code-review(B)只有 12 項,並漏掉設計類(S12 可枚舉性 / S13 分層)。這表示即使是同一模型,只要你明確說明要看的觀點,或專用指令的外殼到底限制了什麼,抓到的指摘就會不同。/code-review 和 /codex:review 的檢出集合很接近,兩者都沒有碰設計類。即使模型不同,只要都是「不加額外設定、回傳高信心 bug」的審查指令,行為就很像。/code-review 是把數量壓低,也就是犧牲 recall,所以才漏掉設計類。於是我又跑了 /code-review shortener.ts max,結果仍然是同樣的正確性 bug + 安全性 + cleanup 那條線,S12、S13 還是沒檢出。所以差異的原因,似乎不是單純的數量限制,而是「範圍」本身。/code-review 比較像是偏向正確性 bug、reuse / simplification / efficiency 的 cleanup 型審查,而脅威模型或領域設計本來就不在它的守備範圍內。
max 版本比較像是提高指摘的把握度與驗證深度,而不是單純增加數量。
/codex:adversarial-review 如果只看埋入 bug 的檢出數,確實是最少的。不過它不是一般審查的低配版,而是本來就看不同面向。
實際上,/codex:review 的部分 run 以及敵對式審查,都會進一步指出 shortener.ts 之外的本機設定(例如 .claude/settings.local.json)Read 權限過寬,並把它視為信任邊界問題。
這種指摘不是單純看「這個檔案有幾個 bug」就容易發現的。敵對式審查與其說是擴大 bug recall,不如說更適合用來挑戰實作方針、前提與信任邊界。
.claude 檔案,證明它看到的不只是目標檔案,而是整個工作樹。這與只針對 shortener.ts 的 Claude 自由描述並不完全是同一個前提。從這次結果來看,AI 程式碼審查不只是「選哪個模型」,也要把「用什麼方式提問」分開考慮。
像 /code-review 或 /codex:review 這類原生指令速度快,而且訊號高。用來抓明顯的正確性、並行性、安全性 bug,非常夠力。
放在 PR 前的自我檢查,或實作完成後的門檻檢查,都很好用。
如果你想看的是設計或領域合理性,最好搭配自由描述提示詞,或直接加上人工審查。
原生指令的範圍偏向 bug + cleanup,因此不能完全期待它去回答「這個設計好不好」、「這個領域假設有沒有危險」。
例如可以像這樣把觀點說清楚再請它審查:
請從正確性 / 安全性 / 並行性 / 隱私 / 設計 / 領域前提的角度審查。
不只指出實作 bug,也請包含規格、威脅模型與營運風險。
透過 codex-plugin-cc 把內容交給另一個模型,就能在同一個 Claude Code 工作階段內加入不同供應商的視角。
這不只是「再問一個模型」而已,而是會改變審查前提。特別是像信任邊界、設定檔這種超出目標程式碼本身的風險,反而更容易被看見,這點很有趣。
敵對式審查比較適合拿來挑戰設計判斷與信任邊界,而不是取代一般審查。
它不是在問「這個實作有幾個 bug」,而是在問「這個實作方針本身危不危險」、「攻擊者會看哪裡」、「權限與設定前提是否合理」。
如果問「Claude 和 Codex 哪個審查比較銳利」,其實有點偏離重點。
這次這個小型驗證顯示,左右結果的與其說是模型名稱,不如說是審查方式。當你明確指定觀點並廣泛提問時,比較容易抓到設計與領域層面的指摘;原生審查指令則偏向高信心的 bug 與 cleanup;而敵對式審查則更適合用來檢視信任邊界與前提是否合理。
codex-plugin-cc 的有趣之處,就在於你可以在 Claude Code 裡很方便地試這些不同的審查方式。
如果把工具分工清楚:bug 初檢用原生指令,設計審查用明確觀點的自由描述或人工審查,前提挑戰用敵對式審查,AI 程式碼審查的漏網之魚應該可以減少不少。
原文出處:https://qiita.com/kunitomo926/items/7dfc85770cf5132f3d1c