{"record":{"id":"b3c897901a0809ce","repo":"garrytan/gstack","slug":"unsafe-value-for-context-val","errorCode":null,"errorMessage":"Unsafe value for ${context}: ${val}","messagePattern":"Unsafe value for (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/host-config-export.ts","lineNumber":30,"sourceCode":" *\n * All output is shell-safe (single-quoted values, no eval needed).\n */\n\nimport { ALL_HOST_CONFIGS, getHostConfig, ALL_HOST_NAMES } from '../hosts/index';\nimport { validateAllConfigs } from './host-config';\nimport { RESOLVERS } from './resolvers';\nimport { execSync } from 'child_process';\n\nconst CLI_REGEX = /^[a-z][a-z0-9_-]*$/;\nconst PATH_REGEX = /^[a-zA-Z0-9_.\\/${}~-]+$/;\n\nfunction shellEscape(s: string): string {\n  return \"'\" + s.replace(/'/g, \"'\\\\''\") + \"'\";\n}\n\nfunction validateValue(val: string, context: string): void {\n  if (!PATH_REGEX.test(val) && !CLI_REGEX.test(val)) {\n    throw new Error(`Unsafe value for ${context}: ${val}`);\n  }\n}\n\nconst [command, ...args] = process.argv.slice(2);\n\nswitch (command) {\n  case 'list':\n    for (const name of ALL_HOST_NAMES) {\n      console.log(name);\n    }\n    break;\n\n  case 'get': {\n    const [hostName, field] = args;\n    if (!hostName || !field) {\n      console.error('Usage: host-config-export.ts get <host> <field>');\n      process.exit(1);\n    }","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/scripts/host-config-export.ts#L12-L48","documentation":"validateValue() in scripts/host-config-export.ts:30 enforces shell safety on values exported into host config. A value must match PATH_REGEX (`^[a-zA-Z0-9_./${}~-]+$`) or CLI_REGEX (`^[a-z][a-z0-9_-]*$`); otherwise it throws to prevent command injection through the export path.","triggerScenarios":"Passing a value containing spaces, semicolons, pipes, backticks, or `$(...)`. Untrusted env-derived values flowing into host-config-export. Paths with shell metacharacters.","commonSituations":"CI variable containing an unexpected character. User-supplied identifier with uppercase or punctuation. Path with spaces not sanitized upstream.","solutions":["Strip shell metacharacters from the value before calling host-config-export","Restrict the input to the CLI_REGEX character class for identifiers","For paths, ensure only characters in PATH_REGEX are present","Quote/escape externally rather than relying on the export to handle hostile input"],"exampleFix":"// before\nvalidateValue('foo; rm -rf /', 'name')\n// after\nvalidateValue('foo', 'name')","handlingStrategy":"validation","validationCode":"const CLI_RE = /^[a-z][a-z0-9_-]*$/;\nconst PATH_RE = /^[a-zA-Z0-9_.\\/${}~-]+$/;\nfunction isSafeValue(v: string): boolean {\n  return CLI_RE.test(v) || PATH_RE.test(v);\n}\nif (!isSafeValue(val)) {\n  throw new Error(`Unsafe value for ${context}: ${val}`);\n}","typeGuard":"const isSafeValue = (v: string): boolean =>\n  /^[a-z][a-z0-9_-]*$/.test(v) || /^[a-zA-Z0-9_.\\/${}~-]+$/.test(v);","tryCatchPattern":null,"preventionTips":["Never pass untrusted user input directly into host-config-export","Allowlist characters at the source (prefer the CLI_REGEX shape for identifiers)","Sanitize env-derived paths before exporting"],"tags":["security","validation","shell-injection","host-config"],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}