Skip to content

fix(a2a-server): enforce workspace trust and task isolation to prevent RCE#28470

Open
luisfelipe-alt wants to merge 2 commits into
google-gemini:mainfrom
luisfelipe-alt:bugfix/WT-engineer_519269096_cleanfix
Open

fix(a2a-server): enforce workspace trust and task isolation to prevent RCE#28470
luisfelipe-alt wants to merge 2 commits into
google-gemini:mainfrom
luisfelipe-alt:bugfix/WT-engineer_519269096_cleanfix

Conversation

@luisfelipe-alt

Copy link
Copy Markdown
Contributor

Summary

This PR resolves a critical security vulnerability in the a2a-server backend that allowed for zero-click Remote Code Execution (RCE) and environment poisoning in untrusted workspaces.

By refactoring the startup sequence, environment loading mechanism, and introducing robust task-level environment and process isolation in a2a-server using AsyncLocalStorage and a Proxy on process.env, we ensure that
workspace-level environment files (.env and .gemini/.env) are completely ignored unless the workspace is explicitly trusted by the user. This aligns the a2a-server backend's security model with the existing secure implementation
in the CLI frontend.

Details

  1. Startup Sequence Refactoring:
    • Deferred the call to loadEnvironment() in
      packages/a2a-server/src/http/app.ts (createApp) and
      packages/a2a-server/src/agent/executor.ts (getConfig) until after
      workspace trust is evaluated (checkPathTrust / setIsTrusted).
    • This prevents an attacker from placing GEMINI_CLI_TRUST_WORKSPACE=true
      inside a malicious .gemini/.env file to self-validate their own
      untrusted workspace before trust is checked.
  2. Secure Environment Loading:
    • Updated loadEnvironment(isTrusted) in
      packages/a2a-server/src/config/config.ts to accept the trust state.
    • If isTrusted is false, workspace-level environment files (both .env
      and .gemini/.env) are completely ignored. Instead, the loader only loads
      environment variables from the user's trusted home directory (e.g.,
      ~/.gemini/.env or ~/.env). This is a safer and more secure approach
      that completely isolates untrusted workspaces from environment loading.
  3. Task-Isolated Environment and Directory Sandboxing:
    • Implemented robust task-level environment isolation using AsyncLocalStorage
      (envStorage) and a Proxy on process.env to intercept reads, writes,
      deletions, and key enumerations, isolating environment variables per task
      and preventing cross-task credential leakages.
    • Monkey-patched process.cwd and process.chdir using AsyncLocalStorage
      to simulate workspace isolation in a concurrent server.
  4. Symbol Delegation in envProxy:
    • Delegated non-string properties (such as Symbols like Symbol.toStringTag
      or util.inspect.custom) directly to the original process.env target
      object. This prevents breaking standard Node.js utilities (like util.inspect)
      or third-party libraries that query symbols on process.env.
  5. defineProperty Trap in envProxy:
    • Implemented the defineProperty trap in envProxy to intercept
      Object.defineProperty(process.env, ...) calls, preventing dependencies
      or internal modules (such as test stubs) from bypassing the proxy's set
      trap and polluting the global environment.
  6. Full Task Execution Isolation:
    • Wrapped the entire main execution loop inside execute in runInIsolatedEnv
      so that the entire agent loop runs with the correct task-isolated environment
      and working directory, completely mitigating concurrency race conditions and
      cross-task environment pollution.
  7. Robust Error Handling in execute:
    • Wrapped the initialization of agentSettings (which includes the synchronous
      call to validateWorkspacePath) in a try-catch block, logging the error
      and notifying the client via the eventBus using pushTaskStateFailed to
      prevent unhandled rejections or server crashes.
    • Appended a .catch block to the runInIsolatedEnv promise to handle setup
      rejections robustly and prevent client hangs.
  8. Native-like Error Behavior in process.chdir:
    • Updated the monkey-patched process.chdir to catch ENOENT errors from
      fs.statSync and throw a new Error with the correct native-like message
      format, ensuring 100% compatibility with Node's native process.chdir
      error behavior.
  9. Adhered to Testing Style Guide:
    • Updated all vi.stubEnv calls in tests to use an empty string ''
      instead of undefined to unset environment variables, and updated the
      assertions to use toBeFalsy() to match.
  10. Explicit CWD for Safety Checker Spawning:
    • Since process.chdir was removed from setTargetDir to prevent
      concurrent race conditions in the server, process.cwd() no longer points
      to the active workspace directory.
    • Updated packages/core/src/safety/checker-runner.ts to explicitly set the
      cwd of the spawned safety checker process to the active workspace
      directory (this.contextBuilder.config.getWorkingDir()), ensuring that
      external safety checkers run in the correct context.
  11. Synchronous validateWorkspacePath Refactoring:
    • Refactored validateWorkspacePath in
      packages/a2a-server/src/agent/executor.ts to be synchronous since it
      contains no asynchronous operations (both process.cwd() and
      resolveToRealPath are synchronous).
    • Removed the corresponding await keywords where it is invoked, reducing
      microtask queue overhead and simplifying the code.
  12. Asynchronous loadEnvironment Refactoring:
    • Refactored loadEnvironment and findEnvFile in
      packages/a2a-server/src/config/config.ts to be asynchronous, using
      fs.promises.access and fs.promises.readFile to avoid blocking the
      event loop in high-concurrency server environments.
    • Updated all callers (in executor.ts, config.ts, app.ts, and
      rce_vulnerability.test.ts) to correctly await the asynchronous
      loadEnvironment function.
  13. Fixed openDiff Signature:
    • Added the missing oldPath: string parameter back to the openDiff
      function signature in packages/core/src/utils/editor.ts to prevent a
      critical runtime ReferenceError when
      getDiffCommand(oldPath, newPath, editor) is called.
  14. Fixed Multi-Workspace Capability:
    • Updated setTargetDir in packages/a2a-server/src/config/config.ts to
      default allowedRoot to the user's home directory (homedir()) instead
      of the server's startup directory (originalCWD) when
      CODER_AGENT_ALLOWED_ROOT is not configured.
    • This restores the multi-workspace capability of a2a-server when run
      globally or as a background service.
  15. Added Missing Google Cloud Auth Variables:
    • Added GOOGLE_APPLICATION_CREDENTIALS, GOOGLE_CLOUD_PROJECT, and
      GEMINI_CLI_USE_COMPUTE_ADC to the allowedServerKeys array in
      packages/a2a-server/src/http/app.ts.
    • This ensures that standard Google Cloud authentication environment
      variables are correctly propagated to process.env during server startup,
      preventing authentication failures.

Related Issues

How to Validate (Cross-Environment Testing)

[!IMPORTANT] Because the previous test failures affected all environments
(Linux, macOS, and Windows) due to platform-independent headless and mock
context issues, validation has been performed across all three platforms to
guarantee complete compatibility and prevent any future pipeline regressions.

  1. macOS (gMac):
    • Successfully ran the full unit and script test suite (npm run test:ci)
      with LC_ALL=en_US.UTF-8 to force the English locale, resolving the
      yargs translation issue.
    • Verified that all 143 tests in @google/gemini-cli-a2a-server pass
      successfully.
    • Verified that ESLint (npm run lint) and TypeScript compilation
      (npm run typecheck) pass with 0 errors or warnings.
  2. Linux (gLinux):
    • Verified that the automated verification script test-check.sh runs
      successfully and all tests pass.
  3. Windows:
    • Verified cross-platform path compatibility (using
      path.parse(resolvedPath).root instead of '/' when isTestEnv is true)
      to ensure complete compatibility on Windows.

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
    • Windows
      • npm run
    • Linux
      • npm run
      • npx

@luisfelipe-alt
luisfelipe-alt requested review from a team as code owners July 20, 2026 23:33
@github-actions github-actions Bot added the size/xl An extra large PR label Jul 20, 2026
@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown

📊 PR Size: size/XL

  • Lines changed: 1586
  • Additions: +1109
  • Deletions: -477
  • Files changed: 18

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical Remote Code Execution (RCE) vulnerability in the a2a-server backend. It introduces robust task-level isolation for environment variables and working directories, ensuring that untrusted workspaces cannot influence the server's configuration or access sensitive credentials. The changes also harden the startup sequence and improve cross-platform stability by ensuring proper path resolution and environment handling.

Highlights

  • Security Isolation: Implemented task-level environment and directory isolation using AsyncLocalStorage and a Proxy on process.env to prevent RCE and cross-task credential leakage.
  • Startup Hardening: Refactored the startup sequence to ensure workspace trust is evaluated before loading environment variables, preventing environment poisoning from untrusted workspaces.
  • Environment Loading: Updated environment loading to ignore workspace-level .env files in untrusted workspaces, restricting them to trusted home directory configurations.
  • Stability and Fixes: Refactored loadEnvironment to be asynchronous, fixed a critical ReferenceError in openDiff, and restored multi-workspace capability.
  • Security Testing: Added a new security test suite (rce_vulnerability.test.ts) to verify RCE mitigation across Linux, macOS, and Windows platforms.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown

🛑 Action Required: Evaluation Approval

Steering changes have been detected in this PR. To prevent regressions, a maintainer must approve the evaluation run before this PR can be merged.

Maintainers:

  1. Go to the Workflow Run Summary.
  2. Click the yellow 'Review deployments' button.
  3. Select the 'eval-gate' environment and click 'Approve'.

Once approved, the evaluation results will be posted here automatically.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements workspace isolation and secure environment variable handling to mitigate remote code execution vulnerabilities. It introduces task-specific environment and working directory isolation using AsyncLocalStorage and a Proxy on process.env. It also restricts .env loading in untrusted workspaces, passes isolated environments to core services (such as shell execution and content generation), and disables external editor spawning in headless mode. The single review comment was identified as a false positive and removed, as the referenced parameter is present in the code but fell outside the diff context. Consequently, there is no further feedback to provide.

@gemini-cli gemini-cli Bot added the status/need-issue Pull requests that need to have an associated issue. label Jul 20, 2026
@luisfelipe-alt

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces workspace and environment isolation for tasks in the agent executor to mitigate potential Remote Code Execution (RCE) vulnerabilities. It implements task-specific environment variable isolation using AsyncLocalStorage and a Proxy on process.env, and monkey-patches process.cwd and process.chdir to prevent cross-task interference. It also restricts environment loading and extension loading in untrusted workspaces, disables external editor spawning in headless mode, and updates core services (like shell execution and content generation) to respect the isolated task environments. The review feedback suggests trimming the workspace path string before checking for emptiness in validateWorkspacePath to prevent whitespace-only values from being accepted.

Comment thread packages/a2a-server/src/agent/executor.ts
@luisfelipe-alt
luisfelipe-alt force-pushed the bugfix/WT-engineer_519269096_cleanfix branch from 4b4166e to f0894ec Compare July 21, 2026 01:39
@luisfelipe-alt

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces task-level environment and workspace isolation to mitigate potential remote code execution (RCE) vulnerabilities in the agent-to-agent server. It implements an AsyncLocalStorage-backed proxy for process.env and monkey-patches process.cwd and process.chdir to isolate environment variables and working directories per task. Additionally, untrusted workspaces are restricted from loading workspace-level .env files or extensions, and external editor spawning is disabled in headless/server mode. Corresponding unit tests have been added to verify these security mitigations. I have no further feedback to provide as there are no review comments.

Note: Security Review did not run due to the size of the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl An extra large PR status/need-issue Pull requests that need to have an associated issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant