mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-05 05:05:08 +02:00
fix: address review informational issues + add regression tests
- Add cookie-import to CHAIN_WRITE set for chain command routing - Add path validation to snapshot -a -o output path - Fix package.json version to match 0.3.1 - Use crypto.randomUUID() for temp DB paths (unpredictable filenames) - Add regression tests for chain cookie-import and snapshot path validation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -241,7 +241,7 @@ function openDb(dbPath: string, browserName: string): Database {
|
||||
}
|
||||
|
||||
function openDbFromCopy(dbPath: string, browserName: string): Database {
|
||||
const tmpPath = `/tmp/browse-cookies-${browserName.toLowerCase()}.db`;
|
||||
const tmpPath = `/tmp/browse-cookies-${browserName.toLowerCase()}-${crypto.randomUUID()}.db`;
|
||||
try {
|
||||
fs.copyFileSync(dbPath, tmpPath);
|
||||
// Also copy WAL and SHM if they exist (for consistent reads)
|
||||
|
||||
@@ -30,7 +30,7 @@ const CHAIN_READ = new Set([
|
||||
const CHAIN_WRITE = new Set([
|
||||
'goto', 'back', 'forward', 'reload',
|
||||
'click', 'fill', 'select', 'hover', 'type', 'press', 'scroll', 'wait',
|
||||
'viewport', 'cookie', 'header', 'useragent',
|
||||
'viewport', 'cookie', 'cookie-import', 'header', 'useragent',
|
||||
'upload', 'dialog-accept', 'dialog-dismiss',
|
||||
'cookie-import-browser',
|
||||
]);
|
||||
|
||||
@@ -309,6 +309,12 @@ export async function handleSnapshot(
|
||||
// ─── Annotated screenshot (-a) ────────────────────────────
|
||||
if (opts.annotate) {
|
||||
const screenshotPath = opts.outputPath || '/tmp/browse-annotated.png';
|
||||
// Validate output path (consistent with screenshot/pdf/responsive)
|
||||
const resolvedPath = require('path').resolve(screenshotPath);
|
||||
const safeDirs = ['/tmp', process.cwd()];
|
||||
if (!safeDirs.some((dir: string) => resolvedPath === dir || resolvedPath.startsWith(dir + '/'))) {
|
||||
throw new Error(`Path must be within: ${safeDirs.join(', ')}`);
|
||||
}
|
||||
try {
|
||||
// Inject overlay divs at each ref's bounding box
|
||||
const boxes: Array<{ ref: string; box: { x: number; y: number; width: number; height: number } }> = [];
|
||||
|
||||
@@ -1523,4 +1523,38 @@ describe('Path traversal prevention', () => {
|
||||
expect(err.message).toContain('Path must be within');
|
||||
}
|
||||
});
|
||||
|
||||
test('snapshot -a -o rejects path outside safe dirs', async () => {
|
||||
await handleWriteCommand('goto', [baseUrl + '/basic.html'], bm);
|
||||
// First get a snapshot so refs exist
|
||||
await handleMetaCommand('snapshot', ['-i'], bm, () => {});
|
||||
try {
|
||||
await handleMetaCommand('snapshot', ['-a', '-o', '/etc/evil.png'], bm, () => {});
|
||||
expect(true).toBe(false);
|
||||
} catch (err: any) {
|
||||
expect(err.message).toContain('Path must be within');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Chain command: cookie-import in chain ──────────────────────
|
||||
|
||||
describe('Chain with cookie-import', () => {
|
||||
test('cookie-import works inside chain', async () => {
|
||||
await handleWriteCommand('goto', [baseUrl + '/basic.html'], bm);
|
||||
const tmpCookies = '/tmp/test-chain-cookies.json';
|
||||
fs.writeFileSync(tmpCookies, JSON.stringify([
|
||||
{ name: 'chain_test', value: 'chain_value', domain: 'localhost', path: '/' }
|
||||
]));
|
||||
try {
|
||||
const commands = JSON.stringify([
|
||||
['cookie-import', tmpCookies],
|
||||
]);
|
||||
const result = await handleMetaCommand('chain', [commands], bm, async () => {});
|
||||
expect(result).toContain('[cookie-import]');
|
||||
expect(result).toContain('Loaded 1 cookie');
|
||||
} finally {
|
||||
try { fs.unlinkSync(tmpCookies); } catch {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gstack",
|
||||
"version": "0.0.1",
|
||||
"version": "0.3.1",
|
||||
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
||||
Reference in New Issue
Block a user