Skip to content

Conversation

yayami3
Copy link
Contributor

@yayami3 yayami3 commented Sep 9, 2025

Fixes an issue where relative path patterns in agent toolsSettings (e.g., './denied/**') would not match files accessed with different relative path formats (e.g., 'denied/file.txt').

Changes:

  • Enhanced canonicalizes_path() to properly normalize relative paths
  • Added path component resolution for '.' and '..' segments
  • Ensures consistent path matching for both fs_read and fs_write tools

This resolves a security issue where deniedPaths could be bypassed by using different relative path formats.

*Issue #2818

Description of changes:

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Fixes an issue where relative path patterns in agent toolsSettings
(e.g., './denied/**') would not match files accessed with different
relative path formats (e.g., 'denied/file.txt').

Changes:
- Enhanced canonicalizes_path() to properly normalize relative paths
- Added path component resolution for '.' and '..' segments
- Ensures consistent path matching for both fs_read and fs_write tools

This resolves a security issue where deniedPaths could be bypassed
by using different relative path formats.
let expanded = shellexpand::full_with_context(path_as_str, home_dir, context)?;

// Convert all relative paths to absolute paths (including glob patterns)
if !expanded.starts_with("/") && !expanded.starts_with("~") {
Copy link
Contributor

Choose a reason for hiding this comment

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

~ is already expanded I think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Consider using Path::new(&expanded).is_relative

@erbenmo
Copy link
Contributor

erbenmo commented Sep 18, 2025

I noticed a same issue in https://github.com/aws/amazon-q-developer-cli/pull/2926/files

My change only applies normalization to fs_read and only to the file being read. I think we should probably use your change since it covers fs_write as well as the allowed_path/denied_path pattern.

Can you add some testing in your change? Feel free to take mine

let current_dir = os.env.current_dir()?;
let absolute_path = current_dir.join(expanded.as_ref());
// Normalize the path to remove ./ and ../ components
match absolute_path.canonicalize() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I am wondering should we just always use the normalize_path() method for code simplicity and consistency?

@kkashilk
Copy link
Contributor

This doesn't currently handle this test -

let result = canonicalizes_path(&test_os, "/absolute/./../path").unwrap();
assert_eq!(result, "/path");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants