Skip to content

Commit 3ad4dd8

Browse files
refactor(wrangler): add safe command/args handling for telemetry
- Rename 'command' to 'safeCommand' (without 'wrangler ' prefix) and 'args' to 'safeArgs' in telemetry events - Add 'logArgs' boolean to control whether command arguments are included in telemetry - Commands must explicitly opt-in via metadata.logArgs: true to log arguments - Safe commands (list, info, get, etc.) that don't handle sensitive data opt-in to logging - Sensitive commands (secret put/delete/bulk, hyperdrive create) intentionally do not opt-in - Update fallback telemetry in index.ts to use new format with logArgs: false
1 parent cf514de commit 3ad4dd8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+248
-68
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
Sanitize commands in telemetry to prevent accidentally capturing sensitive information that users may have mistakenly pasted as command arguments.
6+
7+
The following commands will no longer collect any telemetry on argument usage:
8+
9+
- All secret commands: `wrangler secret put/bulk`, `wrangler pages secret put/bulk`, `wrangler versions secret put/bulk`
10+
- `wrangler login`
11+
- `wrangler kv key put`, `wrangler kv bulk put`
12+
- `wrangler hyperdrive create/update`
13+
- `wrangler r2 bucket sippy enable`
14+
- `wrangler d1 execute`
15+
- `wrangler secrets-store secret create/update`
16+
- `wrangler workflows trigger`, `wrangler workflows instances send-event`
17+
- Generally commands with file paths that could reveal sensitive structure
18+
- Any command not explicitly marked as safe

packages/wrangler/src/__tests__/metrics.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,9 @@ describe("metrics", () => {
241241
argsUsed: [],
242242
argsCombination: "",
243243
agent: null,
244-
command: "wrangler docs",
245-
args: {},
244+
safeCommand: "docs",
245+
safeArgs: {},
246+
logArgs: true,
246247
};
247248
beforeEach(() => {
248249
// Default: no agent detected
@@ -480,7 +481,7 @@ describe("metrics", () => {
480481

481482
expect(requests.count).toBe(2);
482483
expect(std.debug).toContain('"argsCombination":""');
483-
expect(std.debug).toContain('"command":"wrangler login"');
484+
expect(std.debug).toContain('"safeCommand":"login"');
484485
});
485486

486487
it("should include args provided by the user", async () => {

packages/wrangler/src/ai/listCatalog.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const aiModelsCommand = createCommand({
88
description: "List catalog models",
99
status: "stable",
1010
owner: "Product: AI",
11+
logArgs: true,
1112
},
1213
behaviour: {
1314
printBanner: (args) => !args.json,

packages/wrangler/src/ai/listFinetune.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export const aiFineTuneListCommand = createCommand({
99
description: "List your finetune files",
1010
status: "stable",
1111
owner: "Product: AI",
12+
logArgs: true,
1213
},
1314
behaviour: {
1415
printBanner: (args) => !args.json,

packages/wrangler/src/core/register-yargs-command.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,17 @@ function createHandler(
214214
}
215215
}
216216

217+
// Compute safe telemetry properties
218+
// Strip "wrangler " prefix to get safeCommand (e.g., "wrangler dev" -> "dev")
219+
const safeCommand = commandName.replace(/^wrangler\s*/, "");
220+
const logArgs = def.metadata.logArgs ?? false;
221+
// If logArgs is false, send empty object; otherwise pass full args
222+
const safeArgs = logArgs ? args : {};
223+
217224
dispatcher.sendCommandEvent("wrangler command started", {
218-
command: commandName,
219-
args,
225+
safeCommand,
226+
safeArgs,
227+
logArgs,
220228
});
221229

222230
try {
@@ -230,8 +238,9 @@ function createHandler(
230238

231239
const durationMs = Date.now() - startTime;
232240
dispatcher.sendCommandEvent("wrangler command completed", {
233-
command: commandName,
234-
args,
241+
safeCommand,
242+
safeArgs,
243+
logArgs,
235244
durationMs,
236245
durationSeconds: durationMs / 1000,
237246
durationMinutes: durationMs / 1000 / 60,
@@ -247,8 +256,9 @@ function createHandler(
247256

248257
const durationMs = Date.now() - startTime;
249258
dispatcher.sendCommandEvent("wrangler command errored", {
250-
command: commandName,
251-
args,
259+
safeCommand,
260+
safeArgs,
261+
logArgs,
252262
durationMs,
253263
durationSeconds: durationMs / 1000,
254264
durationMinutes: durationMs / 1000 / 60,

packages/wrangler/src/core/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ export type Metadata = {
7676
* Commands without a category will appear under the default "COMMANDS" group.
7777
*/
7878
category?: MetadataCategory;
79+
/**
80+
* If true, arguments for this command will be included in telemetry.
81+
*
82+
* @default false - Arguments are not logged by default.
83+
* Set to `true` to explicitly include this command's args in telemetry.
84+
*/
85+
logArgs?: boolean;
7986
};
8087

8188
export type ArgDefinition = Omit<PositionalOptions, "type"> &

packages/wrangler/src/d1/delete.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const d1DeleteCommand = createCommand({
1414
status: "stable",
1515
epilogue: "This command acts on remote D1 Databases.",
1616
owner: "Product: D1",
17+
logArgs: true,
1718
},
1819
behaviour: {
1920
printBanner: true,

packages/wrangler/src/d1/info.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const d1InfoCommand = createCommand({
1616
epilogue: "This command acts on remote D1 Databases.",
1717
status: "stable",
1818
owner: "Product: D1",
19+
logArgs: true,
1920
},
2021
behaviour: {
2122
printBanner: (args) => !args.json,

packages/wrangler/src/d1/insights.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export const d1InsightsCommand = createCommand({
6060
epilogue: "This command acts on remote D1 Databases.",
6161
status: "experimental",
6262
owner: "Product: D1",
63+
logArgs: true,
6364
},
6465
behaviour: {
6566
printBanner: (args) => !args.json,

packages/wrangler/src/d1/list.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const d1ListCommand = createCommand({
1111
epilogue: "This command acts on remote D1 Databases.",
1212
status: "stable",
1313
owner: "Product: D1",
14+
logArgs: true,
1415
},
1516
behaviour: {
1617
printBanner: (args) => !args.json,

0 commit comments

Comments
 (0)