T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/employee-manager.js:53
- Finding
- Path Traversal Through Attacker-Controlled Employee Role<![CDATA[ ## Vulnerability Details **File Location**: `scripts/employee-manager.js`, lines 53-78 **Vulnerability Type**: Path traversal leading to unauthorized filesystem writes **Risk Level**: High ### Vulnerable Code ```javascript hire(config) { const { name, role, skills = [], model = 'gpt-4', template } = config; if (!name || !role) { throw new Error('员工名称和角色不能为空'); } const id = `${role.toLowerCase().replace(/\s+/g, '-')}-${Date.now()}`; const employee = { id, name, role, skills, model, status: 'idle', createdAt: new Date().toISOString(), currentTask: null, completedTasks: 0, memoryPath: `./memory/${id}` }; // 创建记忆目录 const memDir = path.join(MEMORY_DIR, id); if (!fs.existsSync(memDir)) { fs.mkdirSync(memDir, { recursive: true }); // 创建初始记忆文件 fs.writeFileSync( path.join(memDir, 'memory.md'), `# ${name} - 记忆存储\n\n创建时间: ${new Date().toISOString()}\n\n## 工作记录\n\n`, 'utf8' ); } ``` ### Technical Analysis The `role` field is incorporated directly into the employee identifier. The only transformation replaces whitespace with hyphens; path separators and traversal components such as `..` are not removed or rejected. The resulting identifier is passed to `path.join(MEMORY_DIR, id)` and then used by `fs.mkdirSync()` and `fs.writeFileSync()`. Because `path.join()` normalizes traversal components, a role containing sequences such as `../../` can cause the resolved directory to escape the intended `memory` directory. The timestamp suffix does not prevent traversal because it is appended after the attacker-controlled traversal components. This allows directory creation and creation of a fixed-name `memory.md` file at an unintended filesystem location. ### Attack Path 1. An attacker or untrusted caller invokes the `hire()` method or the corresponding CLI command. 2. The attacker supplies a role containing directory traversal components, such as `../../outside`. ...[truncated 894 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Generate employee identifiers independently of user-controlled fields, preferably with `crypto.randomUUID()`. - If the role must appear in an identifier, apply a strict allowlist such as ASCII letters, digits, underscores, and hyphens. - Reject values containing path separators, `.` or `..` path components, null bytes, and platform-specific separator characters. - Resolve and verify the final path before every filesystem operation: ```javascript const resolvedMemoryRoot = path.resolve(MEMORY_DIR); const resolvedEmployeeDir = path.resolve(MEMORY_DIR, safeId); if ( resolvedEmployeeDir === resolvedMemoryRoot || !resolvedEmployeeDir.startsWith(resolvedMemoryRoot + path.sep) ) { throw new Error('Invalid employee memory path'); } ``` - Run the process with minimum filesystem permissions so that a path-validation failure cannot modify sensitive operating-system locations. - Add automated tests covering traversal payloads with forward slashes, backslashes, repeated traversal components, absolute paths, and encoded or unusual separator characters. ]]>
