Files
hermes-agent/tools/path_security.py
Teknium 1545afb892 refactor(tools): simplify registry, schema_sanitizer, self_repo_guard, plugin_guard, project_tools, path_security (-25% LOC)
Zero behavior change; tool schemas byte-identical; golden corpus (376 guard
commands, 93 heredoc forms, sanitizer/unrename cases) identical old vs new.

registry.py (1263 -> 924): _memo_check per-pass check_fn memo (2 sites),
_grouped/_toolset_entries toolset grouping (6 sites), _unique_env replaces
_extend_unique, _attr accessor for get_schema/get_toolset_for_tool/get_emoji/
get_max_result_size, fold cache-prune loops, flatten _callable_module walk,
merge guard try-blocks, docstring/comment compaction (all WHY kept).
schema_sanitizer.py (511 -> 392): _rewrite bottom-up tree map shared by
_strip_ref_siblings/strip_nullable_unions/collapse_const_unions, _dict_nodes
generator replaces nested _walk closure, collapsed _const_branch_type guards.
self_repo_guard.py (678 -> 517): _scope_keys state machine as one if/elif
ladder, heredoc opener parsed by one regex (_HEREDOC_OPENER_RE), _masked_line
inlined, _operator_before via rstrip, folded tail expressions.
plugin_guard.py (235 -> 163): positional Finding ctor, packed tables, docs.
project_tools.py (181 -> 156): _activated shared by create/switch, _ACTIONS
dict dispatch replaces the if-chain in _handle_project.
path_security.py (24 -> 18): unused logger/logging import dropped.
2026-09-02 23:56:07 -07:00

19 lines
663 B
Python

"""Shared path validation helpers for tool implementations (skills, cron, credential files)."""
from pathlib import Path
from typing import Optional
def validate_within_dir(path: Path, root: Path) -> Optional[str]:
"""Error message if *path* does not resolve inside *root* (symlinks and ``..`` followed)."""
try:
path.resolve().relative_to(root.resolve())
except (ValueError, OSError) as exc:
return f"Path escapes allowed directory: {exc}"
return None
def has_traversal_component(path_str: str) -> bool:
"""Cheap pre-check for a literal ``..`` component before full resolution."""
return ".." in Path(path_str).parts