mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-18 19:02:18 +02:00
fix(make-pdf): write browse-bound temp files under the safe-dirs allowlist
os.tmpdir() on macOS resolves to /var/folders/..., which fails browse's safe-dirs validation ([/tmp, cwd]) since the v1.6.0.0 --from-file tightening. Default PDF output (generate with no -o), the preview HTML, tmpFile() scratch files, and setup's smoke-test fixture/output all wrote there, so browse rejected the paths it was asked to read or write. Export PAYLOAD_TMP_DIR from browseClient (the existing TEMP_DIR convention: os.tmpdir() on Windows, /tmp elsewhere) and route orchestrator.ts and setup.ts temp files through it. Contributed by @lvthewah (PR #2505; the browse-binary directory guard from that PR landed separately via PR #2538). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
7ca68da785
commit
de08279969
@@ -195,16 +195,18 @@ function runBrowse(args: string[]): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a payload to a tmp file and return the path. Used for any payload
|
* Temp dir for any file handed to browse (payloads, rendered HTML, PDF output).
|
||||||
* >4KB to avoid Windows argv limits (Codex round 2 #3).
|
|
||||||
*
|
*
|
||||||
* Path must be under the browse safe-dirs allowlist (/tmp or cwd on
|
* Path must be under the browse safe-dirs allowlist (/tmp or cwd on
|
||||||
* non-Windows; os.tmpdir on Windows). v1.6.0.0 tightened --from-file
|
* non-Windows; os.tmpdir on Windows). v1.6.0.0 tightened --from-file
|
||||||
* validation to close a CLI/API parity gap (PR #1103), so os.tmpdir()
|
* validation to close a CLI/API parity gap (PR #1103), so os.tmpdir()
|
||||||
* on macOS (/var/folders/...) now fails validateReadPath. Use the same
|
* on macOS (/var/folders/...) now fails validateReadPath. Use the same
|
||||||
* TEMP_DIR convention as browse/src/platform.ts.
|
* TEMP_DIR convention as browse/src/platform.ts.
|
||||||
|
*
|
||||||
|
* Exported because orchestrator.ts and setup.ts write files that browse must
|
||||||
|
* read back; os.tmpdir() there trips the same validateReadPath rejection.
|
||||||
*/
|
*/
|
||||||
const PAYLOAD_TMP_DIR = process.platform === "win32" ? os.tmpdir() : "/tmp";
|
export const PAYLOAD_TMP_DIR = process.platform === "win32" ? os.tmpdir() : "/tmp";
|
||||||
|
|
||||||
function writePayloadFile(payload: Record<string, unknown>): string {
|
function writePayloadFile(payload: Record<string, unknown>): string {
|
||||||
const hash = crypto.createHash("sha256")
|
const hash = crypto.createHash("sha256")
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import * as fs from "node:fs";
|
import * as fs from "node:fs";
|
||||||
import * as os from "node:os";
|
|
||||||
import * as path from "node:path";
|
import * as path from "node:path";
|
||||||
import * as crypto from "node:crypto";
|
import * as crypto from "node:crypto";
|
||||||
import { spawn } from "node:child_process";
|
import { spawn } from "node:child_process";
|
||||||
@@ -86,7 +85,7 @@ export async function generate(opts: GenerateOptions): Promise<string> {
|
|||||||
|
|
||||||
const to = opts.to ?? "pdf";
|
const to = opts.to ?? "pdf";
|
||||||
const outputPath = path.resolve(
|
const outputPath = path.resolve(
|
||||||
opts.output ?? path.join(os.tmpdir(), `${deriveSlug(input)}.${to}`),
|
opts.output ?? path.join(browseClient.PAYLOAD_TMP_DIR, `${deriveSlug(input)}.${to}`),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Stage 1: read markdown
|
// Stage 1: read markdown
|
||||||
@@ -358,7 +357,7 @@ export async function preview(opts: PreviewOptions): Promise<string> {
|
|||||||
progress.end("Rendering HTML", `${rendered.meta.wordCount} words`);
|
progress.end("Rendering HTML", `${rendered.meta.wordCount} words`);
|
||||||
|
|
||||||
// Write to a stable path under /tmp so the user can reload in the same tab.
|
// Write to a stable path under /tmp so the user can reload in the same tab.
|
||||||
const previewPath = path.join(os.tmpdir(), `make-pdf-preview-${deriveSlug(input)}.html`);
|
const previewPath = path.join(browseClient.PAYLOAD_TMP_DIR, `make-pdf-preview-${deriveSlug(input)}.html`);
|
||||||
fs.writeFileSync(previewPath, rendered.html, "utf8");
|
fs.writeFileSync(previewPath, rendered.html, "utf8");
|
||||||
|
|
||||||
progress.begin("Opening preview");
|
progress.begin("Opening preview");
|
||||||
@@ -378,7 +377,7 @@ function deriveSlug(p: string): string {
|
|||||||
|
|
||||||
function tmpFile(ext: string): string {
|
function tmpFile(ext: string): string {
|
||||||
const hash = crypto.randomBytes(6).toString("hex");
|
const hash = crypto.randomBytes(6).toString("hex");
|
||||||
return path.join(os.tmpdir(), `make-pdf-${process.pid}-${hash}.${ext}`);
|
return path.join(browseClient.PAYLOAD_TMP_DIR, `make-pdf-${process.pid}-${hash}.${ext}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tryOpen(pathOrUrl: string): void {
|
function tryOpen(pathOrUrl: string): void {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
* 6. Print a 3-command cheatsheet
|
* 6. Print a 3-command cheatsheet
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as os from "node:os";
|
|
||||||
import * as path from "node:path";
|
import * as path from "node:path";
|
||||||
import * as fs from "node:fs";
|
import * as fs from "node:fs";
|
||||||
|
|
||||||
@@ -77,8 +76,8 @@ export async function runSetup(): Promise<void> {
|
|||||||
"The second paragraph contains curly quotes (\"hello\"), an em dash -- like this, and an ellipsis... all of which should render correctly.",
|
"The second paragraph contains curly quotes (\"hello\"), an em dash -- like this, and an ellipsis... all of which should render correctly.",
|
||||||
"",
|
"",
|
||||||
].join("\n");
|
].join("\n");
|
||||||
const fixturePath = path.join(os.tmpdir(), `make-pdf-smoke-${process.pid}.md`);
|
const fixturePath = path.join(browseClient.PAYLOAD_TMP_DIR, `make-pdf-smoke-${process.pid}.md`);
|
||||||
const outPath = path.join(os.tmpdir(), `make-pdf-smoke-${process.pid}.pdf`);
|
const outPath = path.join(browseClient.PAYLOAD_TMP_DIR, `make-pdf-smoke-${process.pid}.pdf`);
|
||||||
fs.writeFileSync(fixturePath, fixture, "utf8");
|
fs.writeFileSync(fixturePath, fixture, "utf8");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user