resolveAndCheckPath is the canonical entry point used by every filesystem handler that operates on a user-supplied path. It resolves the path against the working directory and validates the result against the allow- and deny-lists. The returned string is the on-disk path the handler should pass to t
(path string)
| 633 | // - On GOOS=windows, [*os.Root] additionally rejects reserved device |
| 634 | // names (NUL, COM1, …), which is a strengthening, not a weakening. |
| 635 | func (t *ToolSet) resolveAndCheckPath(path string) (string, error) { |
| 636 | if t.sandboxBroken { |
| 637 | return "", errors.New("filesystem toolset is disabled due to invalid allow/deny list configuration") |
| 638 | } |
| 639 | |
| 640 | resolved := t.resolvePath(path) |
| 641 | if t.allowList == nil && t.denyList == nil { |
| 642 | return resolved, nil |
| 643 | } |
| 644 | realPath, err := resolveRealPath(resolved) |
| 645 | if err != nil { |
| 646 | return "", fmt.Errorf("resolving %q: %w", path, err) |
| 647 | } |
| 648 | if t.denyList != nil && t.denyList.contains(realPath) { |
| 649 | return "", fmt.Errorf("path %q is inside a denied directory (%s)", path, t.denyList.describe()) |
| 650 | } |
| 651 | if t.allowList != nil && !t.allowList.contains(realPath) { |
| 652 | return "", fmt.Errorf("path %q is outside the allowed directories (%s)", path, t.allowList.describe()) |
| 653 | } |
| 654 | return resolved, nil |
| 655 | } |
| 656 | |
| 657 | // rootedAccess returns the [*os.Root] handle and rooted (slash-separated) |
| 658 | // name for resolved when the allow-list is configured. |