Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .changeset/safe-command-args-metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
"wrangler": patch
---

Sanitize commands in telemetry to prevent accidentally capturing sensitive information that users may have mistakenly pasted as command arguments.

The following commands will no longer collect any telemetry on argument usage:

- All secret commands: `wrangler secret put/bulk`, `wrangler pages secret put/bulk`, `wrangler versions secret put/bulk`
- `wrangler login`
- `wrangler kv key put`, `wrangler kv bulk put`
- `wrangler hyperdrive create/update`
- `wrangler r2 bucket sippy enable`
- `wrangler d1 execute`
- `wrangler secrets-store secret create/update`
- `wrangler workflows trigger`, `wrangler workflows instances send-event`
- Generally commands with file paths that could reveal sensitive structure
- Any command not explicitly marked as safe
7 changes: 4 additions & 3 deletions packages/wrangler/src/__tests__/metrics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,9 @@ describe("metrics", () => {
argsUsed: [],
argsCombination: "",
agent: null,
command: "wrangler docs",
args: {},
safeCommand: "docs",
safeArgs: {},
logArgs: true,
};
beforeEach(() => {
// Default: no agent detected
Expand Down Expand Up @@ -480,7 +481,7 @@ describe("metrics", () => {

expect(requests.count).toBe(2);
expect(std.debug).toContain('"argsCombination":""');
expect(std.debug).toContain('"command":"wrangler login"');
expect(std.debug).toContain('"safeCommand":"login"');
});

it("should include args provided by the user", async () => {
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/ai/listCatalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const aiModelsCommand = createCommand({
description: "List catalog models",
status: "stable",
owner: "Product: AI",
logArgs: true,
},
behaviour: {
printBanner: (args) => !args.json,
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/ai/listFinetune.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const aiFineTuneListCommand = createCommand({
description: "List your finetune files",
status: "stable",
owner: "Product: AI",
logArgs: true,
},
behaviour: {
printBanner: (args) => !args.json,
Expand Down
22 changes: 16 additions & 6 deletions packages/wrangler/src/core/register-yargs-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,17 @@ function createHandler(
}
}

// Compute safe telemetry properties
// Strip "wrangler " prefix to get safeCommand (e.g., "wrangler dev" -> "dev")
const safeCommand = commandName.replace(/^wrangler\s*/, "");
const logArgs = def.metadata.logArgs ?? false;
// If logArgs is false, send empty object; otherwise pass full args
const safeArgs = logArgs ? args : {};

dispatcher.sendCommandEvent("wrangler command started", {
command: commandName,
args,
safeCommand,
safeArgs,
logArgs,
});

try {
Expand All @@ -230,8 +238,9 @@ function createHandler(

const durationMs = Date.now() - startTime;
dispatcher.sendCommandEvent("wrangler command completed", {
command: commandName,
args,
safeCommand,
safeArgs,
logArgs,
durationMs,
durationSeconds: durationMs / 1000,
durationMinutes: durationMs / 1000 / 60,
Expand All @@ -247,8 +256,9 @@ function createHandler(

const durationMs = Date.now() - startTime;
dispatcher.sendCommandEvent("wrangler command errored", {
command: commandName,
args,
safeCommand,
safeArgs,
logArgs,
durationMs,
durationSeconds: durationMs / 1000,
durationMinutes: durationMs / 1000 / 60,
Expand Down
7 changes: 7 additions & 0 deletions packages/wrangler/src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ export type Metadata = {
* Commands without a category will appear under the default "COMMANDS" group.
*/
category?: MetadataCategory;
/**
* If true, arguments for this command will be included in telemetry.
*
* @default false - Arguments are not logged by default.
* Set to `true` to explicitly include this command's args in telemetry.
*/
logArgs?: boolean;
};

export type ArgDefinition = Omit<PositionalOptions, "type"> &
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/d1/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const d1DeleteCommand = createCommand({
status: "stable",
epilogue: "This command acts on remote D1 Databases.",
owner: "Product: D1",
logArgs: true,
},
behaviour: {
printBanner: true,
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/d1/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const d1InfoCommand = createCommand({
epilogue: "This command acts on remote D1 Databases.",
status: "stable",
owner: "Product: D1",
logArgs: true,
},
behaviour: {
printBanner: (args) => !args.json,
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/d1/insights.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const d1InsightsCommand = createCommand({
epilogue: "This command acts on remote D1 Databases.",
status: "experimental",
owner: "Product: D1",
logArgs: true,
},
behaviour: {
printBanner: (args) => !args.json,
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/d1/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const d1ListCommand = createCommand({
epilogue: "This command acts on remote D1 Databases.",
status: "stable",
owner: "Product: D1",
logArgs: true,
},
behaviour: {
printBanner: (args) => !args.json,
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/d1/migrations/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const d1MigrationsListCommand = createCommand({
description: "View a list of unapplied migration files",
status: "stable",
owner: "Product: D1",
logArgs: true,
},
behaviour: {
printResourceLocation: true,
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/d1/timeTravel/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const d1TimeTravelInfoCommand = createCommand({
For more information about Time Travel, see https://developers.cloudflare.com/d1/reference/time-travel/`,
status: "stable",
owner: "Product: D1",
logArgs: true,
},
behaviour: {
printBanner: (args) => !args.json,
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/d1/timeTravel/restore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const d1TimeTravelRestoreCommand = createCommand({
For more information about Time Travel, see https://developers.cloudflare.com/d1/reference/time-travel/`,
status: "stable",
owner: "Product: D1",
logArgs: true,
},
behaviour: {
printBanner: (args) => !args.json,
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const deleteCommand = createCommand({
owner: "Workers: Authoring and Testing",
status: "stable",
category: "Compute & AI",
logArgs: true,
},
args: {
script: {
Expand Down
5 changes: 5 additions & 0 deletions packages/wrangler/src/dispatch-namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export const dispatchNamespaceListCommand = createCommand({
description: "List all dispatch namespaces",
owner: "Workers: Deploy and Config",
status: "stable",
logArgs: true,
},
async handler(_, { config }) {
const accountId = await requireAuth(config);
Expand All @@ -149,6 +150,7 @@ export const dispatchNamespaceGetCommand = createCommand({
description: "Get information about a dispatch namespace",
owner: "Workers: Deploy and Config",
status: "stable",
logArgs: true,
},
args: {
name: {
Expand All @@ -172,6 +174,7 @@ export const dispatchNamespaceCreateCommand = createCommand({
description: "Create a dispatch namespace",
owner: "Workers: Deploy and Config",
status: "stable",
logArgs: true,
},
args: {
name: {
Expand All @@ -195,6 +198,7 @@ export const dispatchNamespaceDeleteCommand = createCommand({
description: "Delete a dispatch namespace",
owner: "Workers: Deploy and Config",
status: "stable",
logArgs: true,
},
args: {
name: {
Expand All @@ -218,6 +222,7 @@ export const dispatchNamespaceRenameCommand = createCommand({
description: "Rename a dispatch namespace",
owner: "Workers: Deploy and Config",
status: "stable",
logArgs: true,
},
args: {
oldName: {
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/docs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const docs = createCommand({
description: "📚 Open Wrangler's command documentation in your browser",
owner: "Workers: Authoring and Testing",
status: "stable",
logArgs: true,
},
args: {
search: {
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/hyperdrive/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const hyperdriveDeleteCommand = createCommand({
description: "Delete a Hyperdrive config",
status: "stable",
owner: "Product: Hyperdrive",
logArgs: true,
},
args: {
id: {
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/hyperdrive/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const hyperdriveGetCommand = createCommand({
description: "Get a Hyperdrive config",
status: "stable",
owner: "Product: Hyperdrive",
logArgs: true,
},
args: {
id: {
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/hyperdrive/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const hyperdriveListCommand = createCommand({
description: "List Hyperdrive configs",
status: "stable",
owner: "Product: Hyperdrive",
logArgs: true,
},
args: {},
async handler(_, { config }) {
Expand Down
20 changes: 11 additions & 9 deletions packages/wrangler/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1929,15 +1929,15 @@ export async function main(argv: string[]): Promise<void> {
}, /* applyBeforeValidation */ true);

const startTime = Date.now();
let command: string | undefined;
let safeCommand: string | undefined;
let configArgs: ReadConfigCommandArgs = {};
let dispatcher: ReturnType<typeof getMetricsDispatcher> | undefined;

// Register middleware to capture command info for fallback telemetry
const wranglerWithTelemetry = wranglerWithMiddleware.middleware((args) => {
// Capture command and args for potential fallback telemetry
// (used when yargs validation errors occur before handler runs)
command = `wrangler ${args._.join(" ")}`;
safeCommand = args._.join(" ");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MattieTK - do we want this just to be "" since we cannot guarantee that the args don't contain something sensitive?

configArgs = args;

try {
Expand Down Expand Up @@ -1970,10 +1970,10 @@ export async function main(argv: string[]): Promise<void> {
// The error occurred before Command handler ran
// (e.g., yargs validation errors like unknown commands or invalid arguments).
// So we need to handle telemetry and error reporting here.
if (dispatcher && command) {
if (dispatcher && safeCommand) {
dispatchGenericCommandErrorEvent(
dispatcher,
command,
safeCommand,
configArgs,
startTime,
e
Expand Down Expand Up @@ -2021,7 +2021,7 @@ export async function main(argv: string[]): Promise<void> {
*/
function dispatchGenericCommandErrorEvent(
dispatcher: ReturnType<typeof getMetricsDispatcher>,
command: string,
safeCommand: string,
configArgs: ReadConfigCommandArgs,
startTime: number,
error: unknown
Expand All @@ -2030,13 +2030,15 @@ function dispatchGenericCommandErrorEvent(

// Send "started" event since handler never got to send it.
dispatcher.sendCommandEvent("wrangler command started", {
command,
args: configArgs,
safeCommand,
safeArgs: {},
logArgs: false,
});

dispatcher.sendCommandEvent("wrangler command errored", {
command,
args: configArgs,
safeCommand,
safeArgs: {},
logArgs: false,
durationMs,
durationSeconds: durationMs / 1000,
durationMinutes: durationMs / 1000 / 60,
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const init = createCommand({
owner: "Workers: Authoring and Testing",
status: "stable",
category: "Compute & AI",
logArgs: true,
},
args: {
name: {
Expand Down
Loading
Loading