# How the Extension Path Guard Protects Against Path Traversal in Modly

> Learn how Modly's extension path guard prevents path traversal vulnerabilities. It validates extensions and ensures paths stay within the root directory.

- Repository: [lightningpixel/modly](https://github.com/lightningpixel/modly)
- Tags: security
- Published: 2026-08-20

---

**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`](https://github.com/lightningpixel/modly/blob/main/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 `isAbsolute` checks 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.

```typescript
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:

1. **Dual resolution**: It resolves both the `rootDir` and the candidate path to absolute form using `resolvePath`.
2. **Relative containment check**: It computes the relative path from the root to the candidate and normalizes Windows back-slashes to forward slashes.
3. **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.

```typescript
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:

```typescript
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`](https://github.com/lightningpixel/modly/blob/main/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 `assertSafeExtensionId` function enforces a strict alphanumeric-only regex that blocks path separators, absolute paths, and dot-prefixed identifiers.
- **Canonical containment**: `resolvePathWithinRoot` computes relative paths from the root and explicitly rejects any result containing `..` segments or resolving outside the boundary.
- **Defense in depth**: `resolveExtensionPathWithinRoot` chains both checks, ensuring identifiers are sanitized before path resolution occurs.
- **Immediate failure**: Descriptive `Error` exceptions 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`](https://github.com/lightningpixel/modly/blob/main/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`](https://github.com/lightningpixel/modly/blob/main/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`](https://github.com/lightningpixel/modly/blob/main/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.