diff --git a/.changeset/silly-bats-add.md b/.changeset/silly-bats-add.md new file mode 100644 index 000000000000..e6de77454400 --- /dev/null +++ b/.changeset/silly-bats-add.md @@ -0,0 +1,5 @@ +--- +"wrangler": patch +--- + +Don't log sensitive data to the Wrangler debug log file by default. This includes API request headers and responses. diff --git a/packages/wrangler/src/cfetch/internal.ts b/packages/wrangler/src/cfetch/internal.ts index 0744d8da8760..2793ced96ebf 100644 --- a/packages/wrangler/src/cfetch/internal.ts +++ b/packages/wrangler/src/cfetch/internal.ts @@ -38,11 +38,9 @@ export async function performApiFetch( ); const logHeaders = cloneHeaders(headers); delete logHeaders["Authorization"]; - logger.debug("HEADERS:", JSON.stringify(logHeaders, null, 2)); - logger.debug( - "INIT:", - JSON.stringify({ ...init, headers: logHeaders }, null, 2) - ); + logger.debugWithSanitization("HEADERS:", JSON.stringify(logHeaders, null, 2)); + + logger.debugWithSanitization("INIT:", JSON.stringify({ ...init }, null, 2)); logger.debug("-- END CF API REQUEST"); return await fetch(`${getCloudflareApiBaseUrl()}${resource}${queryString}`, { method, @@ -82,8 +80,8 @@ export async function fetchInternal( ); const logHeaders = cloneHeaders(response.headers); delete logHeaders["Authorization"]; - logger.debug("HEADERS:", JSON.stringify(logHeaders, null, 2)); - logger.debug("RESPONSE:", jsonText); + logger.debugWithSanitization("HEADERS:", JSON.stringify(logHeaders, null, 2)); + logger.debugWithSanitization("RESPONSE:", jsonText); logger.debug("-- END CF API RESPONSE"); // HTTP 204 and HTTP 205 responses do not return a body. We need to special-case this diff --git a/packages/wrangler/src/dev/create-worker-preview.ts b/packages/wrangler/src/dev/create-worker-preview.ts index 6724ed20253c..b4986118db0c 100644 --- a/packages/wrangler/src/dev/create-worker-preview.ts +++ b/packages/wrangler/src/dev/create-worker-preview.ts @@ -160,7 +160,11 @@ export async function createPreviewSession( const switchedExchangeUrl = switchHost(exchange_url, ctx.host).toString(); - logger.debug(`-- START EXCHANGE API REQUEST: GET ${switchedExchangeUrl}`); + logger.debugWithSanitization( + "-- START EXCHANGE API REQUEST:", + ` GET ${switchedExchangeUrl}` + ); + logger.debug("-- END EXCHANGE API REQUEST"); const exchangeResponse = await fetch(switchedExchangeUrl, { signal: abortSignal, @@ -172,7 +176,8 @@ export async function createPreviewSession( exchangeResponse.status ); logger.debug("HEADERS:", JSON.stringify(exchangeResponse.headers, null, 2)); - logger.debug("RESPONSE:", bodyText); + logger.debugWithSanitization("RESPONSE:", bodyText); + logger.debug("-- END EXCHANGE API RESPONSE"); const { inspector_websocket, prewarm, token } = parseJSON<{ diff --git a/packages/wrangler/src/dev/proxy.ts b/packages/wrangler/src/dev/proxy.ts index a490dff7687d..d8d48ebced65 100644 --- a/packages/wrangler/src/dev/proxy.ts +++ b/packages/wrangler/src/dev/proxy.ts @@ -460,8 +460,8 @@ function configureProxyServer({ method, url ); - logger.debug("HEADERS", JSON.stringify(headers, null, 2)); - logger.debug("PREVIEW TOKEN", previewToken); + logger.debugWithSanitization("HEADERS", JSON.stringify(headers, null, 2)); + logger.debugWithSanitization("PREVIEW TOKEN", previewToken); request.on("response", (responseHeaders) => { const status = responseHeaders[":status"] ?? 500; diff --git a/packages/wrangler/src/environment-variables/factory.ts b/packages/wrangler/src/environment-variables/factory.ts index 658ccff593c6..847db1a3ae3d 100644 --- a/packages/wrangler/src/environment-variables/factory.ts +++ b/packages/wrangler/src/environment-variables/factory.ts @@ -16,6 +16,7 @@ type VariableNames = | "WRANGLER_CLIENT_ID" | "WRANGLER_LOG" | "WRANGLER_LOG_PATH" + | "WRANGLER_LOG_SANITIZE" | "WRANGLER_REVOKE_URL" | "WRANGLER_SEND_METRICS" | "WRANGLER_TOKEN_URL"; diff --git a/packages/wrangler/src/environment-variables/misc-variables.ts b/packages/wrangler/src/environment-variables/misc-variables.ts index 44fbd3944050..6511a6a7b929 100644 --- a/packages/wrangler/src/environment-variables/misc-variables.ts +++ b/packages/wrangler/src/environment-variables/misc-variables.ts @@ -57,3 +57,11 @@ export const getCloudflareApiBaseUrl = getEnvironmentVariableFactory({ ? "https://api.staging.cloudflare.com/client/v4" : "https://api.cloudflare.com/client/v4", }); + +// Should we sanitize debug logs? By default we do, since debug logs could be added to GitHub issues and shouldn't include sensitive information +export const getSanitizeLogs = getEnvironmentVariableFactory({ + variableName: "WRANGLER_LOG_SANITIZE", + defaultValue() { + return "true"; + }, +}); diff --git a/packages/wrangler/src/logger.ts b/packages/wrangler/src/logger.ts index 1932a8a9ff84..07c6bad4a60b 100644 --- a/packages/wrangler/src/logger.ts +++ b/packages/wrangler/src/logger.ts @@ -3,6 +3,7 @@ import chalk from "chalk"; import CLITable from "cli-table3"; import { formatMessagesSync } from "esbuild"; import { getEnvironmentVariableFactory } from "./environment-variables/factory"; +import { getSanitizeLogs } from "./environment-variables/misc-variables"; import { appendToDebugLogFile } from "./utils/debug-log-file"; import type { Message } from "esbuild"; export const LOGGER_LEVELS = { @@ -54,6 +55,16 @@ export class Logger { columns = process.stdout.columns; debug = (...args: unknown[]) => this.doLog("debug", args); + debugWithSanitization = (label: string, ...args: unknown[]) => { + if (getSanitizeLogs() === "false") { + this.doLog("debug", [label, ...args]); + } else { + this.doLog("debug", [ + label, + "omitted; set WRANGLER_LOG_SANITIZE=false to include sanitized data", + ]); + } + }; info = (...args: unknown[]) => this.doLog("info", args); log = (...args: unknown[]) => this.doLog("log", args); warn = (...args: unknown[]) => this.doLog("warn", args);