T09 · Insecure Skill Coding Practices
- Location
src/commands/import.js:19- Finding
Path Traversal Through Unvalidated Upstream Identifiers
- Content
View full analysis
[--name ]'); console.error('Example: ustack import https://github.com/garrytan/gstack --name gstack'); process.exitCode = 1; return; } if (!upstreamId) { upstreamId = repoUrl.split('/').pop().replace(/\.git$/, ''); } const upstreamDir = getUpstreamDir(cwd, upstreamId); const repoDir = path.join(upstreamDir, 'repo'); ``` ```js // src/lib/fs.js:30-44 export function getUstackDir(cwd) { return path.join(cwd, '.ustack'); } export function getUpstreamDir(cwd, upstreamId) { return path.join(getUstackDir(cwd), 'upstreams', upstreamId); } export function getRunDir(cwd, upstreamId, timestamp) { return path.join(getUstackDir(cwd), 'runs', upstreamId, timestamp); } export function listRunDirs(cwd, upstreamId) { const runsBase = path.join(getUstackDir(cwd), 'runs', upstreamId); if (!fileExists(runsBase)) return []; return fs.readdirSync(runsBase).sort().reverse(); } ``` ```js // src/commands/publish.js:65-67 const siteDir = path.join(cwd, '.ustack', 'site', 'updates', upstreamId); const slugDate = analysis.analyzedAt.split('T')[0]; const sitePagePath = path.join(siteDir, `${slugDate}-${analysis.toShaShort}.md`); writeText(sitePagePath, page); ``` ### Technical Analysis The value supplied through `--name` or as an upstream command identifier is used directly as a filesystem path component. No validation rejects absolute paths, path separators, `.` or `.. ...[truncated 1841 chars]- Remediation
View remediation
