T09 · Insecure Skill Coding Practices
Error
- Location
- generator.ts:301
- Finding
- Arbitrary File Write Through Unsanitized Generated Paths<![CDATA[ ## Vulnerability Details **File Location**: `generator.ts:301-309` and `generator.ts:541-546` **Vulnerability Type**: Path traversal leading to arbitrary file creation or overwrite **Risk Level**: High ### Vulnerable Code ```typescript for (const page of requirements.pages) { const routePath = page.route.startsWith('/') ? page.route.slice(1) : page.route; const pageDir = routePath === '' ? pagesDir : path.join(pagesDir, ...routePath.split('/')); if (routePath !== '') { await fs.promises.mkdir(pageDir, { recursive: true }); } const pageContent = this.generatePageComponent(page, requirements, uiAnalysis); await fs.promises.writeFile(path.join(pageDir, 'page.tsx'), pageContent); } ``` A second affected write uses the component name directly: ```typescript if (requirements.components && requirements.components.length > 0) { for (const componentName of requirements.components) { const componentContent = this.generateComponent(componentName, uiAnalysis); await fs.promises.writeFile( path.join(componentsDir, `${componentName}.tsx`), componentContent ); } } ``` ### Technical Analysis Page routes and component names extracted from the user-supplied requirements document are used to construct filesystem paths without validation. Node.js `path.join()` normalizes traversal segments such as `..`; it does not guarantee that the resulting path remains under the intended output directory. The code does not reject absolute paths, traversal components, path separators, symbolic-link escapes, or platform-specific path syntax. Consequently, an attacker who controls the requirements document can cause the generator to write outside `src/app` or `src/components`. This exceeds the minimum filesystem privileges needed to generate a project because the generator should only create files beneath the selected project root. ### Attack Path 1. An attacker supplies a requirements document containing a page route such as `. ...[truncated 1048 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Permit only expected route segments and component identifiers, using a restrictive allowlist such as letters, digits, underscores, and hyphens. - Explicitly reject empty segments, `.`, `..`, absolute paths, drive-qualified paths, null bytes, and both Unix and Windows path separators where they are not required. - Resolve every destination against a canonical project root and verify containment before writing: ```typescript const root = path.resolve(projectPath); const destination = path.resolve(root, relativeDestination); if (destination !== root && !destination.startsWith(root + path.sep)) { throw new Error('Destination escapes the generated project root'); } ``` - Perform the same containment validation immediately before every `mkdir` and `writeFile`. - Consider refusing to follow symbolic links or generating inside a newly created directory whose ownership and contents are controlled by the Skill. - Use a separate validated route-to-directory conversion function rather than treating user input as a filesystem path. ]]>
