Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,17 @@ const cmd = `powershell.exe -EncodedCommand ${encoded}`;

### Path Traversal Prevention

- All paths are validated to be within the workspace
- `realpath()` is used to resolve symbolic links
- Parent directory references (`..`) are blocked
- The saved image, and every folder created for it, is checked to be inside the workspace before it is written
- `realpath()` resolves symbolic links in the part of the path that already exists, so a link cannot lead the image outside the workspace
- A save directory that leads outside the workspace, through `..` or otherwise, is refused when the image is saved. One whose `..` stays inside the workspace resolves to the folder it names

```typescript
// Path validation
const realTarget = await fs.realpath(targetPath);
const relative = path.relative(workspaceRoot, realTarget);
if (relative.startsWith('..')) {
throw new PathValidationError('Path is outside workspace');
// Path validation (src/security/path-validator.ts, simplified)
const realRoot = await fs.realpath(workspaceRoot);
const realTarget = await resolveExistingPrefix(targetPath, workspaceRoot);
const relative = path.relative(realRoot, realTarget);
if (relative.startsWith('..') || path.isAbsolute(relative)) {
throw new PathValidationError('Path is outside the workspace');
}
```

Expand All @@ -62,10 +63,10 @@ if (relative.startsWith('..')) {

### Input Validation

All user-configurable values are validated:
- Save directory cannot be absolute or contain `..`
- File name patterns cannot contain shell metacharacters
- Numeric values are clamped to valid ranges
Settings are checked each time they are read:
- Numeric values are clamped to valid ranges, and a value of the wrong type falls back to the default
- A save directory that is absolute or contains `..`, and a file name pattern with shell metacharacters, are reported as configuration warnings in the ClipShot log. They are not what keeps writes inside the workspace; the check above is
- Each generated file name has control characters, and the characters a Windows file name cannot hold (`< > : " / \ | ? *`), removed. On Windows, a reserved name such as `CON` is prefixed

### Workspace Trust

Expand Down
5 changes: 3 additions & 2 deletions src/config/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -425,9 +425,10 @@ export function sanitizeConfiguration(config: DeepPartial<ExtensionConfig>): Dee
.replace(/^\/+|\/+$/g, '');
}

// Sanitize fileName.pattern - remove dangerous characters
// Trim fileName.pattern. Characters a file name cannot hold are removed from
// each generated name by sanitizeFileName; shell metacharacters in the pattern
// are only reported, by validateFileNamePattern.
if (sanitized.fileName?.pattern !== undefined && sanitized.fileName.pattern !== '') {
// Keep only safe characters (alphanumeric, underscore, hyphen, dot, spaces, and ${} tokens)
sanitized.fileName = {
...sanitized.fileName,
pattern: sanitized.fileName.pattern.trim(),
Expand Down
Loading