fix(googlechat): harden google auth transport#69812
Conversation
Greptile SummaryThis PR localizes the Confidence Score: 5/5Safe to merge — clean scoped refactoring with no behavioral changes to the shim logic. All remaining findings are P2 or lower. The shim handles missing gaxios gracefully, the concurrent-call guard is correct given JavaScript's single-threaded event loop, and undici is transitively available through the required openclaw peer dependency. No P0/P1 issues found. No files require special attention. Reviews (1): Last reviewed commit: "fix(googlechat): localize google auth ga..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 60c781d141
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3269ccfde5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ab73fb502f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4582811c1e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
032b826 to
6dd5292
Compare
a3c626b to
85d3ba3
Compare
🔒 Aisle Security AnalysisWe found 2 potential security issue(s) in this PR:
1. 🟡 Client TLS certificate/key may be sent to proxy in env-proxy mode (credential leakage)
Description
This can leak mTLS credentials to an unintended proxy:
If an attacker can influence environment proxy settings (common in some deployment setups) or if a proxy is misconfigured, the client certificate/private key intended for the Google endpoint could be presented to that proxy, disclosing credentials and enabling impersonation. Vulnerable code: if (envProxyUrl) {
return {
dispatcherPolicy: {
mode: "env-proxy",
...(hasTlsOptions(tlsOptions) ? { proxyTls: { ...tlsOptions } } : {}),
},
init: nextInit,
};
}RecommendationDo not automatically reuse destination TLS credentials as proxy TLS credentials.
Example safer change: if (envProxyUrl) {
return {
dispatcherPolicy: {
mode: "env-proxy",
// Do not forward destination mTLS credentials to the proxy.
},
init: nextInit,
};
}
// Only apply connect TLS options for direct connections.
if (hasTlsOptions(tlsOptions)) {
return {
dispatcherPolicy: { mode: "direct", connect: { ...tlsOptions } },
init: nextInit,
};
}If proxy mTLS is required, introduce a separate, explicit configuration path (and keep it distinct from destination TLS settings). 2. 🟡 Potential memory exhaustion when reading Google Chat service account credentials file
DescriptionThe
Vulnerable code: const stat = await handle.stat();
if (stat.size > MAX_GOOGLE_CHAT_SERVICE_ACCOUNT_FILE_BYTES) { /* ... */ }
raw = await handle.readFile({ encoding: "utf8" });
if (Buffer.byteLength(raw, "utf8") > MAX_GOOGLE_CHAT_SERVICE_ACCOUNT_FILE_BYTES) { /* ... */ }RecommendationAvoid unbounded buffering when reading a path that may point to special files.
Example (cap read size): import fs from "node:fs";
import { once } from "node:events";
async function readFileCapped(path: string, maxBytes: number): Promise<string> {
const stream = fs.createReadStream(path, { encoding: "utf8" });
let data = "";
let total = 0;
return await new Promise((resolve, reject) => {
stream.on("data", (chunk: string) => {
total += Buffer.byteLength(chunk, "utf8");
if (total > maxBytes) {
stream.destroy(new Error(`File exceeds ${maxBytes} bytes`));
return;
}
data += chunk;
});
stream.on("error", reject);
stream.on("end", () => resolve(data));
});
}
// usage:
const raw = await readFileCapped(resolvedPath, MAX_GOOGLE_CHAT_SERVICE_ACCOUNT_FILE_BYTES);This prevents large/unknown-sized special files from causing OOM before the limit check runs. Analyzed PR: #69812 at commit Last updated on: 2026-04-22T05:42:32Z |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0ebad02e79
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const httpsProxy = | ||
| lowerHttpsProxy !== undefined | ||
| ? lowerHttpsProxy | ||
| : normalizeGoogleAuthProxyEnvValue(process.env.HTTPS_PROXY); |
There was a problem hiding this comment.
Honor gaxios proxy env precedence for Google auth requests
resolveGoogleAuthEnvProxyUrl currently prefers lowercase env vars (https_proxy/http_proxy) whenever they are set, so a stale lowercase value will override HTTPS_PROXY/HTTP_PROXY. This diverges from gaxios’ own precedence (and the previous compat path), which checks uppercase first. In environments that export both forms with different values, Google Chat auth can be routed through the wrong proxy or fail unexpectedly; the helper should match gaxios ordering to avoid this regression.
Useful? React with 👍 / 👎.
* fix(googlechat): localize google auth gaxios compat * fix(googlechat): declare undici for staged runtime deps * fix(googlechat): harden google auth transport * fix(googlechat): narrow credential file reads * fix(googlechat): preserve auth proxy transport * fix(googlechat): allow symlinked auth files * fix(googlechat): atomically load auth files * fix(googlechat): eagerly buffer auth responses * fix(googlechat): cap auth response buffering * fix(googlechat): pin staged auth runtime deps * fix(googlechat): buffer auth responses as array buffers * Update CHANGELOG.md * fix(googlechat): reject unstreamed auth responses * fix(googlechat): use ambient fetch for auth transport * fix(googlechat): keep guarded auth fetch on runtime path * fix(googlechat): align staged zod range * chore(lockfile): sync googlechat zod spec
* fix(googlechat): localize google auth gaxios compat * fix(googlechat): declare undici for staged runtime deps * fix(googlechat): harden google auth transport * fix(googlechat): narrow credential file reads * fix(googlechat): preserve auth proxy transport * fix(googlechat): allow symlinked auth files * fix(googlechat): atomically load auth files * fix(googlechat): eagerly buffer auth responses * fix(googlechat): cap auth response buffering * fix(googlechat): pin staged auth runtime deps * fix(googlechat): buffer auth responses as array buffers * Update CHANGELOG.md * fix(googlechat): reject unstreamed auth responses * fix(googlechat): use ambient fetch for auth transport * fix(googlechat): keep guarded auth fetch on runtime path * fix(googlechat): align staged zod range * chore(lockfile): sync googlechat zod spec
* fix(googlechat): localize google auth gaxios compat * fix(googlechat): declare undici for staged runtime deps * fix(googlechat): harden google auth transport * fix(googlechat): narrow credential file reads * fix(googlechat): preserve auth proxy transport * fix(googlechat): allow symlinked auth files * fix(googlechat): atomically load auth files * fix(googlechat): eagerly buffer auth responses * fix(googlechat): cap auth response buffering * fix(googlechat): pin staged auth runtime deps * fix(googlechat): buffer auth responses as array buffers * Update CHANGELOG.md * fix(googlechat): reject unstreamed auth responses * fix(googlechat): use ambient fetch for auth transport * fix(googlechat): keep guarded auth fetch on runtime path * fix(googlechat): align staged zod range * chore(lockfile): sync googlechat zod spec
* fix(googlechat): localize google auth gaxios compat * fix(googlechat): declare undici for staged runtime deps * fix(googlechat): harden google auth transport * fix(googlechat): narrow credential file reads * fix(googlechat): preserve auth proxy transport * fix(googlechat): allow symlinked auth files * fix(googlechat): atomically load auth files * fix(googlechat): eagerly buffer auth responses * fix(googlechat): cap auth response buffering * fix(googlechat): pin staged auth runtime deps * fix(googlechat): buffer auth responses as array buffers * Update CHANGELOG.md * fix(googlechat): reject unstreamed auth responses * fix(googlechat): use ambient fetch for auth transport * fix(googlechat): keep guarded auth fetch on runtime path * fix(googlechat): align staged zod range * chore(lockfile): sync googlechat zod spec
* fix(googlechat): localize google auth gaxios compat * fix(googlechat): declare undici for staged runtime deps * fix(googlechat): harden google auth transport * fix(googlechat): narrow credential file reads * fix(googlechat): preserve auth proxy transport * fix(googlechat): allow symlinked auth files * fix(googlechat): atomically load auth files * fix(googlechat): eagerly buffer auth responses * fix(googlechat): cap auth response buffering * fix(googlechat): pin staged auth runtime deps * fix(googlechat): buffer auth responses as array buffers * Update CHANGELOG.md * fix(googlechat): reject unstreamed auth responses * fix(googlechat): use ambient fetch for auth transport * fix(googlechat): keep guarded auth fetch on runtime path * fix(googlechat): align staged zod range * chore(lockfile): sync googlechat zod spec
* fix(googlechat): localize google auth gaxios compat * fix(googlechat): declare undici for staged runtime deps * fix(googlechat): harden google auth transport * fix(googlechat): narrow credential file reads * fix(googlechat): preserve auth proxy transport * fix(googlechat): allow symlinked auth files * fix(googlechat): atomically load auth files * fix(googlechat): eagerly buffer auth responses * fix(googlechat): cap auth response buffering * fix(googlechat): pin staged auth runtime deps * fix(googlechat): buffer auth responses as array buffers * Update CHANGELOG.md * fix(googlechat): reject unstreamed auth responses * fix(googlechat): use ambient fetch for auth transport * fix(googlechat): keep guarded auth fetch on runtime path * fix(googlechat): align staged zod range * chore(lockfile): sync googlechat zod spec
* fix(googlechat): localize google auth gaxios compat * fix(googlechat): declare undici for staged runtime deps * fix(googlechat): harden google auth transport * fix(googlechat): narrow credential file reads * fix(googlechat): preserve auth proxy transport * fix(googlechat): allow symlinked auth files * fix(googlechat): atomically load auth files * fix(googlechat): eagerly buffer auth responses * fix(googlechat): cap auth response buffering * fix(googlechat): pin staged auth runtime deps * fix(googlechat): buffer auth responses as array buffers * Update CHANGELOG.md * fix(googlechat): reject unstreamed auth responses * fix(googlechat): use ambient fetch for auth transport * fix(googlechat): keep guarded auth fetch on runtime path * fix(googlechat): align staged zod range * chore(lockfile): sync googlechat zod spec
* fix(googlechat): localize google auth gaxios compat * fix(googlechat): declare undici for staged runtime deps * fix(googlechat): harden google auth transport * fix(googlechat): narrow credential file reads * fix(googlechat): preserve auth proxy transport * fix(googlechat): allow symlinked auth files * fix(googlechat): atomically load auth files * fix(googlechat): eagerly buffer auth responses * fix(googlechat): cap auth response buffering * fix(googlechat): pin staged auth runtime deps * fix(googlechat): buffer auth responses as array buffers * Update CHANGELOG.md * fix(googlechat): reject unstreamed auth responses * fix(googlechat): use ambient fetch for auth transport * fix(googlechat): keep guarded auth fetch on runtime path * fix(googlechat): align staged zod range * chore(lockfile): sync googlechat zod spec
summary
gaxiosfetch compat shim out of the root CLI path and into Google Chat authgaxiosdependency and startup hookwhy
The root package was still carrying a legacy
gaxioscompat path even though the only remaining in-repo caller was Google Chat auth. Keeping that shim and dependency at the root made the install graph noisier than it needed to be and kept startup behavior coupled to a plugin-local concern.This PR localizes that behavior to
extensions/googlechatand keeps the plugin runtime self-contained.impact
gaxiosgloballygoogle-auth-librarygaxiosdirectlyfollow-up
This does not remove the remaining
node-domexceptiondeprecation warning fromnpm install. That warning still comes from the broader dependency chain below and should be handled in a separate PR:@mariozechner/pi-ai -> @google/genai -> google-auth-library -> gaxios -> node-fetch -> fetch-blob -> node-domexceptionI think that belongs in a follow-up PR, not this one.
@mariozechner/pi-aiis used across core/provider runtime paths, so mixing that dependency work into this scoped cleanup would balloon the blast radius.validation
pnpm test extensions/googlechat/src/gaxios-fetch-compat.test.ts extensions/googlechat/src/targets.test.ts src/index.test.ts src/plugins/contracts/package-manifest.contract.test.ts test/scripts/root-dependency-ownership-audit.test.tsattempted full staged
check:changed, but this worktree currently has unrelated missing-workspace-file failures inui/andpackages/plugin-package-contract/paths