Skip to content

fix: look through all matching permissions in is_path_allowed #10679

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

rubydusa
Copy link

@rubydusa rubydusa commented May 31, 2025

Motivation

Closes #10677

Solution

Solution proposed in #10677 (comment)
(iterate through all matching longest paths)

PR Checklist

  • Added Tests
  • Added Documentation
  • Breaking changes

Copy link
Member

@mattsse mattsse left a comment

Choose a reason for hiding this comment

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

these are slightly sensitive checks so we should think about this a bit more

Comment on lines +80 to +99
pub fn find_all_permissions(&self, path: &Path) -> Vec<FsAccessPermission> {
let mut matching_permissions = Vec::new();
let mut max_path_len = 0;

// First pass: find all matching permissions and determine the maximum path length
for perm in &self.permissions {
let permission_path = dunce::canonicalize(&perm.path).unwrap_or(perm.path.clone());
if path.starts_with(&permission_path) {
let path_len = permission_path.components().count();
if path_len > max_path_len {
max_path_len = path_len;
matching_permissions.clear();
matching_permissions.push(perm.access);
} else if path_len == max_path_len {
matching_permissions.push(perm.access);
}
}
}

matching_permissions
Copy link
Member

Choose a reason for hiding this comment

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

we now have both find_permission and find_all_permissions

I think we only want to keep one impl for this to ensure we always use this behaviour.

the internal check is slightly different from what we have in find_permission, why do we need to account for length here

Copy link
Author

Choose a reason for hiding this comment

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

find_permission also accounts for length:

// the longest path takes precedence
if perm.path < active_perm.path {
    continue;
}

https://github.com/foundry-rs/foundry/pull/10679/files/3d4b883ffbe6b57093d594b7a636295cac49af6e#diff-7a174b097c5cb093b0f560f9cb870fa36e01b702f3fa1cb5496868b791bf5f44R58-R61

It's needed because you could have something like this:

fs_permissions = [
    { access = "read-write", path = "./artifacts" },
    { access = "read", path = "./artifacts/sensitive" }
]

you shouldn't be able to write to ./artifacts/sensitive/data.json

Copy link
Author

Choose a reason for hiding this comment

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

I think we only want to keep one impl for this to ensure we always use this behaviour.

Maybe we can refactor both functions to use a third function for shared logic? I just didn't want to touch find_permission since I didn't know all the places where it's used

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we can refactor both functions to use a third function for shared logic? I just didn't want to touch find_permission since I didn't know all the places where it's used

@rubydusa I think this makes sense, we could also rename current find_permission to find_path_permission for clarity

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

Successfully merging this pull request may close these issues.

bug(forge): Having both a access = read and access = write for the same path in fs_permissions does not work
3 participants