VYPR
High severity7.3GHSA Advisory· Published May 5, 2026· Updated May 7, 2026

CVE-2026-43531

CVE-2026-43531

Description

OpenClaw before 2026.4.9 contains an environment variable injection vulnerability allowing malicious workspace .env files to set runtime-control variables. Attackers can inject variables affecting update sources, gateway URLs, ClawHub resolution, and browser executable paths to compromise application behavior.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
openclawnpm
< 2026.4.92026.4.9

Affected products

2
  • OpenClaw/OpenclawGHSA2 versions
    < 2026.4.9+ 1 more
    • (no CPE)range: < 2026.4.9
    • cpe:2.3:a:openclaw:openclaw:*:*:*:*:*:node.js:*:*range: <2026.4.9

Patches

1
dbfcef319618

fix(dotenv): block workspace runtime env vars (#62660)

https://github.com/openclaw/openclawAgustin RiveraApr 8, 2026via ghsa
3 files changed · +113 3
  • CHANGELOG.md+1 0 modified
    @@ -18,6 +18,7 @@ Docs: https://docs.openclaw.ai
     - Slack/media: preserve bearer auth across same-origin `files.slack.com` redirects while still stripping it on cross-origin Slack CDN hops, so `url_private_download` image attachments load again. (#62960) Thanks @vincentkoc.
     - Gateway/node exec events: mark remote node `exec.started`, `exec.finished`, and `exec.denied` summaries as untrusted system events and sanitize node-provided command/output/reason text before enqueueing them, so remote node output cannot inject trusted `System:` content into later turns. (#62659) Thanks @eleqtrizit.
     - Agents/timeouts: make the LLM idle timeout inherit `agents.defaults.timeoutSeconds` when configured, disable the unconfigured idle watchdog for cron runs, and point idle-timeout errors at `agents.defaults.llm.idleTimeoutSeconds`. Thanks @drvoss.
    +- Security/dotenv: expand workspace `.env` filtering to block runtime-control variables like gateway routing, ClawHub endpoints/tokens, browser executable overrides, and skip/disable control families, so untrusted repositories cannot steer OpenClaw runtime behavior through repo-local dotenv files. (#62660) Thanks @eleqtrizit.
     - Agents/failover: classify Z.ai vendor code `1311` as billing and `1113` as auth, including long wrapped `1311` payloads, so these errors stop falling through to generic failover handling. (#49552) Thanks @1bcMax.
     - QQBot/media-tags: support HTML entity-encoded angle brackets (`&lt;`/`&gt;`) in media-tag regexes so entity-escaped `<qqimg>` tags from upstream are correctly parsed and normalized. (#60493) Thanks @ylc0919.
     - npm packaging: mirror bundled Slack, Telegram, Discord, and Feishu channel runtime deps at the root and harden published-install verification so fresh installs fail fast on manifest drift instead of missing-module crashes. (#63065) Thanks @scoootscooob.
    
  • src/infra/dotenv.test.ts+77 0 modified
    @@ -613,3 +613,80 @@ describe("loadCliDotEnv", () => {
         });
       });
     });
    +
    +describe("workspace .env blocklist completeness", () => {
    +  it("blocks runtime-control variables from workspace .env", async () => {
    +    await withIsolatedEnvAndCwd(async () => {
    +      await withDotEnvFixture(async ({ cwdDir }) => {
    +        const runtimeControlKeys = [
    +          "OPENCLAW_UPDATE_PACKAGE_SPEC",
    +          "OPENCLAW_GATEWAY_PORT",
    +          "OPENCLAW_GATEWAY_URL",
    +          "OPENCLAW_CLAWHUB_URL",
    +          "CLAWHUB_URL",
    +          "OPENCLAW_CLAWHUB_TOKEN",
    +          "CLAWHUB_TOKEN",
    +          "CLAWHUB_AUTH_TOKEN",
    +          "CLAWHUB_CONFIG_PATH",
    +          "OPENCLAW_DISABLE_BUNDLED_PLUGINS",
    +          "OPENCLAW_ALLOW_INSECURE_PRIVATE_WS",
    +          "OPENCLAW_BROWSER_EXECUTABLE_PATH",
    +          "BROWSER_EXECUTABLE_PATH",
    +          "PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH",
    +          "OPENCLAW_SKIP_CHANNELS",
    +          "OPENCLAW_SKIP_PROVIDERS",
    +          "OPENCLAW_SKIP_CRON",
    +          "OPENCLAW_RAW_STREAM",
    +          "OPENCLAW_RAW_STREAM_PATH",
    +          "OPENCLAW_CACHE_TRACE",
    +          "OPENCLAW_CACHE_TRACE_FILE",
    +          "OPENCLAW_CACHE_TRACE_MESSAGES",
    +          "OPENCLAW_CACHE_TRACE_PROMPT",
    +          "OPENCLAW_CACHE_TRACE_SYSTEM",
    +          "OPENCLAW_SHOW_SECRETS",
    +          "OPENCLAW_PLUGIN_CATALOG_PATHS",
    +          "OPENCLAW_MPM_CATALOG_PATHS",
    +          "OPENCLAW_NODE_EXEC_HOST",
    +          "OPENCLAW_NODE_EXEC_FALLBACK",
    +          "OPENCLAW_ALLOW_PROJECT_LOCAL_BIN",
    +        ];
    +
    +        await writeEnvFile(
    +          path.join(cwdDir, ".env"),
    +          `${runtimeControlKeys.map((key) => `${key}=INJECTED_${key}`).join("\n")}\n`,
    +        );
    +
    +        for (const key of runtimeControlKeys) {
    +          delete process.env[key];
    +        }
    +
    +        loadWorkspaceDotEnvFile(path.join(cwdDir, ".env"), { quiet: true });
    +
    +        for (const key of runtimeControlKeys) {
    +          expect(process.env[key], `${key} should be blocked by workspace .env`).toBeUndefined();
    +        }
    +      });
    +    });
    +  });
    +
    +  it("still allows user-defined non-control vars through workspace .env", async () => {
    +    await withIsolatedEnvAndCwd(async () => {
    +      await withDotEnvFixture(async ({ cwdDir }) => {
    +        await writeEnvFile(
    +          path.join(cwdDir, ".env"),
    +          "MY_APP_KEY=user-value\nGITHUB_TOKEN=ghp_test123\nDATABASE_URL_CUSTOM=pg://localhost\n",
    +        );
    +
    +        delete process.env.MY_APP_KEY;
    +        delete process.env.GITHUB_TOKEN;
    +        delete process.env.DATABASE_URL_CUSTOM;
    +
    +        loadWorkspaceDotEnvFile(path.join(cwdDir, ".env"), { quiet: true });
    +
    +        expect(process.env.MY_APP_KEY).toBe("user-value");
    +        expect(process.env.GITHUB_TOKEN).toBe("ghp_test123");
    +        expect(process.env.DATABASE_URL_CUSTOM).toBe("pg://localhost");
    +      });
    +    });
    +  });
    +});
    
  • src/infra/dotenv.ts+35 3 modified
    @@ -14,37 +14,69 @@ const BLOCKED_WORKSPACE_DOTENV_KEYS = new Set([
       "ALL_PROXY",
       "ANTHROPIC_API_KEY",
       "ANTHROPIC_OAUTH_TOKEN",
    +  "BROWSER_EXECUTABLE_PATH",
    +  "CLAWHUB_AUTH_TOKEN",
    +  "CLAWHUB_CONFIG_PATH",
    +  "CLAWHUB_TOKEN",
    +  "CLAWHUB_URL",
       "HTTP_PROXY",
       "HTTPS_PROXY",
       "NODE_TLS_REJECT_UNAUTHORIZED",
       "NO_PROXY",
    +  "OPENAI_API_KEY",
    +  "OPENAI_API_KEYS",
       "OPENCLAW_AGENT_DIR",
    +  "OPENCLAW_ALLOW_INSECURE_PRIVATE_WS",
    +  "OPENCLAW_ALLOW_PROJECT_LOCAL_BIN",
    +  "OPENCLAW_BROWSER_EXECUTABLE_PATH",
       "OPENCLAW_BUNDLED_HOOKS_DIR",
       "OPENCLAW_BUNDLED_PLUGINS_DIR",
       "OPENCLAW_BUNDLED_SKILLS_DIR",
    +  "OPENCLAW_CACHE_TRACE",
    +  "OPENCLAW_CACHE_TRACE_FILE",
    +  "OPENCLAW_CACHE_TRACE_MESSAGES",
    +  "OPENCLAW_CACHE_TRACE_PROMPT",
    +  "OPENCLAW_CACHE_TRACE_SYSTEM",
       "OPENCLAW_CONFIG_PATH",
       "OPENCLAW_GATEWAY_PASSWORD",
    +  "OPENCLAW_GATEWAY_PORT",
       "OPENCLAW_GATEWAY_SECRET",
       "OPENCLAW_GATEWAY_TOKEN",
    +  "OPENCLAW_GATEWAY_URL",
       "OPENCLAW_HOME",
       "OPENCLAW_LIVE_ANTHROPIC_KEY",
       "OPENCLAW_LIVE_ANTHROPIC_KEYS",
       "OPENCLAW_LIVE_GEMINI_KEY",
       "OPENCLAW_LIVE_OPENAI_KEY",
    +  "OPENCLAW_MPM_CATALOG_PATHS",
    +  "OPENCLAW_NODE_EXEC_FALLBACK",
    +  "OPENCLAW_NODE_EXEC_HOST",
       "OPENCLAW_OAUTH_DIR",
       "OPENCLAW_PINNED_PYTHON",
       "OPENCLAW_PINNED_WRITE_PYTHON",
    +  "OPENCLAW_PLUGIN_CATALOG_PATHS",
       "OPENCLAW_PROFILE",
    +  "OPENCLAW_RAW_STREAM",
    +  "OPENCLAW_RAW_STREAM_PATH",
    +  "OPENCLAW_SHOW_SECRETS",
       "OPENCLAW_STATE_DIR",
       "OPENCLAW_TEST_TAILSCALE_BINARY",
    -  "OPENAI_API_KEY",
    -  "OPENAI_API_KEYS",
       "PI_CODING_AGENT_DIR",
    +  "PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH",
       "UV_PYTHON",
     ]);
     
    +// Block endpoint redirection for any service without overfitting per-provider names.
     const BLOCKED_WORKSPACE_DOTENV_SUFFIXES = ["_BASE_URL"];
    -const BLOCKED_WORKSPACE_DOTENV_PREFIXES = ["ANTHROPIC_API_KEY_", "OPENAI_API_KEY_"];
    +const BLOCKED_WORKSPACE_DOTENV_PREFIXES = [
    +  "ANTHROPIC_API_KEY_",
    +  "CLAWHUB_",
    +  "OPENAI_API_KEY_",
    +  "OPENCLAW_CLAWHUB_",
    +  "OPENCLAW_DISABLE_",
    +  "OPENCLAW_SKIP_",
    +  "OPENCLAW_UPDATE_",
    +];
     
     function shouldBlockWorkspaceRuntimeDotEnvKey(key: string): boolean {
       return isDangerousHostEnvVarName(key) || isDangerousHostEnvOverrideVarName(key);
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.