Skip to content

Security

MCP Filesystem Ultra has undergone a full security audit (v3.13.0) with 13 vulnerability fixes across 5 severity levels, plus ongoing hardening through Go 1.26.2 (12 CVEs resolved in the Go toolchain), and an AI-era threat hardening pass (v4.1.4) addressing 5 attack vectors specific to AI-driven filesystem access.

MetricValue
Vulnerabilities fixed13 (5 Critical + 3 High + 5 Medium)
CVEs resolved (Go toolchain)12 (via Go 1.26.2)
AI-era attack vectors mitigated5 (v4.1.4)
Go version1.26.2
unsafe package usageNone in production code
Security tests25+ (unit + CVE pattern tests)
Fuzzinggo test -fuzz on security package

As MCP servers are driven by AI models that process external content, novel attack vectors specific to AI-assisted filesystem access exist beyond traditional path traversal. The following five mitigations were implemented in v4.1.4.

Path Security Layer (core/path_security.go)

Section titled “Path Security Layer (core/path_security.go)”

A new universal validation function validatePathSecurity() runs on every path operation regardless of whether --allowed-paths is configured. It catches three attack classes:

On Windows NTFS, files can have hidden streams accessed via file.txt:streamname. These streams are invisible to list_directory and Windows Explorer, making them ideal for covert data channels.

# Attacker plants hidden payload
write_file("C:\project\README.md:exfil_channel", secret_content)
# list_directory shows nothing unusual
# Payload retrieved later:
read_file("C:\project\README.md:exfil_channel")

Fix: hasNTFSAlternateDataStream() rejects any path with : after the drive-letter colon. Windows-only (guarded by runtime.GOOS).

Unicode Directional Overrides and Zero-Width Characters

Section titled “Unicode Directional Overrides and Zero-Width Characters”

Two sub-attacks, both blocked by findDangerousUnicodeInPath():

RTLO Extension Spoofing (U+202E): The RIGHT-TO-LEFT OVERRIDE character reverses text direction visually. innocent\u202Etxt.exe renders as innocentexe.txt in many UIs but is actually an .exe.

Zero-Width Hook Evasion (U+200B): A zero-width space inserted in a filename bypasses hook glob patterns:

write_file(".en\u200Bv") # Looks like ".env" but "*.env" hook pattern doesn't match

18 dangerous code points blocked including RTLO (U+202E), zero-width space (U+200B), all Unicode bidi format characters, line separators, and soft hyphen. The entire Unicode Cf (Format) category is also blocked.

Windows treats CON, NUL, COM1-9, LPT1-9 as device references even in paths. os.ReadFile("CON") hangs waiting for console stdin (DoS). write_file("NUL", data) silently discards data while reporting success.

Fix: isWindowsReservedName() checks base filename case-insensitively with extension stripped. Applied cross-platform for portability.

Previously, any path starting with \\wsl.localhost\ or \\wsl$\ unconditionally bypassed --allowed-paths access control. This allowed reading any file in any WSL distribution regardless of restrictions:

# Before (VULNERABLE): with --allowed-paths C:\MyProject
read_file("\\wsl.localhost\Ubuntu\etc\shadow") → was ALLOWED (bypass)

Fix: WSL paths now undergo the same containment check as all other paths. In open-access mode (no --allowed-paths), WSL paths remain accessible.

Security checks now run unconditionally — regardless of whether --allowed-paths is configured. The function:

  1. Runs validatePathSecurity() first (ADS, Unicode, reserved names)
  2. Returns true if open-access mode (no AllowedPaths configured)
  3. Otherwise performs symlink-resolved containment check

All 20 call sites across engine.go, file_operations.go, edit_operations.go, streaming_operations.go, and plan_mode.go now always call IsPathAllowed() unconditionally.

Hook commands previously used cmd /C unconditionally, silently failing on Linux/macOS and potentially bypassing blocking hooks (failOnError:true). Fixed with OS detection:

if runtime.GOOS == "windows" {
cmd = exec.CommandContext(execCtx, "cmd", "/C", hook.Command)
} else {
cmd = exec.CommandContext(execCtx, "sh", "-c", hook.Command)
}

Indirect Prompt Injection (Defense-in-Depth)

Section titled “Indirect Prompt Injection (Defense-in-Depth)”

This attack class (embedding instructions in files the AI reads) cannot be fully mitigated at the server layer. Recommended defenses:

  • Configure --allowed-paths to limit readable/writable scope to the working project
  • Use pre-read hooks with failOnError:true to block credential file reads (*.env, *.key, id_rsa)
  • Review AI operations before approving writes to sensitive paths

All file operations pass through isPathAllowed(), which:

  1. Resolves symlinks via filepath.EvalSymlinks() before checking containment
  2. Verifies the resolved path is within one of the configured allowed directories
  3. Blocks traversal attempts (../, ..\, URL-encoded variants)
// Every tool handler calls this before any file I/O
if len(e.config.AllowedPaths) > 0 {
if !e.isPathAllowed(path) {
return nil, &PathError{Op: "operation", Path: path, Err: fmt.Errorf("access denied")}
}
}

Allowed paths are resolved once at engine startup via filepath.EvalSymlinks() for consistent comparison.

  • isPathAllowed() resolves symlinks before containment check, preventing symlink-based directory escape
  • copyDirectory() skips symlinks entirely — does not follow them during recursive copy
  • No symlink creation operations exposed

All temporary files and backup IDs use crypto/rand (not math/rand or predictable timestamps):

  • Backup IDs: timestamp-cryptoRandom format
  • Temp files during edits: crypto/rand hex suffix
  • Pipeline temp files: crypto/rand names

This prevents predictable file name attacks (CWE-330).

Backup IDs are sanitized before use in file paths — only alphanumeric characters, -, and _ are allowed. This prevents path traversal via crafted backup IDs.

Time-of-check-to-time-of-use (TOCTOU) race conditions are mitigated by:

  • Performing access control checks immediately before file operations
  • Using atomic file writes (write to temp, then rename)
  • Channel-based semaphore (operationSem) limiting concurrent operations
  • Temp files: 0600 (owner read/write only)
  • Backup metadata: 0600
  • No world-readable temp files

Risk assessment normalizes line endings (\r\n\n) before calculating change percentages. This prevents CRLF/LF mismatches from inflating risk scores and blocking legitimate edits (fixed in v4.0.2, Bug #23).

No unsafe package usage in production code. All memory management relies on Go’s garbage collector.


Go 1.26.0 resolves 8 CVEs in the standard library:

CVEPackageDescription
CVE-2024-45336net/httpHTTP redirect credential leak
CVE-2024-45341crypto/x509Certificate validation bypass
CVE-2025-22866crypto/internal/fips140/nistecP-256 scalar multiplication timing
CVE-2024-45340os/execCommand execution on Windows
CVE-2024-45339encoding/xmlXML parsing crash
CVE-2024-45337golang.org/x/crypto/sshSSH server auth bypass
CVE-2024-45338golang.org/x/net/htmlHTML parser DoS
CVE-2025-27144github.com/go-jose/go-joseJWE decryption DoS

  1. Symlink directory escapeisPathAllowed() now resolves symlinks before containment check
  2. Predictable temp file names — Switched from timestamp-based to crypto/rand
  3. Predictable backup IDs — Switched to crypto/rand suffix
  4. Unrestricted recursive copy of symlinkscopyDirectory() now skips symlinks
  5. Backup ID path traversal — Sanitization: only [a-zA-Z0-9_-] allowed
  1. TOCTOU in file operations — Atomic write pattern (temp + rename)
  2. Unbounded directory listing--max-list-items limit (default: 500)
  3. Unbounded search results--max-search-results limit (default: 1000)
  1. World-readable temp files — Changed to 0600 permissions
  2. Backup metadata permissions — Changed to 0600
  3. No operation logging — Added audit logging system (--log-dir)
  4. Missing input validation on line ranges — Integer boundary checks added
  5. Error messages leaking internal paths — Sanitized error output

When --allowed-paths is configured (or positional args are provided), all operations are restricted to those directories:

{
"args": [
"--allowed-paths", "C:\\project\\src,C:\\project\\tests",
"C:\\project\\src",
"C:\\project\\tests"
]
}

When empty (default), there are no restrictions.

Edit operations are assessed for risk before execution:

LevelConditionBehavior
LOW< 20% changeProceeds silently
MEDIUM20-74% changeAuto-proceeds with backup + risk notice
HIGH75-89% changeAuto-proceeds with backup + warning
CRITICAL>= 90% changeBlocked (requires force: true)

Only CRITICAL blocks the operation. MEDIUM and HIGH auto-proceed with an automatic backup.

The EditSafetyValidator provides additional protection:

  • Context validation (surrounding lines must match)
  • Stale edit prevention (file changed since last read)

The Request Normalizer acts as a security layer by:

  • Validating and coercing parameter types (prevents type confusion)
  • Rejecting malformed JSON payloads
  • Sanitizing pipeline step structures

tests/security/
├── security_tests.go # 10+ unit tests: dependency verification, secret detection, input validation
├── cves_test.go # 15+ CVE pattern tests: path traversal, command injection, race conditions
└── README.md
Terminal window
# All security tests
go test ./tests/security/...
# With race detector
go test -race ./tests/security/...
# Fuzzing
go test -fuzz=Fuzz ./tests/security
# Specific test
go test ./tests/security -run TestPathTraversalVulnerability -v
PatternCWEStatus
Path traversal (../, ..\, URL-encoded)CWE-22Tested
Command injection (;, |, `, $())CWE-78Tested
Integer overflow in line rangesCWE-190Tested
Race conditions (concurrent access)CWE-362Tested
No unsafe importsCWE-242Verified
No eval/exec patternsCWE-94Verified
Dependency vulnerabilitiesScanned
scripts/security/
├── run_all_security_tests.bat # 9-phase orchestration script
├── vulnerability_scan.bat # Dependency scanner
└── run_security_tests.bat # Unit test runner
Terminal window
# Quick dependency check
scripts\security\vulnerability_scan.bat
# Full assessment (9 phases)
scripts\security\run_all_security_tests.bat --coverage --report

For deeper analysis (auto-detected by scripts):

Terminal window
go install github.com/securego/gosec/v2/cmd/gosec@latest # Static analysis
go install github.com/sonatype-nexus-oss/nancy@latest # CVE scanning
go install github.com/google/go-licenses@latest # License compliance

  • Use GitHub private security advisory
  • Do not create public issues for security vulnerabilities
  • Include: description, reproduction steps, impact assessment, suggested fix

Last updated: March 2026 Version: 4.1.0