mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-02 03:35:09 +02:00
fix(design): bind server to localhost and validate reload paths
Cherry-pick PR #803 by @garagon. Adds hostname: '127.0.0.1' to Bun.serve() and validates /api/reload paths are within cwd() or tmpdir(). Closes C1+C2 from security audit #783. Co-Authored-By: garagon <garagon@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+15
-1
@@ -33,19 +33,21 @@
|
||||
*/
|
||||
|
||||
import fs from "fs";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import { spawn } from "child_process";
|
||||
|
||||
export interface ServeOptions {
|
||||
html: string;
|
||||
port?: number;
|
||||
hostname?: string; // default '127.0.0.1' — localhost only
|
||||
timeout?: number; // seconds, default 600 (10 min)
|
||||
}
|
||||
|
||||
type ServerState = "serving" | "regenerating" | "done";
|
||||
|
||||
export async function serve(options: ServeOptions): Promise<void> {
|
||||
const { html, port = 0, timeout = 600 } = options;
|
||||
const { html, port = 0, hostname = '127.0.0.1', timeout = 600 } = options;
|
||||
|
||||
// Validate HTML file exists
|
||||
if (!fs.existsSync(html)) {
|
||||
@@ -59,6 +61,7 @@ export async function serve(options: ServeOptions): Promise<void> {
|
||||
|
||||
const server = Bun.serve({
|
||||
port,
|
||||
hostname,
|
||||
fetch(req) {
|
||||
const url = new URL(req.url);
|
||||
|
||||
@@ -182,6 +185,17 @@ export async function serve(options: ServeOptions): Promise<void> {
|
||||
);
|
||||
}
|
||||
|
||||
// Validate path is within cwd or temp directory
|
||||
const resolved = path.resolve(newHtmlPath);
|
||||
const safeDirs = [process.cwd(), os.tmpdir()];
|
||||
const isSafe = safeDirs.some(dir => resolved.startsWith(dir + path.sep) || resolved === dir);
|
||||
if (!isSafe) {
|
||||
return Response.json(
|
||||
{ error: `Path must be within working directory or temp` },
|
||||
{ status: 403 }
|
||||
);
|
||||
}
|
||||
|
||||
// Swap the HTML content
|
||||
htmlContent = fs.readFileSync(newHtmlPath, "utf-8");
|
||||
state = "serving";
|
||||
|
||||
Reference in New Issue
Block a user