Trust store for skill directories that resolve outside trusted roots.
load_skill_content refuses to read a SKILL.md whose resolved path falls
outside every trusted skill root — this stops a symlink inside a skill
directory from reading arbitrary files. The static escape hatch is the
DEEPAGENTS_CODE_EXTRA_SKILLS_DIRS env var / [skills].extra_allowed_dirs
config allowlist.
This module adds an in-the-moment, persistent approval path (mirroring
deepagents_code.mcp_trust): when a skill resolves outside the trusted roots,
the user is asked once to allow the resolved target directory, and the decision
is remembered. Trust is keyed by the approved target directory — the canonical
path resolved and shown to the user at approval time, stored as-is and never
re-resolved.
Two distinct post-approval swaps are caught by two distinct layers, so neither grants access the user never approved:
SKILL.md path) at a new target is
caught by containment enforcement in load_skill_content: the new target is
not on the allowlist, so the read is refused and the user is re-prompted.
The stored trust entry — the original resolved target — is untouched.resolve()-to-self re-verification in
load_trusted_skill_dirs, which drops the stale entry rather than following
the injected symlink to a directory the user never approved.Trust entries are app-managed bookkeeping (a set of approved directories), not
user-facing configuration, so they live alongside the other state files under
~/.deepagents/.state/skill_trust.json rather than in the hand-editable
config.toml.
Check whether a resolved skill directory has been trusted.
Persist trust for a resolved skill directory.
Remove trust for a skill directory.
Matches on both the approved (expanduser-only) key form that
trust_skill_dir stores and the fully-resolved form, so a caller can
revoke either by the path they see in skills trust list or by the
original symlink path.
Remove all trusted skill directories.
Return the sorted list of trusted skill directory paths.
Return trusted directories paired with their approval timestamps.
The audit surface for the trusted_at metadata that trust_skill_dir
records: list_trusted_skill_dirs returns only paths (all enforcement
needs), so this is the one reader of the timestamp, used by skills trust list to show when each directory was approved.
Return verified trusted skill directories as canonical Path objects.
Used to extend the containment allowlist passed to load_skill_content.
Stored entries are the exact canonical directory the user approved (already resolved at trust time). Each entry is re-verified here rather than blindly re-resolved: if a stored path no longer resolves to itself — because it, or a parent component, was replaced with a symlink after approval — the current resolution would point somewhere the user never approved. Such entries are dropped (and logged) instead of silently allowlisting the swapped target, so a post-approval symlink swap re-prompts rather than granting access.
Outcome of a revoke_skill_dir_trust call.
Distinguishing NOT_FOUND from REMOVED lets the CLI print an honest
message instead of a false success when the target was never trusted (a
plain bool collapsed the two).