How the Extension Path Guard Protects Against Path Traversal in Modly
The Modly extension path guard eliminates path traversal vulnerabilities by strictly validating extension identifiers against a whitelist regex and verifying that resolved filesystem paths remain canonically within a designated root directory.
The Modly Electron backend isolates all extension-related filesystem operations behind a self-contained security module. Located at electron/main/extension-path-guard.ts, this path guard ensures that any path derived from an extension identifier can never escape the designated extensions directory, effectively neutralizing classic directory traversal attacks.
Strict Identifier Validation
The first line of defense operates on the raw extensionId before any filesystem interaction occurs. The assertSafeExtensionId function implements a whitelist approach that rejects any input capable of being interpreted as a path traversal vector.
- Type and content validation: The function rejects non-string values, empty strings, and the specific directory indicators
"."and"..". - Path separator blocking: Any identifier containing forward slashes (
/) or backslashes (\\) is immediately rejected, preventing attackers from injecting path components. - Absolute path prevention: The guard uses
isAbsolutechecks to refuse any identifier that resolves to an absolute path. - Regex enforcement: Only identifiers matching
/^[a-z0-9][a-z0-9._-]*$/are accepted. This pattern restricts valid IDs to lowercase alphanumerics, dots, underscores, and hyphens, while explicitly forbidding leading dots to reserve dot-prefixed names for internal system use (such as backup and staging directories).
Canonical Path Resolution
After validation, the resolvePathWithinRoot function guarantees that the final computed path cannot escape the extensions root directory, even when dealing with symbolic links or platform-specific path resolution quirks.
import { resolvePathWithinRoot } from './extension-path-guard.js';
// Resolves the absolute path and verifies containment
const safePath = resolvePathWithinRoot('/usr/local/modly/extensions', 'mesh-process');
// -> '/usr/local/modly/extensions/mesh-process'
The resolution algorithm performs three critical safety checks:
- Dual resolution: It resolves both the
rootDirand the candidate path to absolute form usingresolvePath. - Relative containment check: It computes the relative path from the root to the candidate and normalizes Windows back-slashes to forward slashes.
- Escape detection: The function throws a descriptive error if the relative result is empty (indicating the root itself),
"..", starts with"../", or is absolute—any of which indicate the candidate resolves outside the root boundary.
Combined Validation Workflow
For most operations, the resolveExtensionPathWithinRoot convenience wrapper chains both stages of protection. It first sanitizes the identifier with assertSafeExtensionId, then delegates to resolvePathWithinRoot for filesystem resolution.
import { resolveExtensionPathWithinRoot } from './extension-path-guard.js';
// Safe usage: returns validated absolute path
const path = resolveExtensionPathWithinRoot('/usr/local/modly/extensions', 'image_model.v2');
// Unsafe usage: throws before filesystem access
resolveExtensionPathWithinRoot('/usr/local/modly/extensions', '../evil');
// ❌ Error: Extension id "../evil" must not contain path separators
Integration Across the Codebase
The guard functions are exercised throughout the Modly backend wherever extension directories are created or accessed. Both buildExtensionBackupPath and buildExtensionStagingPath call resolvePathWithinRoot after sanitizing IDs to ensure backup and staging folders remain contained:
import { buildExtensionBackupPath } from './extension-path-guard.js';
// Creates a backup folder guaranteed to stay inside the root
const backupPath = buildExtensionBackupPath(
'/usr/local/modly/extensions',
'image_model.v2',
'1650000000'
);
// -> '/usr/local/modly/extensions/.modly-backup-image_model.v2-1650000000'
The IPC handlers in electron/main/ipc-handlers.ts utilize these guards when processing extension-related calls, ensuring that renderer-process requests cannot manipulate filesystem paths to access sensitive system files.
Summary
- Whitelist validation: The
assertSafeExtensionIdfunction enforces a strict alphanumeric-only regex that blocks path separators, absolute paths, and dot-prefixed identifiers. - Canonical containment:
resolvePathWithinRootcomputes relative paths from the root and explicitly rejects any result containing..segments or resolving outside the boundary. - Defense in depth:
resolveExtensionPathWithinRootchains both checks, ensuring identifiers are sanitized before path resolution occurs. - Immediate failure: Descriptive
Errorexceptions halt execution instantly when validation fails, preventing unsafe filesystem operations. - Comprehensive coverage: The guard protects all extension operations including backups, staging, and IPC-handled file access, with full test coverage in
electron/main/extension-path-guard.test.ts.
Frequently Asked Questions
What is a path traversal attack?
A path traversal (or directory traversal) attack occurs when an attacker manipulates input containing sequences like ../ to access files or directories stored outside the intended folder. In the context of Modly, this could theoretically allow malicious code to read system files or overwrite critical application data by supplying a malicious extension ID. The extension path guard prevents this by ensuring all resolved paths remain strictly within the configured extensions root.
How does the extension identifier regex prevent directory traversal?
The regex /^[a-z0-9][a-z0-9._-]*$/ functions as a whitelist that explicitly forbids characters used in path traversal. By rejecting forward slashes, backslashes, and leading dots, the pattern ensures the identifier can only represent a single directory name segment. Additionally, by requiring lowercase alphanumerics at the start, it blocks attempts to use .. or absolute path indicators (like drive letters on Windows or leading slashes on Unix) as valid extension IDs.
What happens when the guard detects a potentially unsafe path?
When any validation check fails—whether in assertSafeExtensionId or resolvePathWithinRoot—the function immediately throws a descriptive Error with a message explaining the violation (such as "Extension id must not contain path separators" or "Path must be within root"). This exception propagates up to the calling code in ipc-handlers.ts or other modules, causing the operation to abort before any filesystem access occurs, thereby failing safely.
How is the path guard tested for security?
The test suite in electron/main/extension-path-guard.test.ts validates the guard against both legitimate and malicious inputs, covering edge cases such as empty strings, "..", absolute paths, mixed-case characters, and various path separators. These tests verify that the regex correctly rejects malformed IDs and that the resolution logic properly detects escape attempts through relative path computation, ensuring the security model holds across platform-specific path behaviors.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →