Deployment protection bypass (#298)
* test preview bypass 2 Co-authored-by: Cursor <cursoragent@cursor.com> * add apiFetch wrapper with Vercel bypass via query param + header the template workflow was missing VERCEL_AUTOMATION_BYPASS_SECRET, so all action API calls to preview deployments hit Vercel's deployment protection without bypass. this also consolidates the bypass logic into a single fetch wrapper that applies the secret as both a query parameter (matching server-side forwarding) and a header for belt-and-suspenders reliability. Co-authored-by: Cursor <cursoragent@cursor.com> * security hardening for Vercel bypass - redact bypass token from webhook forwarder logs and response body - remove dead x-preview-api-forward header - refactor getAllSecrets() to use SENSITIVE_PATTERNS instead of hardcoded list - enforce https:// on API_URL (localhost exempt for local dev) Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
pullfrog[bot]
parent
d5508d99bb
commit
6f108237d4
+16
-13
@@ -1,24 +1,27 @@
|
||||
import { log } from "./cli.ts";
|
||||
|
||||
function isLocalUrl(url: URL): boolean {
|
||||
return url.hostname === "localhost" || url.hostname === "127.0.0.1";
|
||||
}
|
||||
|
||||
/**
|
||||
* resolve the Pullfrog API base URL.
|
||||
*
|
||||
* in the action: API_URL is not explicitly set, so this falls back to https://pullfrog.com.
|
||||
* in local dev: API_URL=http://localhost:3000 (from .env).
|
||||
*
|
||||
* enforces https:// for non-local URLs to prevent cleartext credential transmission.
|
||||
*/
|
||||
export function getApiUrl(): string {
|
||||
const url = process.env.API_URL || "https://pullfrog.com";
|
||||
log.debug(`resolved API_URL: ${url}`);
|
||||
return url;
|
||||
}
|
||||
const raw = process.env.API_URL || "https://pullfrog.com";
|
||||
const parsed = new URL(raw);
|
||||
|
||||
/**
|
||||
* returns headers needed to bypass Vercel deployment protection on preview deployments.
|
||||
* when VERCEL_AUTOMATION_BYPASS_SECRET is set (preview repos), includes the bypass header.
|
||||
* otherwise returns an empty object (production / local dev).
|
||||
*/
|
||||
export function getVercelBypassHeaders(): Record<string, string> {
|
||||
const secret = process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
|
||||
if (!secret) return {};
|
||||
return { "x-vercel-protection-bypass": secret };
|
||||
if (parsed.protocol !== "https:" && !isLocalUrl(parsed)) {
|
||||
throw new Error(
|
||||
`API_URL must use https:// (got ${parsed.protocol}). only localhost is exempt.`
|
||||
);
|
||||
}
|
||||
|
||||
log.debug(`resolved API_URL: ${raw}`);
|
||||
return raw;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user