{"record":{"id":"9af7c23bd4d28d4a","repo":"langchain-ai/deepagents","slug":"permission-path-must-not-contain-path-r","errorCode":null,"errorMessage":"Permission path must not contain '..': {path!r}","messagePattern":"Permission path must not contain '\\.\\.': (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/deepagents/deepagents/middleware/filesystem.py","lineNumber":417,"sourceCode":"\n        Best paired with patterns that have a literal leading anchor (e.g.,\n        `/secrets/**`, `/projects/*/secrets/**`). Bulk tools\n        (`ls`/`glob`/`grep`) fire the interrupt based on whether their\n        search subtree could overlap the rule's anchored prefix, so a fully\n        unanchored pattern (`/**/secrets`) collapses to `/` and\n        conservatively over-fires for any bulk call.\n    \"\"\"\n\n    def __post_init__(self) -> None:\n        \"\"\"Validate permission path patterns.\"\"\"\n        for path in self.paths:\n            if not path.startswith(\"/\"):\n                msg = f\"Permission path must start with '/': {path!r}\"\n                raise ValueError(msg)\n            parts = PurePosixPath(path.replace(\"\\\\\", \"/\")).parts\n            if \"..\" in parts:\n                msg = f\"Permission path must not contain '..': {path!r}\"\n                raise ValueError(msg)\n            if \"~\" in parts:\n                msg = f\"Permission path must not contain '~': {path!r}\"\n                raise NotImplementedError(msg)\n\n\ndef _check_fs_permission(\n    rules: list[FilesystemPermission],\n    operation: FilesystemOperation,\n    path: str,\n) -> Literal[\"allow\", \"deny\", \"interrupt\"]:\n    for rule in rules:\n        if operation not in rule.operations:\n            continue\n        if any(wcglob.globmatch(path, pattern, flags=_FS_WCMATCH_FLAGS) for pattern in rule.paths):\n            return rule.mode\n    return \"allow\"\n\n","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/deepagents/deepagents/middleware/filesystem.py#L399-L435","documentation":"FilesystemPermission patterns must not contain '..' path segments; parent-directory traversal would make permission rules ambiguous or let rules escape their intended tree. Violating patterns raise this ValueError in __post_init__.","triggerScenarios":"Constructing FilesystemPermission with a pattern like '/a/../etc' or '/..' — after converting backslashes, '..' appears in PurePosixPath parts.","commonSituations":"Concatenating user-supplied path fragments without normalization; porting Windows-style relative patterns; generated patterns from templates that inject '..'.","solutions":["Remove '..' by normalizing/resolving the path (os.path.normpath or posixpath.normpath) before building the pattern","Express the intended target directly without traversal segments","Sanitize user input to reject traversal attempts early"],"exampleFix":"// before\nFilesystemPermission(paths=[\"/project/../secrets\"])\n// after\nFilesystemPermission(paths=[\"/secrets\"])","handlingStrategy":"validation","validationCode":"import posixpath\ndef ensure_no_dotdot(p: str) -> str:\n    normalized = posixpath.normpath(p)\n    if \"..\" in posixpath.normpath(p).split(\"/\"):\n        raise ValueError(f\"permission path must not contain '..': {p!r}\")\n    return normalized","typeGuard":null,"tryCatchPattern":"try:\n    perm = FilesystemPermission(paths=paths)\nexcept ValueError as e:\n    logger.error(\"traversal in permission pattern: %s\", e)\n    raise","preventionTips":["Normalize with posixpath.normpath before creating permissions","Never concatenate untrusted fragments into permission patterns","Treat '..' in config as a security signal, not just a validation failure"],"tags":["python","filesystem","security","validation"],"backgroundTag":"path-traversal-denied","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}