Skip to content

fix(security): validate --upload and --output paths against traversal#447

Closed
anshul-garg27 wants to merge 1 commit intogoogleworkspace:mainfrom
anshul-garg27:fix/validate-upload-output-paths
Closed

fix(security): validate --upload and --output paths against traversal#447
anshul-garg27 wants to merge 1 commit intogoogleworkspace:mainfrom
anshul-garg27:fix/validate-upload-output-paths

Conversation

@anshul-garg27
Copy link
Contributor

Summary

  • Add validate_safe_file_path() to src/validate.rs that rejects paths escaping CWD
  • Call it in src/main.rs for both --upload and --output flags before any file I/O
  • Prevents path traversal attacks (e.g. --upload ../../.ssh/id_rsa) especially dangerous when CLI is invoked by AI agents

Details

Previously, --upload and --output accepted arbitrary file paths without validation. The path was passed directly to tokio::fs::read() (upload) or tokio::fs::File::create() (output) with no checks.

An AI agent receiving adversarial input could be tricked into:

  • Reading sensitive files via --upload ../../.ssh/id_rsa
  • Writing to arbitrary locations via --output ../../.bashrc

The new validate_safe_file_path() function:

  1. Rejects control characters (null bytes, etc.)
  2. Resolves the path relative to CWD
  3. Canonicalizes to follow symlinks
  4. Rejects paths that resolve outside CWD

Test plan

  • Relative file paths within CWD are accepted
  • ../../etc/passwd traversal is rejected
  • Null byte injection is rejected
  • Symlink escape to /tmp is rejected (Unix only)
  • Existing validate tests continue to pass

@changeset-bot
Copy link

changeset-bot bot commented Mar 12, 2026

🦋 Changeset detected

Latest commit: 4844e8e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@googleworkspace/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@googleworkspace-bot googleworkspace-bot added the area: core Core CLI parsing, commands, error handling, utilities label Mar 12, 2026
@gemini-code-assist
Copy link
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 significantly enhances the security of the CLI by introducing robust path validation for the --upload and --output command-line arguments. The changes prevent malicious path traversal attacks, which could otherwise lead to unauthorized file reading or writing, particularly in scenarios involving AI agent interaction. A new validation function ensures paths stay within the current working directory and are free of control characters, thereby safeguarding sensitive data and system integrity.

Highlights

  • New Security Validation Function: Introduced validate_safe_file_path() in src/validate.rs to robustly check file paths against traversal attempts, control characters, and symlink escapes.
  • Path Validation Integration: Integrated the new validation function in src/main.rs to validate paths provided via the --upload and --output command-line flags before any file I/O operations occur.
  • Enhanced Security: Mitigated potential path traversal vulnerabilities, which could be exploited by adversarial inputs, especially when the CLI is invoked by AI agents, preventing unauthorized file access or modification.
  • Comprehensive Testing: Added a suite of new unit tests for validate_safe_file_path to ensure correct behavior across various scenarios, including valid relative paths, rejected traversal attempts, control character rejection, and symlink escape prevention.
Changelog
  • .changeset/fix-validate-upload-output-paths.md
    • Added a new changeset entry documenting the security fix for path validation.
  • src/main.rs
    • Added calls to crate::validate::validate_safe_file_path for --upload and --output arguments to enforce path security before file operations.
  • src/validate.rs
    • Implemented a new public function validate_safe_file_path to check for path traversal, control characters, and symlink escapes.
    • Added several new unit tests for validate_safe_file_path, covering valid relative paths, rejected traversal attempts, control character rejection, and symlink escape rejection.
Activity
  • The pull request was created by anshul-garg27 to address a security vulnerability related to path traversal.
  • The author provided a detailed summary, explanation of the vulnerability, and a comprehensive test plan for the implemented changes.
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 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 counter productive. 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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

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

Copy link
Contributor

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

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 a security fix to prevent path traversal vulnerabilities for --upload and --output command-line arguments. A new validate_safe_file_path function has been added to src/validate.rs which rejects paths that attempt to escape the current working directory via .. traversal, contain control characters, or follow symlinks to external locations. This validation is integrated into src/main.rs to be performed before any file I/O operations. Comprehensive unit tests have also been added to src/validate.rs to cover various path validation scenarios.

The --upload and --output flags accepted arbitrary file paths without
validation, allowing path traversal (../../.ssh/id_rsa) and symlink
escape attacks. This is especially dangerous when the CLI is invoked
by an AI agent that may receive adversarial input.

Add validate_safe_file_path() to validate.rs and call it in main.rs
before any file I/O. Rejects paths that resolve outside CWD, contain
control characters, or follow symlinks to external locations.
@anshul-garg27 anshul-garg27 force-pushed the fix/validate-upload-output-paths branch from cc5a973 to 4844e8e Compare March 13, 2026 20:33
@googleworkspace-bot
Copy link
Collaborator

/gemini review

Copy link
Contributor

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

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 aims to fix a path traversal security vulnerability by validating --upload and --output paths. The implementation in src/validate.rs is comprehensive, covering control characters, path traversal, and symlink escapes. However, there is a critical Time-of-check to time-of-use (TOCTOU) vulnerability in src/main.rs. The result of the path validation is discarded, and the original, un-sanitized path is used for file operations, which defeats the purpose of the validation. This must be fixed by using the canonicalized path returned by the validation function.

Comment on lines +221 to +226
if let Some(p) = upload_path {
crate::validate::validate_safe_file_path(p, "--upload")?;
}
if let Some(p) = output_path {
crate::validate::validate_safe_file_path(p, "--output")?;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

security-critical critical

This validation introduces a Time-of-check to time-of-use (TOCTOU) vulnerability. The validate_safe_file_path function is called, and it correctly canonicalizes the path to prevent traversal. However, the returned safe PathBuf is discarded. The original, potentially unsafe path string is then used later for file I/O in executor::execute_method. An attacker could modify the file system between the check and the use (e.g., by replacing a file with a symlink to a sensitive location) to bypass this validation.

To fix this, you must use the canonicalized path returned from the validation function for all subsequent operations. This will likely require refactoring how upload_path and output_path are defined and passed to executor::execute_method to ensure the sanitized path is used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah TOCTOU is inherent to filesystem checks, but this still blocks the most common attack vector (user-supplied paths with ../ in them). a full fix would need O_NOFOLLOW or similar which is a bigger change. this raises the bar significantly vs no validation at all

jpoehnelt pushed a commit that referenced this pull request Mar 17, 2026
…alidate --upload/--output paths

- Cap Retry-After header at 60s to prevent hostile servers from hanging the CLI
- Extract compute_retry_delay() with saturating_pow for safe exponential backoff
- Sanitize mimeType by stripping control characters to prevent MIME header injection
- Add validate_safe_file_path() for --upload and --output path validation
- Gate --upload/--output through path validation in main.rs before any I/O

Consolidates security fixes from PRs #448 and #447.
jpoehnelt added a commit that referenced this pull request Mar 17, 2026
…alidate --upload/--output paths (#523)

* fix(security): cap Retry-After sleep, sanitize upload mimeType, and validate --upload/--output paths

- Cap Retry-After header at 60s to prevent hostile servers from hanging the CLI
- Extract compute_retry_delay() with saturating_pow for safe exponential backoff
- Sanitize mimeType by stripping control characters to prevent MIME header injection
- Add validate_safe_file_path() for --upload and --output path validation
- Gate --upload/--output through path validation in main.rs before any I/O

Consolidates security fixes from PRs #448 and #447.

* chore: regenerate skills [skip ci]

* fix: resolve mimeType sanitization bypass and document TOCTOU caveat

- Restructure resolve_upload_mime() using or_else chain so all code paths
  go through control-char stripping (early returns were bypassing it)
- Document TOCTOU limitation in validate_safe_file_path() as known caveat

* fix: use canonicalized paths for I/O and normalize .. in non-existent suffix

Address review comments:
- main.rs: use canonicalized path from validate_safe_file_path for I/O
  instead of discarding it (closes TOCTOU gap)
- validate.rs: add normalize_dotdot() to resolve .. components in
  non-existent suffix (prevents traversal via doesnt_exist/../../etc/passwd)
- Add regression test for non-existent prefix traversal bypass

---------

Co-authored-by: jpoehnelt-bot <jpoehnelt-bot@users.noreply.github.com>
Co-authored-by: googleworkspace-bot <googleworkspace-bot@users.noreply.github.com>
@jpoehnelt
Copy link
Member

Superseded by #523 (merged as b241a5b) — path validation landed in the combined PR.

@jpoehnelt jpoehnelt closed this Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: core Core CLI parsing, commands, error handling, utilities

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants