改用 AI 助理 CLI 並強化 AI Code Review 執行流程 #13
+8
-4
@@ -1,5 +1,7 @@
|
||||
import https from 'https';
|
||||
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
||||
|
||||
|
|
||||
export const GITEA_TOKEN = process.env.GITEA_TOKEN || '';
|
||||
export const GITEA_COMMENT_TOKEN = process.env.GITEA_COMMENT_TOKEN || '';
|
||||
export const GITEA_SERVER_URL = process.env.GITEA_SERVER_URL || 'https://gitea.com';
|
||||
@@ -14,18 +16,20 @@ export const EXCLUSIONS_PATH = '.gitea/ai-review/exclusions.json';
|
||||
|
||||
/**
|
||||
* 建立一個停用 TLS 憑證驗證(`rejectUnauthorized: false`)的 HTTPS Agent,
|
||||
* 供連接使用自簽或無效憑證的 OpenCode 服務時使用。
|
||||
* 供連接使用自簽或無效憑證的內部服務時使用。
|
||||
*
|
||||
* @remarks 首次呼叫時建立,之後快取為模組層級單例(singleton)重複使用,
|
||||
* 避免每次都新建 Agent 與連線池、浪費 TCP 三次握手。
|
||||
* 停用憑證驗證有中間人攻擊風險,僅限受信任的內部環境使用。
|
||||
* @returns {import('https').Agent} 已關閉憑證驗證的 HTTPS Agent 單例。
|
||||
*/
|
||||
|
admin
commented
嚴重等級:🟡 警告 **嚴重等級**:🟡 警告
**審查員**:Bard
**問題**:`getInsecureHttpsAgent` 與 `getOpenCodeHttpsAgent` 同時存在,卻指向同一個物件來源,等於替同一段旋律寫了兩個名字,容易讓後續維護者搞不清楚哪個才是正規稱呼。
**建議**:保留一個主名稱即可;如果一定要兼容舊名稱,請加上明確的遷移註解,說明哪個是新名字、哪個只是過渡別名。
|
||||
let _openCodeHttpsAgent = null;
|
||||
export function getOpenCodeHttpsAgent() {
|
||||
return (_openCodeHttpsAgent ??= new https.Agent({ rejectUnauthorized: false }));
|
||||
let _insecureHttpsAgent = null;
|
||||
export function getInsecureHttpsAgent() {
|
||||
return (_insecureHttpsAgent ??= new https.Agent({ rejectUnauthorized: false }));
|
||||
}
|
||||
|
||||
export const getOpenCodeHttpsAgent = getInsecureHttpsAgent;
|
||||
|
||||
/**
|
||||
* 依環境變數解析並回傳 LLM 提供者設定。
|
||||
*
|
||||
|
||||
+7
-1
@@ -61,7 +61,13 @@ function makeRunner(spawn) {
|
||||
function withAskpass(workspace, fn, token = GITEA_TOKEN) {
|
||||
const askpassScript = path.join(workspace, '.git-askpass.sh');
|
||||
fs.writeFileSync(askpassScript, '#!/bin/sh\necho "$GIT_TOKEN"\n', { mode: 0o700 });
|
||||
const credEnv = { ...process.env, GIT_ASKPASS: askpassScript, GIT_USERNAME: 'x-token', GIT_TOKEN: token };
|
||||
const credEnv = {
|
||||
...process.env,
|
||||
GIT_ASKPASS: askpassScript,
|
||||
GIT_SSL_NO_VERIFY: 'true',
|
||||
|
admin
commented
嚴重等級:🟡 警告 **嚴重等級**:🟡 警告
**審查員**:Assassin
**問題**:這裡對所有 git 網路操作強制關閉 SSL 驗證。攻擊者若能攔截遠端回應,就能偽造 `ls-remote`、污染抓到的內容,甚至在有認證的情況下竊取 GITEA_TOKEN,讓後續審查建立在被污染的資料上。
**建議**:移除 `GIT_SSL_NO_VERIFY=true`。若是內部憑證問題,改用正確的 CA bundle 或指定受信任憑證檔,不要整體關閉 git 的憑證驗證。
|
||||
GIT_USERNAME: 'x-token',
|
||||
GIT_TOKEN: token,
|
||||
};
|
||||
const cleanup = () => { try { fs.unlinkSync(askpassScript); } catch {} };
|
||||
let result;
|
||||
try {
|
||||
|
||||
+2
-3
@@ -1,9 +1,8 @@
|
||||
import axios from 'axios';
|
||||
import https from 'https';
|
||||
import { GITEA_TOKEN, GITEA_COMMENT_TOKEN, GITEA_SERVER_URL, GITEA_REPOSITORY, PR_NUMBER, PR_HEAD_SHA, PR_HEAD_BRANCH } from './config.js';
|
||||
import { GITEA_TOKEN, GITEA_COMMENT_TOKEN, GITEA_SERVER_URL, GITEA_REPOSITORY, PR_NUMBER, PR_HEAD_SHA, PR_HEAD_BRANCH, getInsecureHttpsAgent } from './config.js';
|
||||
import { line, warn } from './log.js';
|
||||
|
||||
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
||||
const httpsAgent = getInsecureHttpsAgent();
|
||||
/**
|
||||
* 產生呼叫 Gitea API 所需的 HTTP headers(含 Gitea token 授權與 JSON content-type)。
|
||||
* 授權格式為 Gitea 專用的 `token <token>`,並非 OAuth Bearer。
|
||||
|
||||
+2
-2
@@ -1,18 +1,18 @@
|
||||
import axios from 'axios';
|
||||
import https from 'https';
|
||||
import {
|
||||
GITEA_TOKEN,
|
||||
GITEA_COMMENT_TOKEN,
|
||||
GITEA_SERVER_URL,
|
||||
GITEA_REPOSITORY,
|
||||
PR_NUMBER,
|
||||
getInsecureHttpsAgent,
|
||||
getOpenCodeHttpsAgent,
|
||||
getLLMConfig,
|
||||
} from './config.js';
|
||||
import { verifyRemoteAccess } from './git.js';
|
||||
import { step, line, ok, error, result } from './log.js';
|
||||
|
||||
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
||||
const httpsAgent = getInsecureHttpsAgent();
|
||||
/**
|
||||
* 組出 Gitea REST API v1 的完整網址。
|
||||
*
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import axios from 'axios';
|
||||
import { getInsecureHttpsAgent } from './config.js';
|
||||
import { warn } from './log.js';
|
||||
|
||||
/** 本次執行的 token 累計(跨所有 LLM 呼叫)。 */
|
||||
@@ -176,6 +177,7 @@ async function fetchOpenRouterQuota({ apiKey, baseURL }, get) {
|
||||
const resp = await get(`${stripSlash(baseURL)}/auth/key`, {
|
||||
headers: { Authorization: `Bearer ${apiKey}` },
|
||||
timeout: 30000,
|
||||
httpsAgent: getInsecureHttpsAgent(),
|
||||
|
admin
commented
嚴重等級:🟡 警告 **嚴重等級**:🟡 警告
**審查員**:Assassin
**問題**:這裡對 OpenRouter 額度查詢也明確套用不驗證憑證的 agent。攻擊者只要攔截這條 HTTPS 請求,就能讀到 `Authorization: Bearer` 的 API key,還能回傳假 quota 資料誤導流程判斷。
**建議**:改回預設的 HTTPS 憑證驗證。若必須支援自簽憑證,僅對特定內部主機單獨配置受信任 CA,且不要對外部 API 一律關閉驗證。
|
||||
});
|
||||
const d = resp.data?.data || {};
|
||||
const used = num(d.usage);
|
||||
|
||||
Reference in New Issue
Block a user
嚴重等級:🟡 警告
審查員:Bard
問題:
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'放在模組載入時就直接生效,這種全域副作用太早出聲,會讓讀者在還沒看到任何呼叫前,就先被迫接受一個隱晦的環境改寫。建議:把這種全域設定移到明確的啟動流程或初始化函式中,至少搭配更醒目的註解,讓副作用出現的位置和目的都更清楚。