T09 · Insecure Skill Coding Practices
- Location
scripts/memory-extract.py:80- Finding
Unvalidated date argument permits directory traversal when reading session files
- Content
View full analysis
Vulnerability Details
File Location:
scripts/memory-extract.py:80-89, 405-411, 437-441
Vulnerability Type: Path traversal / unintended local file access
Risk Level: MediumVulnerable Code
python def get_last_session_content(date: str) -> str: """Get content from last session (either LCM or memory file).""" session_file = MEMORY_DIR / f"{date}.md" if session_file.exists(): return session_file.read_text() # Try LCM via openclaw command (if available) try: result = os.popen("lcm_describe 2>/dev/null").read()The value originates from a command-line argument without format validation:
python parser.add_argument( "--date", type=str, default=None, help="Date for session to process (YYYY-MM-DD)" )It is subsequently passed directly to the file-access function:
python extraction_date = args.date or get_latest_session_date() logger.info(f"Processing date: {extraction_date}") # Get content content = get_last_session_content(extraction_date)Technical Analysis
Although the documented format is
YYYY-MM-DD, the program does not enforce that format.pathlib.Pathpreserves path separators and parent-directory components contained indate. Consequently, a value such as../../targetproduces a path equivalent to:text <workspace>/memory/../../target.mdThis escapes the intended
memorydirectory. If the resulting Markdown file exists and is readable by the current process, its contents are loaded as session data. The contents are then incorporated into the extraction prompt and submitted to the configured local Ollama API.The vulnerability does not bypass operating-system permissions. It nevertheless violates the application’s intended file-access boundary and allows any caller who can control the command-line argument to select arbitrary readable
.mdfiles re ...[truncated 1230 chars]- Remediation
View remediation
Remediation Suggestions
-
Parse and validate
--datebefore using it in a path:python from datetime import datetime def validate_date(value: str) -> str: try: parsed = datetime.strptime(value, "%Y-%m-%d") except ValueError as exc: raise argparse.ArgumentTypeError( "Date must use the YYYY-MM-DD format" ) from exc canonical = parsed.strftime("%Y-%m-%d") if canonical != value: raise argparse.ArgumentTypeError("Date is not canonical") return canonicalRegister this function as the argument type:
python parser.add_argument("--date", type=validate_date, default=None) -
Enforce containment as a defense-in-depth measure:
python session_file = (MEMORY_DIR / f"{date}.md").resolve() memory_root = MEMORY_DIR.resolve() if session_file.parent != memory_root: raise ValueError("Session file must be inside the memory directory") -
Apply the same canonical validation to the date used in report filenames.
-
Read files with an explicit encoding and handle permission and decoding failures safely.
-
Add regression tests for
../, absolute paths, path separators, malformed dates, and valid leap-year dates.
-
