all2md.mcp.security
Security utilities for MCP server path validation.
This module provides MCP-specific path validation and allowlist enforcement for secure file access in the MCP server.
Functions
validate_read_path: Validate a path is in the read allowlist
validate_write_path: Validate a path is in the write allowlist
prepare_allowlist_dirs: Convert allowlist strings to resolved Paths
secure_open_for_write: Open a file for writing with TOCTOU protection
- exception all2md.mcp.security.MCPSecurityError
Bases:
All2MdErrorRaised when MCP security validation fails.
Initialize MCP security error.
- Parameters:
message (str) – Error message
path (str | None) – Path that failed validation
- __init__(message: str, path: str | None = None) None
Initialize MCP security error.
- Parameters:
message (str) – Error message
path (str | None) – Path that failed validation
- all2md.mcp.security.validate_read_path(path: str | Path, read_allowlist_dirs: list[str | Path] | None) Path
Validate a path is allowed for reading.
- Parameters:
path (str | Path) – Path to validate
read_allowlist_dirs (list[str | Path] | None) – List of allowed read directory paths (strings or resolved Path objects), or None to allow all
- Returns:
Validated, resolved path
- Return type:
Path
- Raises:
MCPSecurityError – If path is not in read allowlist or validation fails
Notes
The allowlist comparison uses resolved canonical paths, which are case-normalized on Windows. This prevents bypass via case variations on case-insensitive filesystems.
- all2md.mcp.security.validate_write_path(path: str | Path, write_allowlist_dirs: list[str | Path] | None) Path
Validate a path is allowed for writing.
Uses security checks consistent with validate_local_file_access to ensure proper path validation and symlink resolution in all cases.
- Parameters:
path (str | Path) – Path to validate
write_allowlist_dirs (list[str | Path] | None) – List of allowed write directory paths (strings or resolved Path objects), or None to allow all
- Returns:
Validated, resolved path
- Return type:
Path
- Raises:
MCPSecurityError – If path is not in write allowlist or validation fails
Notes
The allowlist comparison uses resolved canonical paths, which are case-normalized on Windows. This prevents bypass via case variations on case-insensitive filesystems.
- all2md.mcp.security.resolve_workspace_path(raw: str | Path, allowlist_dirs: list[str | Path] | None, *, must_exist: bool) Path | None
Resolve a possibly-relative path against the workspace (allowlist) dirs.
The first allowlist directory acts as the working directory, so agents can refer to files by a bare name or workspace-relative path instead of always supplying an absolute path.
- Parameters:
raw (str | Path) – Path supplied by the caller. May be absolute, workspace-relative, or a bare filename.
allowlist_dirs (list[str | Path] | None) – Allowed directories (strings or resolved Paths). Used as candidate bases for relative paths, in order.
must_exist (bool) – When True (reads), each candidate is probed and the first that exists is returned, or None if none exist. When False (writes), the path is simply anchored to the first allowlist directory (or CWD) without probing.
- Returns:
The resolved path, or None when
must_existis True and no candidate exists. Absolute inputs are returned unchanged.- Return type:
Path | None
- all2md.mcp.security.prepare_allowlist_dirs(paths: list[str | Path] | None) list[Path] | None
Validate allowlist directory paths.
Ensures all paths exist and are directories. Resolves paths to canonical form, which normalizes case on Windows and follows symlinks.
- Parameters:
paths (list[str | Path] | None) – List of directory paths (as strings or Path objects), or None for no restrictions
- Returns:
Validated list of resolved Path objects, or None
- Return type:
list[Path] | None
- Raises:
MCPSecurityError – If any path is invalid or doesn’t exist
Notes
Paths are resolved to canonical form using Path.resolve(strict=True), which normalizes case on Windows filesystems. This ensures that case variations cannot bypass security checks on case-insensitive systems.
- all2md.mcp.security.secure_open_for_write(validated_path: Path) BinaryIO
Open a file for writing with TOCTOU race condition protection.
This function opens a file using OS-level flags to prevent Time-Of-Check Time-Of-Use (TOCTOU) attacks where a file could be replaced with a symlink between validation and write operations.
- Parameters:
validated_path (Path) – Path that has already been validated by validate_write_path(). Must be an absolute, resolved path.
- Returns:
Binary file object opened for writing in a secure manner. Caller is responsible for closing this file.
- Return type:
BinaryIO
- Raises:
MCPSecurityError – If the file cannot be opened securely (e.g., it’s a symlink or access is denied)
Notes
Security measures: - On Unix-like systems: Uses O_NOFOLLOW flag to prevent following symlinks - On Windows: Uses os.open without follow_symlinks behavior - Creates new files with O_CREAT | O_EXCL when possible - For existing files, verifies they are not symlinks before opening
This function should be called immediately after validate_write_path() to minimize the TOCTOU window. The returned file object must be used for all write operations to ensure the validated path is actually being written to.