{"record":{"id":"c6ec3be2a6a6972a","repo":"davila7/claude-code-templates","slug":"invalid-agent-name","errorCode":null,"errorMessage":"Invalid agent name","messagePattern":"Invalid agent name","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"cli-tool/src/sandbox-server.js","lineNumber":234,"sourceCode":"        tasks: tasks.sort((a, b) => new Date(b.startTime) - new Date(a.startTime))\n    });\n});\n\n// API endpoint to install agent\napp.post('/api/install-agent', async (req, res) => {\n    const { agentName } = req.body;\n\n    if (!agentName) {\n        return res.status(400).json({\n            success: false,\n            error: 'Agent name is required'\n        });\n    }\n\n    // SECURITY: agent names are `category/name` slugs. Reject anything else so a\n    // value like \"x; rm -rf ~\" can never reach the child process.\n    if (!/^[A-Za-z0-9._/-]+$/.test(agentName)) {\n        return res.status(400).json({\n            success: false,\n            error: 'Invalid agent name'\n        });\n    }\n\n    try {\n        console.log(chalk.blue('🔧 Installing agent:'), chalk.cyan(agentName));\n\n        // SECURITY: shell:false (default) keeps agentName as a single argv entry —\n        // no shell parses it, so metacharacters cannot inject commands.\n        const child = spawn(NPX_CMD, ['claude-code-templates@latest', '--agent', agentName, '--yes'], {\n            cwd: process.cwd(),\n            stdio: ['pipe', 'pipe', 'pipe']\n        });\n        \n        let output = [];\n        let error = [];\n        ","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/davila7/claude-code-templates/blob/a0851ed10c7c60463dac8cfaaca124cf32d5804d/cli-tool/src/sandbox-server.js#L216-L252","documentation":"POST /api/install-agent validates agentName against the whitelist regex ^[A-Za-z0-9._/-]+$ because the value is passed to a child process. Any character outside letters, digits, dot, underscore, hyphen and slash triggers 400 'Invalid agent name'. This is an intentional command-injection guard.","triggerScenarios":"Sending agentName containing spaces, quotes, semicolons, ampersands, or shell metacharacters — e.g. \"frontend developer\", \"x; rm -rf ~\", or a value with a trailing newline. Unicode agent names also fail.","commonSituations":"User pastes a display name with spaces instead of the slug; client doesn't trim the input; attempted (or accidental) shell injection via the API; agent slugs containing non-ASCII characters.","solutions":["Send the exact kebab-case slug in category/name form, e.g. development-team/frontend-developer","Trim whitespace client-side and reject values with spaces or special characters before submitting","Verify the slug exists in GET /components.json before calling install"],"exampleFix":"// before\n{ \"agentName\": \"Frontend Developer\" }\n// after\n{ \"agentName\": \"development-team/frontend-developer\" }","handlingStrategy":"type-guard","validationCode":"const AGENT_SLUG_RE = /^[A-Za-z0-9._/-]+$/;\nif (!AGENT_SLUG_RE.test(agentName)) throw new Error('invalid agent slug');","typeGuard":"const isValidAgentSlug = (name) => typeof name === 'string' && /^[A-Za-z0-9._/-]+$/.test(name.trim()) && name.trim().length > 0;","tryCatchPattern":null,"preventionTips":["Always send slugs (category/name, kebab-case), never display names","Trim input client-side","Cross-check the slug against GET /components.json before installing"],"tags":["http-400","validation","command-injection","sanitize-input","security"],"backgroundTag":"input-sanitization-rejected","analyzedSha":"a0851ed10c7c60463dac8cfaaca124cf32d5804d","analyzedAt":"2026-08-28T14:11:56.058Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}