chore: sync core lib and CLAUDE.md from agent-core#14
Conversation
|
Superseded by fresh sync after agent-core upstreamed missing files (workflow-state.js full version + lib/repo-intel/queries.js). Close older PR to avoid conflicts. |
There was a problem hiding this comment.
Code Review
This pull request implements security hardening for binary downloading and extraction, adding SHA-256 verification, path traversal protections, and isolated scratch directories. Feedback focuses on improving the robustness of the tar process by explicitly defining stdin for portability, using stdin.end(buf) for stream management, and correctly handling Buffer chunks to avoid character encoding issues.
| const tar = cp.spawn('tar', ['xz', '-C', tarDest], { | ||
| stdio: ['pipe', 'pipe', 'pipe'] | ||
| }); | ||
| const tar = cp.spawn('tar', ['-tz'], { stdio: ['pipe', 'pipe', 'pipe'] }); |
There was a problem hiding this comment.
Explicitly specifying -f - is more portable and ensures tar reads from stdin across different implementations (e.g., some versions of GNU tar might otherwise try to read from a default device).
| const tar = cp.spawn('tar', ['-tz'], { stdio: ['pipe', 'pipe', 'pipe'] }); | |
| const tar = cp.spawn('tar', ['-tzf', '-'], { stdio: ['pipe', 'pipe', 'pipe'] }); |
| tar.stdout.on('data', function(d) { stdout += d; }); | ||
| tar.stderr.on('data', function(d) { stderr += d; }); |
There was a problem hiding this comment.
Appending a Buffer to a string relies on implicit conversion which can be problematic if a multi-byte character is split across chunks. It is safer to collect chunks and join them at the end.
const stdoutChunks = [];
const stderrChunks = [];
tar.stdout.on('data', function(d) { stdoutChunks.push(d); });
tar.stderr.on('data', function(d) { stderrChunks.push(d); });| reject(new Error('tar -tz listing failed (code ' + code + '): ' + stderr)); | ||
| return; | ||
| } | ||
| const entries = stdout.split(/\r?\n/).filter(function(l) { return l.length > 0; }); |
| tar.stdin.write(buf); | ||
| tar.stdin.end(); |
|
|
||
| try { | ||
| await new Promise(function(resolve, reject) { | ||
| const tar = cp.spawn('tar', ['xz', '-C', scratch], { stdio: ['pipe', 'pipe', 'pipe'] }); |
There was a problem hiding this comment.
Similar to the listing command, explicitly specifying -f - is recommended for portability when piping the archive buffer to stdin.
| const tar = cp.spawn('tar', ['xz', '-C', scratch], { stdio: ['pipe', 'pipe', 'pipe'] }); | |
| const tar = cp.spawn('tar', ['-xzf', '-', '-C', scratch], { stdio: ['pipe', 'pipe', 'pipe'] }); |
| tar.stdin.write(buf); | ||
| tar.stdin.end(); |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 647deaf. Configure here.
| const scratch = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-analyzer-zip-')); | ||
| const tmpZip = path.join(scratch, '__archive.zip'); | ||
| const scriptDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-analyzer-ps-')); | ||
| const scriptPath = path.join(scriptDir, 'extract.ps1'); |
There was a problem hiding this comment.
Scratch directory leaked if scriptDir creation fails
Low Severity
In extractZipToScratch, the scratch temp directory is created at line 503, then a second fs.mkdtempSync for scriptDir runs at line 505 — before the try block at line 508. If the second mkdtempSync throws (e.g. disk full), scratch is never cleaned up: the function's own catch block is never entered, and the caller's finally guard (if (scratch) rmrf(scratch)) also skips cleanup because the caller's scratch variable remains undefined. This leaks a temp directory. Contrast with extractTarGzToScratch, which correctly places mkdtempSync immediately before a try block.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 647deaf. Configure here.


Automated sync of lib/ and CLAUDE.md from agent-core.
Note
Medium Risk
Touches the runtime binary download/install path, adding checksum verification and new extraction logic (including a custom PowerShell zip extractor), which could cause install failures or platform-specific regressions if release assets or archive layouts differ.
Overview
Hardens the
agent-analyzerruntime installer against supply-chain and archive-extraction attacks. Downloads now require a matching.sha256sidecar (with an explicit local-dev-onlyskipChecksumescape hatch) and abort on mismatch before any extraction.Extraction is reworked to use an isolated scratch directory with pre-validation of archive entry paths (rejecting absolute/UNC/drive-letter paths and
..traversal), post-extraction checks for symlinks/escape, and only the expected binary is copied into~/.agent-sh/binwhile all other extracted content is discarded. On Windows, zip handling switches fromExpand-Archivecommand strings to a-FilePowerShell helper script that validates entries and avoids quoting/space issues.Adds a comprehensive
node:testsuite for checksum parsing/verification, path validation, scratch cleanup, and basic tar/zip extraction behavior, and exports several helper functions for testing/advanced use.Reviewed by Cursor Bugbot for commit 647deaf. Configure here.