Skip to content

Files safeJoin rejects valid paths under symlinked storage roots #62

Description

@Qyra-One

Bug

The Files service path confinement guard can reject valid paths under /me or /public when the configured storage root is reached through a symlink/canonicalized prefix. On macOS this shows up with temp/data paths under /var that filepath.EvalSymlinks resolves to /private/var; the lexical root remains /var/..., so safeJoin incorrectly treats the resolved existing prefix as outside the area. The same can happen if an operator configures AGENTBBS_DATA_DIR/files root through a symlink.

Reproduction

On a system where the root path canonicalizes differently (or with a symlinked files root), run:

go test ./internal/files

Before the fix, valid paths such as /me/notes.txt can fail with files: path escapes its area. A smaller reproducer is safeJoin(aliasRoot, "notes.txt") where aliasRoot is a symlink to the real area root.

Expected

  • Legitimate paths under a symlinked/canonicalized area root should be accepted.
  • Symlink escapes below the area root, e.g. area/escape -> /etc, should still be rejected.

Proposed fix

Canonicalize the area root before comparing it with the EvalSymlinks result of the longest existing prefix, while keeping the initial lexical containment check. I have a PR with regression tests for both the allowed symlinked-root case and the escaping child-symlink case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions