Skip to content

enforcePermission doc/code mismatch: unparsable paths throw instead of being silently skipped #744

Description

The doc comment on enforcePermission (src/permissions/enforce.ts) says:

Paths that fail validatePath are silently skipped — the tool's own input validation will surface a better error.

but the implementation calls validatePath(path) without catching, so any non-absolute (or ../~-carrying) path throws path must be absolute: ... out of the permission layer instead of reaching the tool's own validation:

function enforcePermission(rules, operation, path) {
  if (rules.length === 0) return;
  const canonical = validatePath(path); // throws — not "silently skipped"
  if (decidePathAccess(rules, operation, canonical) === "deny") throw new Error(...);
}

Observed in deepagents@1.10.2. The practical consequence: on any graph configured with permissions, EVERY filesystem tool call with a relative path fails with the validation error — including pure reads, and including operations no rule covers — whereas the same relative path works fine on a rule-less graph (the legacy FilesystemBackend resolves it under rootDir).

Sibling detail in the same file: filterByPermissions DOES catch the validatePath throw (entries with unparsable paths are included), so the two halves of the module currently disagree about the documented contract.

Note for a potential fix: making the code match the doc (skip unparsable paths) has a subtle consequence — a deny rule would then never fire for relative paths at the rule layer; the backend's rootDir resolution would apply the operation instead. Depending on intent, canonicalizing relative paths against the backend root before rule evaluation (rather than skipping them) may be the safer contract.

Happy to provide more detail — we hit this downstream (stigmer/stigmer#429) and worked around it by normalizing paths in middleware before enforcement.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions