langchain-ai/deepagents · error · InvalidGlobPatternError
Path traversal not allowed in glob pattern {pattern!r}
Error message
Path traversal not allowed in glob pattern {pattern!r} What it means
`compile_grep_include_glob` compiles include/exclude glob patterns used by glob and grep across all backends. Patterns containing a literal `..` path component are rejected up-front with `InvalidGlobPatternError` so traversal cannot behave inconsistently between backends (accepted in one, silently empty in another).
Source
Thrown at libs/deepagents/deepagents/backends/utils.py:146
Args:
pattern: Glob include pattern.
Returns:
Predicate accepting a search-root-relative POSIX path; returns True when
the path is included by `pattern`.
Raises:
InvalidGlobPatternError: If the pattern contains a `..` segment, or if
`wcmatch` refuses it (e.g. brace expansion past its limit). Note
most malformed patterns (`*.{py`, `[a-`) do not raise -- they
compile and simply match nothing.
"""
# Reject traversal here rather than per-backend: every backend routes
# through this function, so a single check keeps `../*.py` from being an
# exception in one backend and a silent empty result in another.
if ".." in pattern.replace("\\", "/").split("/"):
msg = f"Path traversal not allowed in glob pattern {pattern!r}"
raise InvalidGlobPatternError(msg)
flags = wcglob.BRACE | wcglob.GLOBSTAR
# A leading `/` anchors to the search root: strip it so it matches against
# the (slash-less) relative path, but decide anchoring from the original
# pattern so `/*.py` stays root-anchored instead of collapsing to a
# basename-at-any-depth match.
anchored = "/" in pattern
try:
compiled = wcglob.compile(pattern.lstrip("/"), flags=flags)
except Exception as exc:
# `wcmatch` only raises private types (`wcmatch._wcparse.PatternLimitException`),
# so catch broadly and re-raise a public type: every backend can then catch
# one public type instead of importing from a private module. Log first --
# the breadth also swallows genuine bugs (a non-`str` pattern, a wcmatch
# version bump), which would otherwise reach the user as "invalid pattern"
# for a pattern that is perfectly valid.
logger.warning("wcmatch refused glob pattern %r (%s): %s", pattern, type(exc).__name__, exc)
msg = f"Invalid glob pattern {pattern!r}: {exc}"View on GitHub (pinned to a1af029e6e)
Solutions
- Remove the `..` component: anchor the pattern to the search root instead (e.g. `**/*.py`)
- Pass the intended root as the search path/`path=` argument rather than climbing with `..` in the pattern
- Sanitize or reject user/LLM-supplied globs containing `..` before invoking the tool
- Catch `InvalidGlobPatternError` to return a clear tool error instead of crashing
Example fix
// before
backend.glob('../workspace/*.py')
// after
backend.glob('*.py', path='/workspace/') Defensive patterns
Strategy: validation
Validate before calling
def safe_glob(pattern: str) -> str:
if '..' in pattern.replace('\\', '/').split('/'):
raise ValueError(f'path traversal in glob: {pattern!r}')
return pattern
backend.glob(safe_glob('**/*.py'), path='/workspace') Type guard
def is_safe_glob(pattern: object) -> bool:
return isinstance(pattern, str) and '..' not in pattern.replace('\\', '/').split('/') Try / catch
from deepagents.backends.utils import InvalidGlobPatternError
try:
files = backend.glob(pattern)
except InvalidGlobPatternError:
files = backend.glob('**/*') # safe fallback pattern Prevention
- Never concatenate parent-relative paths into glob patterns; use the `path=` parameter instead
- Sanitize LLM/user-supplied globs for `..` components
- Anchor patterns at the virtual root (`/workspace/*.py` or `*.py` with path=)
- Return a clear tool error (InvalidGlobPatternError) instead of letting agents retry traversal
When it happens
Trigger: Calling `glob('**/../*.py')` or passing an include/exclude glob like `'../src/*.py'` to grep; building glob strings by naive concatenation of a relative parent path with a wildcard.
Common situations: Letting an LLM-generated tool call supply the glob; constructing patterns from user-supplied subdirectories; older code that used filesystem-style relative globs now routed through the virtual path layer.
Related errors
- Path traversal not allowed
- Path traversal not allowed: {path}
- Path traversal detected after normalization: {path} -> {norm
- Path must start with one of {allowed_prefixes}: {path}
- {info.filename}: unsafe zip path
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/5fe5c25bccd99181.
Report an issue: GitHub.