feat(core): --insecure flag and QWEN_TLS_INSECURE env var (#3535) - #3635
feat(core): --insecure flag and QWEN_TLS_INSECURE env var (#3535)#3635JahanzaibTayyab wants to merge 2 commits into
Conversation
…#3535) Allow skipping TLS certificate verification for outbound HTTPS requests to model APIs and MCP servers. Required for self-signed dev/lab/homelab endpoints because Node's bundled HTTP client (undici, used by fetch) ignores NODE_TLS_REJECT_UNAUTHORIZED by design -- Claude Code works in those setups only because Anthropic's SDK reads it back through a custom agent. Qwen Code does not, so users had no escape hatch. Resolution order (highest to lowest): 1. --insecure CLI flag 2. QWEN_TLS_INSECURE=1|true|yes (case-insensitive) 3. NODE_TLS_REJECT_UNAUTHORIZED=0 (parity with Claude Code / legacy Node http stack -- now also respected here) When set, the resolver passes connect: { rejectUnauthorized: false } to the undici Agent / ProxyAgent used as the dispatcher for the OpenAI, Anthropic, and DashScope SDK clients, and to the global dispatcher that backs MCP / streaming / telemetry traffic. - packages/core/src/utils/runtimeFetchOptions.ts: builder now accepts either a bare proxy-URL string (legacy positional form) or a RuntimeFetchConfig object carrying proxyUrl + insecure. Pre-existing callers continue to work unchanged. - packages/core/src/config/config.ts: new ConfigParameters.insecure field, getInsecure() accessor, and setGlobalDispatcher block updated to apply rejectUnauthorized: false when no proxy is configured. - packages/cli/src/config/config.ts: new --insecure yargs option and resolveInsecureFlag() helper that stitches the three sources together with a clear precedence. - All three SDK provider builders (default OpenAI, DashScope, Anthropic) now thread cliConfig.getInsecure() through the runtime options. - docs/users/support/troubleshooting.md: documents why NODE_TLS_REJECT_UNAUTHORIZED alone fails for fetch-based code paths and which flag/env vars to use instead. Tests - packages/core/src/utils/runtimeFetchOptions.test.ts: 5 new cases pinning the connect option behavior (omitted when unset, present on both Agent and ProxyAgent when insecure=true) and confirming the string and object forms produce identical output. - packages/cli/src/config/config.test.ts: 7 new cases covering the three precedence layers, the negation cases (=0, =1, arbitrary values), and the override interaction. - Existing provider mocks updated to expose getInsecure() so the new call sites resolve. Affected suite: 2,134 core + 439 CLI tests pass; full TypeScript build clean. Prepared with assistance from Claude (Anthropic) under human review.
There was a problem hiding this comment.
Pull request overview
Adds an opt-in mechanism to disable TLS certificate verification for outbound HTTPS traffic (model providers, MCP, telemetry), addressing self-signed / lab endpoints where undici-backed fetch ignores NODE_TLS_REJECT_UNAUTHORIZED.
Changes:
- Introduces
--insecureandQWEN_TLS_INSECURE/NODE_TLS_REJECT_UNAUTHORIZEDresolution in the CLI and threads the resolved value into core config. - Extends
buildRuntimeFetchOptions()to accept{ proxyUrl?, insecure? }(while preserving legacy string proxy argument) and appliesconnect: { rejectUnauthorized: false }to undici dispatchers. - Updates tests/mocks and troubleshooting docs to cover the new behavior.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/core/src/utils/runtimeFetchOptions.ts | Adds RuntimeFetchConfig + insecure TLS wiring into undici Agent/ProxyAgent dispatchers. |
| packages/core/src/utils/runtimeFetchOptions.test.ts | Adds unit tests ensuring connect.rejectUnauthorized=false is applied/omitted correctly and preserves legacy proxy arg behavior. |
| packages/core/src/core/openaiContentGenerator/provider/default.ts | Passes { proxyUrl, insecure } into runtime fetch options for OpenAI-compatible provider. |
| packages/core/src/core/openaiContentGenerator/provider/default.test.ts | Updates provider mock config to include getInsecure(). |
| packages/core/src/core/openaiContentGenerator/provider/dashscope.ts | Threads { proxyUrl, insecure } into DashScope provider runtime fetch options. |
| packages/core/src/core/openaiContentGenerator/provider/dashscope.test.ts | Updates provider mock config to include getInsecure(). |
| packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts | Threads { proxyUrl, insecure } into Anthropic SDK runtime fetch options. |
| packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.test.ts | Updates generator mock config to include getInsecure(). |
| packages/core/src/config/config.ts | Adds insecure param + getter and applies it to the global undici dispatcher (with/without proxy). |
| packages/cli/src/config/config.ts | Adds --insecure flag, env var resolution, and passes resolved value into core Config. |
| packages/cli/src/config/config.test.ts | Adds precedence tests for --insecure, QWEN_TLS_INSECURE, and NODE_TLS_REJECT_UNAUTHORIZED. |
| packages/cli/src/commands/auth/handler.ts | Extends minimal CliArgs literal to include insecure. |
| packages/cli/src/gemini.test.tsx | Updates test CliArgs literal to include insecure. |
| docs/users/support/troubleshooting.md | Documents self-signed endpoint failure mode and the new insecure escape hatches. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…eview) Yargs ``default: false`` collapsed two distinct user intents -- "didn't pass the flag" and "passed --no-insecure" -- into a single boolean ``false`` at parse time, so ``QWEN_TLS_INSECURE=1 --no-insecure`` ended up enabling insecure mode despite the documented "CLI wins" precedence. Drop the default so the parsed value is tri-state (``true | false | undefined``), and treat any explicit value (including ``false``) as the highest-precedence override in ``resolveInsecureFlag``. ``undefined`` continues to fall through to ``QWEN_TLS_INSECURE`` and ``NODE_TLS_REJECT_UNAUTHORIZED`` as before. Two new tests pin the override behavior: - ``QWEN_TLS_INSECURE=1`` + ``--no-insecure`` -> verification on - ``NODE_TLS_REJECT_UNAUTHORIZED=0`` + ``--no-insecure`` -> verification on
| uri: proxyUrl, | ||
| headersTimeout: 0, | ||
| bodyTimeout: 0, | ||
| ...(connect ? { connect } : {}), |
There was a problem hiding this comment.
[Critical] This passes rejectUnauthorized: false under connect, but undici ProxyAgent does not use connect for TLS to the tunneled upstream request. In undici, the target HTTPS TLS options are read from requestTls, so --insecure will still reject self-signed model endpoints whenever --proxy is configured.
| ...(connect ? { connect } : {}), | |
| ...(connect ? { requestTls: connect } : {}), |
— gpt-5.5 via Qwen Code /review
| new ProxyAgent({ | ||
| uri: proxyUrl, | ||
| ...(connect ? { connect } : {}), | ||
| }), |
There was a problem hiding this comment.
[Critical] The global proxy dispatcher has the same issue: ProxyAgent needs upstream TLS options in requestTls, not connect. As written, MCP/streaming/telemetry fetches that rely on the global dispatcher will still fail against self-signed HTTPS targets when a proxy is configured, despite insecure being enabled.
| }), | |
| ...(connect ? { requestTls: connect } : {}), |
— gpt-5.5 via Qwen Code /review
wenshao
left a comment
There was a problem hiding this comment.
No additional inline comments from this review. The previously collected packages/cli/src/utils/modelConfigUtils.ts finding is not present in the current GitHub PR diff, so it was not posted. Existing Qwen Code comments on ProxyAgent TLS options still cover the remaining confirmed issue.
— gpt-5.5 via Qwen Code /review
🔬 Local verification report — PR #3635
|
| scenario | result |
|---|---|
| plain fetch, verification on (control) | FAILS DEPTH_ZERO_SELF_SIGNED_CERT ✅ |
buildRuntimeFetchOptions(insecure:false) |
FAILS ✅ (no accidental bypass) |
| legacy string form (proxy only, no insecure) | FAILS ✅ (back-compat safe) |
buildRuntimeFetchOptions(insecure:true) (OpenAI) |
200 OK ✅ |
Anthropic shape, insecure:true |
200 OK ✅ |
| global dispatcher insecure, plain fetch (MCP/streaming/telemetry path) | 200 OK ✅ |
So connect:{rejectUnauthorized:false} genuinely disables verification when opted in, and verification stays on otherwise — no accidental weakening. The precedence resolver and string/object equivalence are also unit-tested.
3) Unit tests on PR head — ✅
runtimeFetchOptions.test.ts: 9/9 passcli/config.test.ts→Insecure / TLS-skip configuration (#3535): 8/8 pass (all three precedence layers +--no-insecureoverrides + negation cases)eslinton the changed source files: clean
4) ⚠️ Premise check — NODE_TLS_REJECT_UNAUTHORIZED=0 already works today
The PR's motivation is "undici (used by fetch) ignores NODE_TLS_REJECT_UNAUTHORIZED by design … so today a user has no escape hatch" and lists that layer as "Before: silent no-op". In the current runtime this is no longer true:
NODE_TLS_REJECT_UNAUTHORIZED=0 → plain undici fetch → SUCCEEDED (200)
NODE_TLS_REJECT_UNAUTHORIZED=0 → provider Agent (insecure:false, the Agent main builds today) → SUCCEEDED (200)
NODE_TLS_REJECT_UNAUTHORIZED=1 → same paths → FAILED (DEPTH_ZERO_SELF_SIGNED_CERT)
Because the provider Agent does not explicitly set rejectUnauthorized, it inherits Node's global TLS default, which NODE_TLS_REJECT_UNAUTHORIZED controls. So on current main, NODE_TLS_REJECT_UNAUTHORIZED=0 already lets fetch-based provider calls skip verification — the escape hatch the PR says is missing already exists (likely a Node/undici behavior change since April). This makes the PR's NODE_TLS_REJECT_UNAUTHORIZED layer largely redundant. The net-new, still-valuable parts are the explicit, discoverable --insecure flag and QWEN_TLS_INSECURE env var, and making the intent explicit rather than relying on Node's implicit global inheritance.
5) Security considerations (for review)
- Disabling TLS verification exposes traffic to MITM. The PR correctly gates it behind explicit opt-in (flag/env) and keeps verification on by default — verified above. 👍
- All-or-nothing scope. The global-dispatcher mutation makes the setting process-wide: enabling
--insecurefor one self-signed model endpoint also disables verification for every other outbound call (telemetry, all MCP servers, streaming). There is no per-host scoping. Worth calling out in the docs/UX (a one-time warning when insecure mode is active would be prudent).
Recommendation
The feature is implemented soundly and is safe-by-default, but: (a) rebase onto current main (re-applying the provider/config threading; resolve the auth/handler.ts modify/delete), (b) re-validate the premise — NODE_TLS_REJECT_UNAUTHORIZED=0 already works, so the description/behavior-matrix should be updated and the team should decide whether the remaining value (--insecure / QWEN_TLS_INSECURE convenience + explicitness) justifies the surface area, (c) re-run npm run build / typecheck after the rebase (not meaningfully runnable on this stale branch against current deps), and consider a runtime warning given the all-or-nothing scope.
🇨🇳 中文版(点击展开)
🔬 本地验证报告 — PR #3635 feat(core): --insecure 标志与 QWEN_TLS_INSECURE 环境变量
结论:机制本身正确、且默认安全(仅显式开启时才跳过校验),但本 PR 目前无法直接合并,且其立论前提在当前运行时已过时。 合并前需要维护者关注两点:(1) 它与 main 存在冲突,需要 rebase;(2) 在当前 Node/undici 下,NODE_TLS_REJECT_UNAUTHORIZED=0 已经能让 undici fetch 跳过校验,因此“没有逃生通道”的说法不再成立——真正新增的价值是 --insecure 标志和 QWEN_TLS_INSECURE 变量。
验证方式
在 tmux 中运行真实 vitest + 一个真实的自签名 HTTPS 服务器(用 tsx 驱动),worktree 检出在 PR head(b1eb211a)。环境:Node v22.22.2、undici 7.27.2。(由于存在冲突,无法把 PR 合入 main 后验证合并态——见下——所以直接在 PR head 上验证功能。)
1) 合并状态 —— ⚠️ 冲突,需要 rebase
git merge-tree origin/main pr3635-head → 8 个冲突文件,含一个 modify/delete 冲突:
packages/cli/src/commands/auth/handler.ts—— 在main上已被删除,本 PR 又修改了它- 内容冲突:
cli/config.ts、core/config.ts、runtimeFetchOptions.ts(+test)、provider/default.ts、provider/dashscope.ts、anthropicContentGenerator.ts(+test)
该分支约 2 个月前(merge-base a6b0b7e5,4/26),main 已重构了大部分被改文件。没有非平凡的 rebase 无法合并,对 providers/config 的串联需要在当前代码上重新施加。
2) 机制 —— ✅ 正确且安全(真实自签名 HTTPS E2E)
自签名证书 + 真实 https 服务器,经 buildRuntimeFetchOptions 产出的 dispatcher 发起请求:
| 场景 | 结果 |
|---|---|
| 普通 fetch,开启校验(对照) | 失败 DEPTH_ZERO_SELF_SIGNED_CERT ✅ |
buildRuntimeFetchOptions(insecure:false) |
失败 ✅(不会误绕过) |
| 旧版字符串形式(仅 proxy,无 insecure) | 失败 ✅(向后兼容安全) |
buildRuntimeFetchOptions(insecure:true)(OpenAI) |
200 OK ✅ |
Anthropic 形态,insecure:true |
200 OK ✅ |
| 全局 dispatcher insecure,普通 fetch(MCP/streaming/telemetry 路径) | 200 OK ✅ |
即 connect:{rejectUnauthorized:false} 在显式开启时确实跳过校验,否则保持开启——不会意外削弱安全。优先级解析与字符串/对象等价也有单测覆盖。
3) PR head 上的单测 —— ✅
runtimeFetchOptions.test.ts:9/9 通过cli/config.test.ts→Insecure / TLS-skip configuration (#3535):8/8 通过(三层优先级 +--no-insecure覆盖 + 反向用例)- 改动源文件
eslint:干净
4) ⚠️ 前提核查 —— NODE_TLS_REJECT_UNAUTHORIZED=0 现在已经生效
PR 的立论是“undici(fetch 使用)按设计忽略 NODE_TLS_REJECT_UNAUTHORIZED …… 所以用户没有逃生通道”,并把该层标为 “Before: silent no-op”。在当前运行时这已不成立:
NODE_TLS_REJECT_UNAUTHORIZED=0 → 普通 undici fetch → 成功 (200)
NODE_TLS_REJECT_UNAUTHORIZED=0 → provider Agent(insecure:false,即 main 今天构造的 Agent) → 成功 (200)
NODE_TLS_REJECT_UNAUTHORIZED=1 → 同上路径 → 失败 (DEPTH_ZERO_SELF_SIGNED_CERT)
因为 provider 的 Agent 没有显式设置 rejectUnauthorized,它会继承 Node 的全局 TLS 默认值,而该默认值由 NODE_TLS_REJECT_UNAUTHORIZED 控制。因此在当前 main 上,NODE_TLS_REJECT_UNAUTHORIZED=0 已经能让基于 fetch 的 provider 调用跳过校验——PR 所说“缺失”的逃生通道其实已存在(很可能是 4 月以来 Node/undici 行为变化所致)。这使 PR 的 NODE_TLS_REJECT_UNAUTHORIZED 这一层基本变得冗余。真正新增且仍有价值的是显式、可发现的 --insecure 标志与 QWEN_TLS_INSECURE 环境变量,以及让意图显式化(而非依赖 Node 的隐式全局继承)。
5) 安全考量(供评审)
- 关闭 TLS 校验会暴露于中间人攻击。PR 正确地将其限定为显式开启(标志/环境变量),默认仍开启校验——上文已验证。👍
- 全有或全无的范围。 全局 dispatcher 改动让该设置作用于整个进程:为某个自签名模型端点开启
--insecure,也会对所有其他出站请求(telemetry、所有 MCP server、streaming)关闭校验,没有按 host 的细分。建议在文档/UX 里明确提示(开启 insecure 模式时给一次性告警更稳妥)。
建议
功能实现稳健、默认安全,但:(a) rebase 到当前 main(重新施加 provider/config 串联,解决 auth/handler.ts 的 modify/delete),(b) 重新核对前提——NODE_TLS_REJECT_UNAUTHORIZED=0 现已生效,应更新描述/行为矩阵,并由团队决定剩余价值(--insecure/QWEN_TLS_INSECURE 的便利性与显式性)是否值得这部分代码面;(c) rebase 后重跑 npm run build/typecheck(在这个对着当前依赖的陈旧分支上跑没有意义),并考虑鉴于“全有或全无”的范围加一个运行时告警。
Verified locally under tmux on a worktree at the PR head (Node 22.22.2 / undici 7.27.2): merge-conflict detection vs current main, PR unit suites, a real self-signed-HTTPS end-to-end exercising the insecure/secure dispatcher + global dispatcher, and a direct premise check showing NODE_TLS_REJECT_UNAUTHORIZED=0 already disables undici-fetch verification in this runtime. Full build/typecheck deferred to post-rebase.
DragonnZhang
left a comment
There was a problem hiding this comment.
No new blocking issues at this commit. The opt-in design is safe-by-default (TLS verification stays on unless explicitly disabled), the --insecure / QWEN_TLS_INSECURE / NODE_TLS_REJECT_UNAUTHORIZED precedence is correctly implemented and tested, and all three SDK providers plus the global undici dispatcher (MCP / telemetry / streaming) thread the flag consistently. CI is green. The substantive items previously raised — that proxied insecure TLS on undici ProxyAgent needs requestTls rather than connect, and the suggestion to surface a runtime warning given the process-wide scope — already cover the remaining concerns and are not repeated here.
— Qwen Code /review
Generated by Claude Code
| proxyUrlOrConfig?: string | RuntimeFetchConfig, | ||
| ): OpenAIRuntimeFetchOptions | AnthropicRuntimeFetchOptions { | ||
| const runtime = detectRuntime(); | ||
| const { proxyUrl, insecure } = normalizeConfig(proxyUrlOrConfig); |
There was a problem hiding this comment.
[Security / Correctness] insecure is extracted from the config here, but the case 'bun': branch (line 108) never reads it. When running on Bun, --insecure, QWEN_TLS_INSECURE=1, and NODE_TLS_REJECT_UNAUTHORIZED=0 are all silently ignored -- TLS verification stays on with no warning to the user. This defeats the feature's purpose (self-signed dev/lab endpoints) on Bun without any diagnostic.
Suggested fix: either propagate the flag in the Bun branch (e.g. set process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' at startup when insecure is resolved true, since Bun honors that env var), or emit a runtime warning that --insecure has no effect on Bun so the user is not left guessing.
| if (proxyUrl) { | ||
| setGlobalDispatcher(new ProxyAgent(proxyUrl)); | ||
| setGlobalDispatcher( | ||
| new ProxyAgent({ |
There was a problem hiding this comment.
[Correctness] The global ProxyAgent is constructed without headersTimeout: 0 and bodyTimeout: 0, while the per-SDK ProxyAgent instances created in buildFetchOptionsWithDispatcher (in runtimeFetchOptions.ts) explicitly set both to 0. This is inconsistent.
The global dispatcher backs MCP transports, streaming endpoints, and telemetry -- all of which can involve long-lived or idle connections. Undici's default timeouts (300 s for headers, 300 s for body) will apply here, which can silently kill MCP long-polls or streaming reads that exceed the default. Adding headersTimeout: 0, bodyTimeout: 0 to match the per-SDK ProxyAgent configuration would prevent this.
|
@qwen-code /triage |
|
@qwen-code /resolve |
1 similar comment
|
@qwen-code /resolve |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Thanks for the PR, @JahanzaibTayyab!
Template: needs update
- "What this PR does" and "Why it's needed" (prose, not code-level)
- "Reviewer Test Plan" with "How to verify", "Evidence (Before & After)", and "Tested on" (OS table)
- "Risk & Scope" (main risk, what's out of scope, breaking changes)
- Chinese translation in the
<details>block
Could you restructure the body to match the template? The technical content is solid — it just needs to be reorganized into the expected sections so reviewers can find what they need.
Additional context for the rebase (from the prior verification report): this branch is ~2 months old and conflicts with main in 8 files, including a modify/delete on auth/handler.ts. The NODE_TLS_REJECT_UNAUTHORIZED=0 premise has also been partially invalidated — it now works for undici fetch in the current runtime (Node 22.22.2 / undici 7.27.2). The genuinely new value is the explicit --insecure flag and QWEN_TLS_INSECURE env var.
中文说明
感谢 PR,@JahanzaibTayyab!
模板需要更新
- "What this PR does" 和 "Why it's needed"(用散文描述,非代码层面)
- "Reviewer Test Plan" 包括 "How to verify"、"Evidence (Before & After)" 和 "Tested on"(操作系统表格)
- "Risk & Scope"(主要风险、不在范围内的内容、破坏性变更)
<details>块中的中文翻译
请按照模板重新组织正文。技术内容本身很好——只是需要重新组织到预期的章节中,以便审查者找到所需信息。
关于 rebase 的额外信息(来自先前的验证报告):该分支约 2 个月前创建,与 main 在 8 个文件中存在冲突,包括 auth/handler.ts 的 modify/delete 冲突。NODE_TLS_REJECT_UNAUTHORIZED=0 的前提也已部分失效——在当前运行时(Node 22.22.2 / undici 7.27.2)中它已能正常作用于 undici fetch。真正新增的价值是显式的 --insecure 标志和 QWEN_TLS_INSECURE 环境变量。
— Qwen Code · qwen3.7-max
|
@qwen-code /resolve |
1 similar comment
|
@qwen-code /resolve |
|
Qwen Code attempted to resolve merge conflicts but the run did not complete successfully. Check the workflow run for full logs. |
|
Qwen Code attempted to resolve merge conflicts but the run did not complete successfully. Check the workflow run for full logs. |
|
@qwen-code /resolve |
|
@qwen-code /triage |
|
@qwen-code /resolve |
|
Qwen Code attempted to resolve merge conflicts but the run did not complete successfully. Check the workflow run for full logs. |
|
Qwen Code attempted to resolve merge conflicts but the run did not complete successfully. Check the workflow run for full logs. |
|
@qwen-code /resolve |
Gate — PR #3635This PR is fully superseded by PR #5962 (commit
The branch also has 8 conflicting files against current Recommendation: close as superseded. The author's intent was good and the implementation on the stale branch is sound, but the feature has already shipped via a different path. 中文说明门禁 — PR #3635本 PR 已被 PR #5962(commit
分支与当前 建议: 以"已被取代"关闭。作者的意图正确,在过期分支上的实现也合理,但该功能已通过另一条路径上线。 — Qwen Code · qwen3.7-max |
|
Closing as superseded — this feature has already shipped via PR #5962. Thanks for the effort, @JahanzaibTayyab! 🙏 |
|
Qwen Code resolved the merge conflicts, but could not push to Merge Conflict Resolution Summary — PR #3635Branch: ContextPR #3635 added a The PR's unique value-add is the tri-state Conflicted Files (9 total)1.
|
|
Qwen Code did not run conflict resolution for this request. PR #3635 is CLOSED. |
Closes #3535.
What
Allow skipping TLS certificate verification for outbound HTTPS requests to model APIs and MCP servers. Required for self-signed dev / lab / homelab endpoints because Node's bundled HTTP client (
undici, used byfetch) ignoresNODE_TLS_REJECT_UNAUTHORIZEDby design — Claude Code works in those setups only because Anthropic's SDK reads the env var back through a custom agent. Qwen Code does not, so today a user with a self-signed Qwen3.6 server has no escape hatch and just sees:This PR adds three coordinated entry points and threads the resolved value through every place an undici dispatcher is constructed.
How (resolution order, highest to lowest)
--insecureCLI flagQWEN_TLS_INSECURE=1|true|yes(case-insensitive)NODE_TLS_REJECT_UNAUTHORIZED=0— for parity with Claude Code and Node's legacyhttpstack. We respect this even thoughfetchitself doesn't, because users reasonably expect the global Node convention to apply.When set, the resolver passes
connect: { rejectUnauthorized: false }to:Behavior matrix
--insecureQWEN_TLS_INSECURE=1NODE_TLS_REJECT_UNAUTHORIZED=0NODE_TLS_REJECT_UNAUTHORIZED=1--proxy <url>ProxyAgentAreas needing careful review
buildRuntimeFetchOptions. Second arg now accepts either a bare proxy-URL string (legacy) or aRuntimeFetchConfigobject ({ proxyUrl?, insecure? }).normalizeConfig()reduces both to the same internal shape, and a regression test pins the equivalence ('treats a bare proxy-URL string identically to legacy callers'). Open to renaming the option totlsRejectUnauthorized: falseif maintainers prefer matching Node's exact spelling.setGlobalDispatcher(new Agent({ connect: { rejectUnauthorized: false } }))wheninsecureis set without a proxy. This is process-wide, but only triggered by an explicit opt-in flag/env, and the existing proxy path already mutates global state in the same place — I followed that pattern rather than introducing a new injection point.insecure: undefinedin two CliArgs literals.auth/handler.tsandgemini.test.tsxbuild a fully-spreadCliArgsliteral so I addedinsecure: undefinedrather than make the field optional in the interface; matches the surroundingproxy: undefinedstyle.Tests
runtimeFetchOptions.test.ts: 5 new cases pinning theconnectoption behavior (omitted when unset, present on bothAgentandProxyAgentwheninsecure=true, also threaded for Anthropic), plus a string-vs-object equivalence test.cli/config.test.ts: 7 new cases covering the three precedence layers, the negation cases (=0,=1, arbitrary values), and the--insecureoverridesQWEN_TLS_INSECURE=0interaction.default.test.ts,dashscope.test.ts,anthropicContentGenerator.test.ts) updated to exposegetInsecure()so the new call sites resolve.Testing
npm run buildclean (full TypeScript build)docs/users/support/troubleshooting.md)Prepared with assistance from Claude (Anthropic) under human review.