Description
The parseYamlWithFrontmatter() function in app/src/utils/yaml.tsx parses untrusted YAML without resource limits or security configurations, making it vulnerable to DoS attacks.
Context
- File:
app/src/utils/yaml.tsx:14
- Component: YAML parser for project metadata
- Severity: HIGH
Current Behavior
```typescript
export function parseYamlWithFrontmatter<F, C>(
yaml: string,
): {
frontmatter: F;
content: C;
} {
yaml = yaml.trim();
let contentList = yaml.split("---");
contentList = contentList.filter(Boolean);
const frontmatter = contentList[0];
const content = contentList[1];
return { frontmatter: YAML.parse(frontmatter), content: YAML.parse(content) };
}
```
This is vulnerable to:
- DoS via YAML anchors/aliases - Infinite loops, exponential memory usage
- DoS via deep nesting - Stack overflow
- DoS via large payloads - Memory exhaustion
Exploit Example
```yaml
anchor: &a
... repeated 1000x - exponential blowup
```
Expected Behavior
YAML parsing should:
- Have strict size limits (max document size: 1MB)
- Have recursion depth limits (max depth: 20)
- Have anchor/alias limits (max references: 100)
- Parse with sandboxing if possible
Steps to Reproduce
// Create malicious YAML with exponential anchors
const maliciousYaml = `
---
&ref [*ref *ref *ref *ref *ref *ref *ref *ref *ref *ref *ref *ref *ref *ref]
---
`;
parseYamlWithFrontmatter(maliciousYaml); // Hangs or crashes
Suggested Fix
```typescript
import YAML from "yaml";
// Configure limits
const MAX_YAML_SIZE = 1024 * 1024; // 1MB
const MAX_DEPTH = 20;
const MAX_ANCHORS = 100;
export function parseYamlWithFrontmatter<F, C>(
yaml: string,
): {
frontmatter: F;
content: C;
} {
// 1. Size validation
if (yaml.length > MAX_YAML_SIZE) {
throw new Error(`YAML document too large: ${yaml.length} bytes (max: ${MAX_YAML_SIZE})`);
}
yaml = yaml.trim();
let contentList = yaml.split("---");
contentList = contentList.filter(Boolean);
const frontmatter = contentList[0];
const content = contentList[1];
// 2. Parse with strict options
const options = {
strict: true,
maxAliasCount: MAX_ANCHORS,
// Use the yaml library's security features
};
return {
frontmatter: YAML.parse(frontmatter, options) as F,
content: YAML.parse(content, options) as C
};
}
```
Alternative: Use a more secure YAML parser like js-yaml with schema: FAILSAFE_SCHEMA.
Impact
- Who is affected: All users opening project files with YAML frontmatter
- Severity: HIGH - Could freeze the application, consume all memory
- Attack vector: Malicious .prg files, pasted content, imported projects
Environment
- Version: v3.02+ (current)
- OS: All platforms
Additional Context
This attack is especially effective because:
- Project files are user-controllable
- No rate limiting on file operations
- Could be used for UI-based DoS attacks
Consider adding:
- Parse timeouts
- Memory usage monitoring
- Warning dialogs for large files
Positively — happy to submit a PR if this is welcome.
Description
The
parseYamlWithFrontmatter()function inapp/src/utils/yaml.tsxparses untrusted YAML without resource limits or security configurations, making it vulnerable to DoS attacks.Context
app/src/utils/yaml.tsx:14Current Behavior
```typescript
export function parseYamlWithFrontmatter<F, C>(
yaml: string,
): {
frontmatter: F;
content: C;
} {
yaml = yaml.trim();
let contentList = yaml.split("---");
contentList = contentList.filter(Boolean);
const frontmatter = contentList[0];
const content = contentList[1];
return { frontmatter: YAML.parse(frontmatter), content: YAML.parse(content) };
}
```
This is vulnerable to:
Exploit Example
```yaml
anchor: &a
... repeated 1000x - exponential blowup
```
Expected Behavior
YAML parsing should:
Steps to Reproduce
Suggested Fix
```typescript
import YAML from "yaml";
// Configure limits
const MAX_YAML_SIZE = 1024 * 1024; // 1MB
const MAX_DEPTH = 20;
const MAX_ANCHORS = 100;
export function parseYamlWithFrontmatter<F, C>(
yaml: string,
): {
frontmatter: F;
content: C;
} {
// 1. Size validation
if (yaml.length > MAX_YAML_SIZE) {
throw new Error(`YAML document too large: ${yaml.length} bytes (max: ${MAX_YAML_SIZE})`);
}
yaml = yaml.trim();
let contentList = yaml.split("---");
contentList = contentList.filter(Boolean);
const frontmatter = contentList[0];
const content = contentList[1];
// 2. Parse with strict options
const options = {
strict: true,
maxAliasCount: MAX_ANCHORS,
// Use the yaml library's security features
};
return {
frontmatter: YAML.parse(frontmatter, options) as F,
content: YAML.parse(content, options) as C
};
}
```
Alternative: Use a more secure YAML parser like
js-yamlwithschema: FAILSAFE_SCHEMA.Impact
Environment
Additional Context
This attack is especially effective because:
Consider adding:
Positively — happy to submit a PR if this is welcome.