How Modly's Extension Path Security Prevents Directory Traversal Attacks
Modly prevents directory traversal attacks by validating extension IDs against strict patterns and resolving all paths within a canonical root directory, ensuring resolved paths never escape the extension folder boundary.
The Modly extension framework isolates third-party code in a dedicated directory tree, implementing a defense-in-depth strategy against filesystem escapes. According to the lightningpixel/modly source code, every filesystem operation involving extensions passes through a security layer that validates identifiers and canonicalizes paths before any disk access occurs. This approach blocks malicious inputs like ../../etc/passwd at multiple validation stages.
Three-Stage Path Validation Strategy
Strict Extension-ID Validation with assertSafeExtensionId
The first line of defense resides in electron/main/extension-path-guard.ts, where the assertSafeExtensionId function enforces five strict constraints on any extension identifier:
- Non-empty and trimmed: The ID must contain visible characters after whitespace removal (lines 10‑13).
- No navigation tokens: Rejects single
.or double..directory references (lines 15‑17). - Relative-only: Blocks absolute paths such as
/etc/passwd(lines 19‑21). - No path separators: Explicitly forbids forward slashes, backslashes, or other directory separators (lines 23‑25).
- Pattern matching: Validates against the regex
^[a-z0-9][a-z0-9._-]*$to ensure alphanumeric-starting, shell-safe names (lines 27‑29).
By rejecting identifiers containing ../ sequences or absolute path markers at the entry point, Modly prevents attackers from injecting traversal payloads through the extension ID itself.
Canonical Resolution Inside Root Boundaries
The resolvePathWithinRoot function handles the second validation stage, ensuring that even manipulated relative paths cannot escape the designated extension directory. Operating within electron/main/extension-path-guard.ts, this function accepts a trusted rootDir and an unsafeLeaf parameter, then performs the following verification:
After constructing an absolute candidate path, it calculates the relative path from the root to the candidate (line 37). The critical security gate at line 41 rejects any resolution that:
- Results in an empty relative string (indicating the leaf resolved directly to the root).
- Equals
..or begins with../(indicating upward directory escape). - Resolves to an absolute path after normalization.
If any condition triggers, the function throws an exception immediately, guaranteeing the final path remains within the extension directory tree.
The Combined Safe-Resolution API
To ensure consistent application of both validation layers, Modly exposes resolveExtensionPathWithinRoot (lines 48‑50 in electron/main/extension-path-guard.ts). This high-level function composes assertSafeExtensionId and resolvePathWithinRoot into a single call, requiring all public filesystem operations to pass both security checks.
Internally, electron/main/extension-install-utils.ts leverages this API during extension installation, staging, and backup operations, ensuring that every file access respects the sandbox boundaries regardless of the operation type.
Practical Security Examples
The following TypeScript examples demonstrate how Modly's path security handles legitimate extensions versus traversal attempts:
import { resolveExtensionPathWithinRoot } from './electron/main/extension-path-guard.ts';
// Safe resolution: Valid extension ID resolved within the root directory
const safePath = resolveExtensionPathWithinRoot(
'/usr/local/modly/extensions',
'my_cool.extension-1'
);
// Returns: '/usr/local/modly/extensions/my_cool.extension-1'
Attempting to traverse upward using directory navigation in the extension ID triggers an immediate validation error:
// Blocked at assertSafeExtensionId (lines 15-17, 23-25)
try {
resolveExtensionPathWithinRoot(
'/usr/local/modly/extensions',
'../outside'
);
} catch (e) {
console.error(e.message); // Throws: Invalid extension ID
}
Even when bypassing the ID validation (internals only), the path resolution layer catches escapes:
import { resolvePathWithinRoot } from './electron/main/extension-path-guard.ts';
// Blocked at line 41 during relative path calculation
try {
resolvePathWithinRoot(
'/usr/local/modly/extensions',
'../../etc/passwd'
);
} catch (e) {
console.error(e.message); // Throws: Path escapes root directory
}
Summary
- Multi-layer validation: Modly combines strict ID pattern matching (
assertSafeExtensionId) with canonical path resolution (resolvePathWithinRoot) to create a defense-in-depth architecture. - Root confinement: The resolution logic explicitly checks for
..prefixes and absolute paths after normalization, ensuring all operations remain withinelectron/main/extension-path-guard.tsdefined boundaries. - Consistent API enforcement: The
resolveExtensionPathWithinRootfunction ensures that installation utilities inelectron/main/extension-install-utils.tsand other callers cannot accidentally skip security checks. - Comprehensive test coverage: Unit tests in
electron/main/extension-path-guard.test.tsverify that various traversal patterns are rejected before filesystem access occurs.
Frequently Asked Questions
What specific patterns does Modly block in extension identifiers?
Modly rejects any extension ID that is empty, equals . or .., contains path separators, starts with an absolute path marker, or fails to match the regex ^[a-z0-9][a-z0-9._-]*$. These constraints prevent attackers from embedding ../ sequences or absolute paths directly into the identifier string before it reaches the filesystem layer.
How does Modly prevent path traversal if an attacker bypasses the ID validation?
Even if an attacker somehow supplies a malicious relative path like ../../etc/passwd to the internal resolvePathWithinRoot function, the code calculates the relative path from the trusted root and rejects any result that equals .., begins with ../, or resolves to an absolute path (line 41 in electron/main/extension-path-guard.ts). This ensures the final resolved path never escapes the extension directory.
Which Modly components rely on these path security functions?
The electron/main/extension-install-utils.ts module uses these guards during extension installation, staging, and backup operations. Additionally, electron/main/extension-path-guard.test.ts contains the unit test suite that continuously validates the security boundaries against traversal attempts.
Can absolute paths ever be resolved by Modly's extension system?
No. The assertSafeExtensionId function explicitly blocks absolute paths at lines 19‑21, and resolvePathWithinRoot throws an exception if normalization results in an absolute path outside the root. Combined, these checks ensure that only relative, validated paths within the extension directory tree are accessible.
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 →