Skip to content

fix(a2a-server): never derive workspace trust from request agentSettings in createTask - #29525

Open
venkatchalla06 wants to merge 1 commit into
google-gemini:mainfrom
venkatchalla06:fix/a2a-createtask-force-untrusted
Open

venkatchalla06 wants to merge 1 commit into
google-gemini:mainfrom
venkatchalla06:fix/a2a-createtask-force-untrusted

Conversation

@venkatchalla06

Copy link
Copy Markdown

What

CoderAgentExecutor.createTask() forwarded the caller-supplied agentSettings directly into runInIsolatedEnv(), where setIsTrusted(agentSettings, …) honors agentSettings.isTrusted. The other two entry points that build a task from external input already normalize their settings first:

  • execute() → { ...raw, workspacePath: validateWorkspacePath(...), isTrusted: false }
  • reconstruct() → same shape, isTrusted: false

createTask() did neither, so a task created through the POST /tasks handler (http/app.ts, which passes req.body.agentSettings unchanged) could set isTrusted: true and mark its workspace trusted. A trusted workspace re-enables workspace-declared mcpServers/tools and workspace .env loading (GEMINI_YOLO_MODE), which is command execution during task init — the same class the b-519269096 / #28470 hardening closed for execute()/reconstruct().

Fix

Normalize createTask()'s input the same way as the sibling methods: force isTrusted: false and route workspacePath through validateWorkspacePath(). The only internal caller (execute()) already passes normalized settings, so this is a no-op there; it just removes request-controlled trust from the createTask path.

const rawAgentSettings: AgentSettings = agentSettingsInput || {
  kind: CoderAgentEvent.StateAgentSettingsEvent,
  workspacePath: process.cwd(),
};
const agentSettings: AgentSettings = {
  ...rawAgentSettings,
  workspacePath: validateWorkspacePath(rawAgentSettings.workspacePath),
  isTrusted: false,
};

Scope / severity note

The a2a-server binds to localhost (http/app.ts: expressApp.listen(port, 'localhost', …)), so this is not a remote-network issue. It is a defense-in-depth / trust-model consistency fix: request-supplied settings should never be able to elevate workspace trust, matching the invariant execute()/reconstruct() already enforce.

Suggested regression test

Assert that a createTask call carrying isTrusted: true still yields an untrusted config (mirror the mocking used in the existing executor tests):

it('createTask ignores caller-supplied isTrusted:true (workspace stays untrusted)', async () => {
  const executor = new CoderAgentExecutor();
  const wrapper = await executor.createTask('t1', 'c1', {
    kind: CoderAgentEvent.StateAgentSettingsEvent,
    workspacePath: tmpWorkspace,      // dir containing a .gemini/settings.json with mcpServers
    isTrusted: true,                  // caller-supplied
  } as AgentSettings);
  expect(wrapper.task.config.isTrusted()).toBe(false);
});

Refs

Hardens the trust check from #28470 (b-519269096) at the one entry point it missed. No behavior change for trusted local CLI flows.

🤖 Generated with Claude Code

@venkatchalla06
venkatchalla06 requested a review from a team as a code owner September 27, 2026 08:50
@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 hardens the security model of the a2a-server by ensuring that workspace trust cannot be derived from user-provided request settings. By normalizing input in the createTask method, it aligns the trust-checking logic with other entry points, preventing potential unauthorized command execution via workspace-declared tools or environment variables.

Highlights

  • Security Hardening: Updated createTask to prevent workspace trust elevation from caller-supplied agent settings, closing a bypass vector for command execution.
  • Input Normalization: Forced isTrusted to false and implemented workspace path validation in createTask to ensure consistency with existing entry points like execute and reconstruct.
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 added the size/s A small PR label Sep 27, 2026
@github-actions

github-actions Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

📊 PR Size: size/S

  • Lines changed: 27
  • Additions: +26
  • Deletions: -1
  • Files changed: 1

@google-cla

google-cla Bot commented Sep 27, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@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 hardens the task creation process in CoderAgentExecutor.createTask by validating the workspace path and forcing isTrusted to false, preventing tasks from bypassing trust checks. The review feedback points out that any error thrown during workspace path validation is not caught, which could lead to unhandled rejections; it suggests wrapping the validation in a try-catch block to properly report the failure to the event bus.

Comment on lines +250 to +254
const agentSettings: AgentSettings = {
...rawAgentSettings,
workspacePath: validateWorkspacePath(rawAgentSettings.workspacePath),
isTrusted: false,
};

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.

high

When validating the workspace path in createTask, any error thrown by validateWorkspacePath (such as ENOENT from resolveToRealPath) is not caught. This can lead to unhandled rejections and prevents the failure from being reported to the eventBus. Wrapping this in a try-catch block and calling pushTaskStateFailed ensures consistent error handling and reporting, matching the behavior in reconstruct() and execute().

let agentSettings: AgentSettings;
try {
  agentSettings = {
    ...rawAgentSettings,
    workspacePath: validateWorkspacePath(rawAgentSettings.workspacePath),
    isTrusted: false,
  };
} catch (error) {
  logger.error(
    "[CoderAgentExecutor] Invalid workspace path during task creation for task " + taskId + ":",
    error,
  );
  if (eventBus) {
    void pushTaskStateFailed(error, eventBus, taskId, contextId);
  }
  throw error;
}
References
  1. Ensure consistent path resolution by using a single, robust function (e.g., resolveToRealPath) for all related path validations, including internal validations in components like WorkspaceContext.

…ngs in createTask

createTask() forwarded the caller-supplied agentSettings straight into
runInIsolatedEnv(), where setIsTrusted() honors agentSettings.isTrusted. Every
other entry point that builds a task from external input — execute() and
reconstruct() — already normalizes agentSettings to isTrusted:false and runs the
workspacePath through validateWorkspacePath(). createTask() was the one that did
not, so a task created via the POST /tasks handler (which passes req.body
.agentSettings unchanged) could set isTrusted:true and mark its workspace
trusted. That re-enables workspace-declared mcpServers/tools and workspace .env
loading (GEMINI_YOLO_MODE), i.e. command execution — the exact class google-gemini#28470
closed for the other paths.

Normalize createTask's input the same way (force isTrusted:false, validate the
workspace path). The workspace-path validation is wrapped in try/catch that logs
and reports the failure via pushTaskStateFailed before re-throwing, matching the
error handling in reconstruct() and execute() so a bad path cannot become an
unhandled rejection. The only internal caller (execute()) already passes
normalized settings, so this is a no-op there and simply removes
request-controlled trust from the createTask path.
@venkatchalla06
venkatchalla06 force-pushed the fix/a2a-createtask-force-untrusted branch from 15d455e to e92bba9 Compare September 30, 2026 08:09
@gemini-cli

gemini-cli Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Hi there! Thank you for your interest in contributing to Gemini CLI.

To ensure we maintain high code quality and focus on our prioritized roadmap, we only guarantee review and consideration of pull requests for issues that are explicitly labeled as 'help wanted'.

This PR will be closed in 7 days if it remains without that designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding.

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant