Skip to content

fix(security): harden runtime path validation for upload/output#363

Open
abhinavkale-dev wants to merge 3 commits intogoogleworkspace:mainfrom
abhinavkale-dev:path-hardening-upload-output
Open

fix(security): harden runtime path validation for upload/output#363
abhinavkale-dev wants to merge 3 commits intogoogleworkspace:mainfrom
abhinavkale-dev:path-hardening-upload-output

Conversation

@abhinavkale-dev
Copy link

Refs #251

Description

This PR hardens runtime file path handling for dynamic --upload and --output.

It adds shared path validators for safe input/output file paths and applies them at the execution boundary so unsafe absolute paths, traversal (..), and escapes outside the current working directory are rejected before dry-run or execution.

This fixes the issue where commands like these were previously accepted:

./.local/bin/gws drive files create --upload /etc/hosts --dry-run
./.local/bin/gws drive files list --output /tmp/gws-proof.bin --dry-run

After this change, those inputs fail with validation errors instead of proceeding.

Dry Run Output:

{
  "error": {
    "code": 400,
    "message": "--output must be a relative path, got absolute path '/tmp/gws-proof.bin'",
    "reason": "validationError"
  }
}

Checklist:

  • My code follows the AGENTS.md guidelines (no generated google-* crates).
  • I have run cargo fmt --all to format the code perfectly.
  • I have run cargo clippy -- -D warnings and resolved all warnings.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have provided a Changeset file (e.g. via pnpx changeset) to document my changes.

@changeset-bot
Copy link

changeset-bot bot commented Mar 10, 2026

🦋 Changeset detected

Latest commit: 442a4d7

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

@google-cla
Copy link

google-cla bot commented Mar 10, 2026

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.

@googleworkspace-bot googleworkspace-bot added area: skills area: http area: core Core CLI parsing, commands, error handling, utilities labels Mar 10, 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 strict validation for file paths provided via the --upload and --output flags. The changes prevent malicious or unintended file system access by ensuring that all specified paths are relative to the current working directory and do not attempt path traversal or refer to locations outside the intended scope. This proactive validation improves the overall robustness and security posture of the application.

Highlights

  • Security Hardening: Implemented robust runtime file path validation for --upload and --output flags to prevent security vulnerabilities like path traversal and the use of absolute paths.
  • Path Validation Logic: Introduced new shared path validators (validate_safe_input_file_path and validate_safe_output_file_path) that enforce paths to be relative, resolve within the current working directory, and reject traversal attempts.
  • Execution Boundary Enforcement: Applied the new path validators at the execution boundary within execute_method, ensuring that unsafe paths are rejected before any dry-run or actual command execution.
  • Comprehensive Testing: Added new unit tests to cover various scenarios for path validation, including rejection of absolute paths, path traversal, symlink escapes, and acceptance of safe relative paths for both input and output operations.
Changelog
  • .changeset/path-hardening-upload-output.md
    • Hardened runtime file path handling for dynamic --upload and --output flags by enforcing safe relative paths within the current working directory.
  • skills/gws-gmail-forward/SKILL.md
    • Clarified that forwarded Gmail messages are sent as new messages rather than forcing them into the original thread.
  • src/executor.rs
    • Added validate_execution_paths function to centralize path validation for --upload and --output parameters.
    • Integrated validate_execution_paths into the execute_method to perform path validation at the execution boundary.
    • Added new tokio::test cases to verify that execute_method correctly rejects absolute and unsafe relative paths for --upload and --output during dry-run.
    • Added a tokio::test case to confirm that execute_method accepts safe relative paths during dry-run.
  • src/validate.rs
    • Implemented validate_safe_input_file_path to ensure --upload paths are relative, resolve within the CWD, and point to an existing regular file.
    • Implemented validate_safe_output_file_path to ensure --output paths are relative, resolve within the CWD, and do not point to existing directories.
    • Added comprehensive unit tests for validate_safe_input_file_path covering valid relative files, rejection of absolute paths, path traversal, and symlink escapes.
    • Added comprehensive unit tests for validate_safe_output_file_path covering valid nested paths, rejection of absolute paths, path traversal, and symlink escapes.
Activity
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 important security hardening for file path validation. The new validation logic in src/validate.rs is comprehensive and covers various attack vectors like absolute paths, path traversal, and symlink escapes. However, there is a critical issue in src/executor.rs where the validated, canonical paths are discarded, and the original, potentially unsafe paths are used for file operations. This undermines the security fix and leaves a TOCTOU (Time-of-check to time-of-use) vulnerability. My review includes a critical comment with a suggestion to fix this by propagating and using the safe canonical paths.

Comment on lines +350 to +361
fn validate_execution_paths(
output_path: Option<&str>,
upload_path: Option<&str>,
) -> Result<(), GwsError> {
if let Some(path) = output_path {
crate::validate::validate_safe_output_file_path(path)?;
}
if let Some(path) = upload_path {
crate::validate::validate_safe_input_file_path(path)?;
}
Ok(())
}
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

This validation function is a great addition for security. However, it currently has a critical flaw: it performs the validation but discards the resulting canonical (safe) path. The rest of the code continues to use the original, potentially unsafe output_path and upload_path strings. This creates a Time-of-check to time-of-use (TOCTOU) vulnerability, as the file system could be manipulated between the check and the actual file operation.

To fix this, validate_execution_paths should return the canonical PathBufs. Then, execute_method must use these canonical paths for all subsequent file operations.

After applying the suggestion below, you will also need to update execute_method to capture and use these canonical paths, passing them down to build_http_request and handle_binary_response. Those functions will need to be adjusted to accept &Path instead of &str for file paths.

Suggested change
fn validate_execution_paths(
output_path: Option<&str>,
upload_path: Option<&str>,
) -> Result<(), GwsError> {
if let Some(path) = output_path {
crate::validate::validate_safe_output_file_path(path)?;
}
if let Some(path) = upload_path {
crate::validate::validate_safe_input_file_path(path)?;
}
Ok(())
}
fn validate_execution_paths(
output_path: Option<&str>,
upload_path: Option<&str>,
) -> Result<(Option<PathBuf>, Option<PathBuf>), GwsError> {
let canonical_output_path = output_path
.map(crate::validate::validate_safe_output_file_path)
.transpose()?;
let canonical_upload_path = upload_path
.map(crate::validate::validate_safe_input_file_path)
.transpose()?;
Ok((canonical_output_path, canonical_upload_path))
}

@github-actions
Copy link
Contributor

/gemini review

@abhinavkale-dev
Copy link
Author

@jpoehnelt, Gemini’s canonical-path finding is fixed in 93f78b0.

The remaining extra commit on this PR,

  • 2194edb chore: regenerate skills [skip ci]

is unrelated and is not part of the security fix. It is being added by my fork workflow and is causing the CLA check to fail again by adding github-actions[bot] as a contributor.

The intended fix commits are:

  • 5ea0dad
  • 93f78b0

If easier, please review/cherry-pick only those two commits.

@abhinavkale-dev abhinavkale-dev force-pushed the path-hardening-upload-output branch from 2194edb to 93f78b0 Compare March 10, 2026 04:34
@github-actions
Copy link
Contributor

/gemini review

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 area: http

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants