fix(TLS 驗證): 套用全域憑證忽略設定

This commit is contained in:
2026-06-26 09:20:57 +00:00
parent 4431f2fec5
commit bc0df06445
5 changed files with 21 additions and 10 deletions
+8 -4
View File
@@ -1,5 +1,7 @@
import https from 'https'; import https from 'https';
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
export const GITEA_TOKEN = process.env.GITEA_TOKEN || ''; export const GITEA_TOKEN = process.env.GITEA_TOKEN || '';
export const GITEA_COMMENT_TOKEN = process.env.GITEA_COMMENT_TOKEN || ''; export const GITEA_COMMENT_TOKEN = process.env.GITEA_COMMENT_TOKEN || '';
export const GITEA_SERVER_URL = process.env.GITEA_SERVER_URL || 'https://gitea.com'; 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 * 建立一個停用 TLS 憑證驗證(`rejectUnauthorized: false`)的 HTTPS Agent
* 供連接使用自簽或無效憑證的 OpenCode 服務時使用。 * 供連接使用自簽或無效憑證的內部服務時使用。
* *
* @remarks 首次呼叫時建立,之後快取為模組層級單例(singleton)重複使用, * @remarks 首次呼叫時建立,之後快取為模組層級單例(singleton)重複使用,
* 避免每次都新建 Agent 與連線池、浪費 TCP 三次握手。 * 避免每次都新建 Agent 與連線池、浪費 TCP 三次握手。
* 停用憑證驗證有中間人攻擊風險,僅限受信任的內部環境使用。 * 停用憑證驗證有中間人攻擊風險,僅限受信任的內部環境使用。
* @returns {import('https').Agent} 已關閉憑證驗證的 HTTPS Agent 單例。 * @returns {import('https').Agent} 已關閉憑證驗證的 HTTPS Agent 單例。
*/ */
let _openCodeHttpsAgent = null; let _insecureHttpsAgent = null;
export function getOpenCodeHttpsAgent() { export function getInsecureHttpsAgent() {
return (_openCodeHttpsAgent ??= new https.Agent({ rejectUnauthorized: false })); return (_insecureHttpsAgent ??= new https.Agent({ rejectUnauthorized: false }));
} }
export const getOpenCodeHttpsAgent = getInsecureHttpsAgent;
/** /**
* 依環境變數解析並回傳 LLM 提供者設定。 * 依環境變數解析並回傳 LLM 提供者設定。
* *
+7 -1
View File
@@ -61,7 +61,13 @@ function makeRunner(spawn) {
function withAskpass(workspace, fn, token = GITEA_TOKEN) { function withAskpass(workspace, fn, token = GITEA_TOKEN) {
const askpassScript = path.join(workspace, '.git-askpass.sh'); const askpassScript = path.join(workspace, '.git-askpass.sh');
fs.writeFileSync(askpassScript, '#!/bin/sh\necho "$GIT_TOKEN"\n', { mode: 0o700 }); 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',
GIT_USERNAME: 'x-token',
GIT_TOKEN: token,
};
const cleanup = () => { try { fs.unlinkSync(askpassScript); } catch {} }; const cleanup = () => { try { fs.unlinkSync(askpassScript); } catch {} };
let result; let result;
try { try {
+2 -3
View File
@@ -1,9 +1,8 @@
import axios from 'axios'; 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, getInsecureHttpsAgent } from './config.js';
import { GITEA_TOKEN, GITEA_COMMENT_TOKEN, GITEA_SERVER_URL, GITEA_REPOSITORY, PR_NUMBER, PR_HEAD_SHA, PR_HEAD_BRANCH } from './config.js';
import { line, warn } from './log.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 API 所需的 HTTP headers(含 Gitea token 授權與 JSON content-type)。
* 授權格式為 Gitea 專用的 `token <token>`,並非 OAuth Bearer。 * 授權格式為 Gitea 專用的 `token <token>`,並非 OAuth Bearer。
+2 -2
View File
@@ -1,18 +1,18 @@
import axios from 'axios'; import axios from 'axios';
import https from 'https';
import { import {
GITEA_TOKEN, GITEA_TOKEN,
GITEA_COMMENT_TOKEN, GITEA_COMMENT_TOKEN,
GITEA_SERVER_URL, GITEA_SERVER_URL,
GITEA_REPOSITORY, GITEA_REPOSITORY,
PR_NUMBER, PR_NUMBER,
getInsecureHttpsAgent,
getOpenCodeHttpsAgent, getOpenCodeHttpsAgent,
getLLMConfig, getLLMConfig,
} from './config.js'; } from './config.js';
import { verifyRemoteAccess } from './git.js'; import { verifyRemoteAccess } from './git.js';
import { step, line, ok, error, result } from './log.js'; import { step, line, ok, error, result } from './log.js';
const httpsAgent = new https.Agent({ rejectUnauthorized: false }); const httpsAgent = getInsecureHttpsAgent();
/** /**
* 組出 Gitea REST API v1 的完整網址。 * 組出 Gitea REST API v1 的完整網址。
* *
+2
View File
@@ -1,4 +1,5 @@
import axios from 'axios'; import axios from 'axios';
import { getInsecureHttpsAgent } from './config.js';
import { warn } from './log.js'; import { warn } from './log.js';
/** 本次執行的 token 累計(跨所有 LLM 呼叫)。 */ /** 本次執行的 token 累計(跨所有 LLM 呼叫)。 */
@@ -176,6 +177,7 @@ async function fetchOpenRouterQuota({ apiKey, baseURL }, get) {
const resp = await get(`${stripSlash(baseURL)}/auth/key`, { const resp = await get(`${stripSlash(baseURL)}/auth/key`, {
headers: { Authorization: `Bearer ${apiKey}` }, headers: { Authorization: `Bearer ${apiKey}` },
timeout: 30000, timeout: 30000,
httpsAgent: getInsecureHttpsAgent(),
}); });
const d = resp.data?.data || {}; const d = resp.data?.data || {};
const used = num(d.usage); const used = num(d.usage);