mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:40:44 +00:00
fix(dotenv): block Windows shell trust-root vars from workspace .env [AI-assisted] (#74460)
* fix: address issue * fix: address PR review feedback * changelog: PR #74460 --------- Co-authored-by: Devin Robison <drobison@nvidia.com>
This commit is contained in:
@@ -163,6 +163,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Agents/failover: carry `sessionId`, `lane`, `provider`, `model`, and `profileId` attribution through `FailoverError` and `describeFailoverError`/`coerceToFailoverError` so structured error logs (e.g. `gateway.err.log` ingestion) can attribute exhausted-fallback wrapper errors to the originating session and last-attempted provider instead of dropping the metadata after the per-profile errors. Fixes #42713. (#73506) Thanks @wenxu007.
|
||||
- Context Engine: treat assembled prompt as the default authority for preemptive overflow prechecks so engines that return a windowed, self-contained context no longer trigger false hard-fail compactions on huge raw history. Engines whose assembled view can hide overflow risk can opt back into the legacy behavior with `AssembleResult.promptAuthority: "preassembly_may_overflow"`. (#74255) Thanks @100yenadmin.
|
||||
- Mattermost: refresh current native slash command registrations before accepting callbacks so stale tokens from deleted or regenerated commands stop being accepted without a gateway restart while failed validations stay briefly cached and lookup starts are rate-limited per command, gate each callback against the resolved command's own startup token so a token leaked for one slash command cannot poison another command's failure cache, redact slash validation lookup errors, and add a body read timeout to the multi-account routing path so slow callback senders cannot tie up the dispatcher. Thanks @feynman-hou and @eleqtrizit.
|
||||
- Security/dotenv: block `COMSPEC` in workspace `.env` so a malicious repo cannot redirect Windows `cmd.exe` resolution, and lock in case-insensitive workspace-`.env` regression coverage for the full Windows shell trust-root family (`COMSPEC`, `PROGRAMFILES`, `PROGRAMW6432`, `SYSTEMROOT`, `WINDIR`). (#74460) Thanks @mmaps.
|
||||
|
||||
## 2026.4.29
|
||||
|
||||
|
||||
@@ -41,6 +41,19 @@ const BUNDLED_TRUST_ROOT_ENV_KEYS = BUNDLED_TRUST_ROOT_ENV_LINES.map(
|
||||
(line) => line.split("=")[0] ?? "",
|
||||
);
|
||||
|
||||
const WINDOWS_SHELL_TRUST_ROOT_ENV_KEYS = [
|
||||
"ComSpec",
|
||||
"COMSPEC",
|
||||
"ProgramFiles",
|
||||
"PROGRAMFILES",
|
||||
"ProgramW6432",
|
||||
"PROGRAMW6432",
|
||||
"SystemRoot",
|
||||
"SYSTEMROOT",
|
||||
"windir",
|
||||
"WINDIR",
|
||||
] as const;
|
||||
|
||||
async function writeEnvFile(filePath: string, contents: string) {
|
||||
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
||||
await fs.writeFile(filePath, contents, "utf8");
|
||||
@@ -305,6 +318,34 @@ describe("loadDotEnv", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("blocks Windows shell trust-root vars from workspace .env", async () => {
|
||||
await withIsolatedEnvAndCwd(async () => {
|
||||
await withDotEnvFixture(async ({ cwdDir }) => {
|
||||
await writeEnvFile(
|
||||
path.join(cwdDir, ".env"),
|
||||
[
|
||||
"ComSpec=.\\evil-comspec",
|
||||
"COMSPEC=.\\evil-comspec-upper",
|
||||
"ProgramFiles=.\\evil-pfiles",
|
||||
"PROGRAMFILES=.\\evil-pfiles-upper",
|
||||
"ProgramW6432=.\\evil-pw6432",
|
||||
"PROGRAMW6432=.\\evil-pw6432-upper",
|
||||
"SystemRoot=.\\fake-root",
|
||||
"SYSTEMROOT=.\\fake-root-upper",
|
||||
"windir=.\\fake-windir",
|
||||
"WINDIR=.\\fake-windir-upper",
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
clearEnv(WINDOWS_SHELL_TRUST_ROOT_ENV_KEYS);
|
||||
|
||||
loadWorkspaceDotEnvFile(path.join(cwdDir, ".env"), { quiet: true });
|
||||
|
||||
expectEnvUndefined(WINDOWS_SHELL_TRUST_ROOT_ENV_KEYS);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("blocks path-override vars (OPENCLAW_AGENT_DIR, OPENCLAW_BUNDLED_PLUGINS_DIR, PI_CODING_AGENT_DIR, OPENCLAW_OAUTH_DIR) from workspace .env", async () => {
|
||||
await withIsolatedEnvAndCwd(async () => {
|
||||
await withDotEnvFixture(async ({ base, cwdDir }) => {
|
||||
|
||||
@@ -23,6 +23,7 @@ const BLOCKED_WORKSPACE_DOTENV_KEYS = new Set([
|
||||
"CLAWHUB_TOKEN",
|
||||
"CLAWHUB_URL",
|
||||
"CLOUDSDK_PYTHON",
|
||||
"COMSPEC",
|
||||
"HTTP_PROXY",
|
||||
"HTTPS_PROXY",
|
||||
"HOMEBREW_BREW_FILE",
|
||||
|
||||
Reference in New Issue
Block a user