@crouton-kit/capture 1.3.18 → 1.3.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/bin/capture +4204 -3244
  2. package/package.json +1 -1
  3. package/src/capture.ts +4 -1
  4. package/src/cdp/args.ts +22 -3
  5. package/src/cdp/browser-process.ts +510 -0
  6. package/src/cdp/client.ts +10 -1
  7. package/src/cdp/color-scheme.ts +47 -0
  8. package/src/cdp/commands/measure/index.ts +1 -1
  9. package/src/cdp/commands/measure/snap.ts +50 -8
  10. package/src/cdp/commands/motion/mask.ts +8 -2
  11. package/src/cdp/commands/page/click.ts +14 -0
  12. package/src/cdp/commands/page/elements.ts +2 -2
  13. package/src/cdp/commands/page/index.ts +1 -1
  14. package/src/cdp/commands/page/shot.ts +58 -13
  15. package/src/cdp/commands/tab/index.ts +19 -8
  16. package/src/cdp/commands/tab/launch.ts +73 -0
  17. package/src/cdp/commands/tab/list.ts +14 -2
  18. package/src/cdp/commands/tab/quit.ts +78 -0
  19. package/src/cdp/har-recorder.ts +14 -20
  20. package/src/cdp/measure/collectors/ax.ts +3 -4
  21. package/src/cdp/measure/collectors/forms.ts +4 -6
  22. package/src/cdp/measure/collectors/media.ts +1 -2
  23. package/src/cdp/measure/collectors/states.ts +1 -6
  24. package/src/cdp/measure/collectors/style-provenance.ts +4 -16
  25. package/src/cdp/measure/collectors/styles.ts +21 -10
  26. package/src/cdp/measure/collectors/text.ts +3 -5
  27. package/src/cdp/measure/snapshot.ts +197 -29
  28. package/src/cdp/measure/types.ts +36 -2
  29. package/src/cdp/motion/jank.ts +8 -1
  30. package/src/cdp/screenshot.ts +83 -8
  31. package/src/cdp/targets.ts +5 -0
  32. package/src/cdp/types.ts +6 -0
  33. package/src/har-manager.ts +16 -15
  34. package/src/interact.ts +20 -4
  35. package/src/output/render.ts +2 -0
  36. package/src/registry.ts +1 -1
  37. package/src/session/commands.ts +223 -43
  38. package/src/session/har-redact.ts +125 -0
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Render-time credential redaction for HAR request URLs — the ONE narrow
3
+ * carve-out in Capture's otherwise no-redaction posture.
4
+ *
5
+ * Capture preserves browser evidence rather than redacting it, and the HAR
6
+ * artifact on disk remains full fidelity: this module is applied only where a
7
+ * URL is rendered into a `session har` block, never on collection, never on
8
+ * the stored `har.json`/live NDJSON, and never on the value a `--filter-url`
9
+ * pattern is matched against. Its whole job is to keep a dashboard/API session
10
+ * token out of an agent's transcript and terminal scrollback while leaving the
11
+ * request itself identifiable — the parameter name, ordering, and every
12
+ * non-credential value survive untouched, so the row still joins to the
13
+ * artifact record it came from.
14
+ *
15
+ * Matching is on the parameter NAME only; no value is ever inspected, so this
16
+ * cannot depend on the shape of any observed secret.
17
+ */
18
+
19
+ /** Replacement text for a credential-like parameter value in rendered output. */
20
+ export const REDACTED_VALUE = 'REDACTED';
21
+
22
+ /**
23
+ * Parameter names that are credential-bearing on their own. Compared after
24
+ * normalization (lowercased, every non-alphanumeric character dropped), so
25
+ * `api_key`, `API-Key`, and `apiKey` all reduce to `apikey`.
26
+ */
27
+ const CREDENTIAL_PARAM_NAMES: ReadonlySet<string> = new Set([
28
+ 'key',
29
+ 'apikey',
30
+ 'accesskey',
31
+ 'secretkey',
32
+ 'privatekey',
33
+ 'sig',
34
+ 'signature',
35
+ 'auth',
36
+ 'authorization',
37
+ 'credential',
38
+ 'credentials',
39
+ 'password',
40
+ 'passwd',
41
+ 'pwd',
42
+ 'token',
43
+ 'secret',
44
+ 'code',
45
+ 'authcode',
46
+ 'authorizationcode',
47
+ 'sessionid',
48
+ 'sessionkey',
49
+ ]);
50
+
51
+ /**
52
+ * Fragments that make ANY containing parameter name credential-bearing —
53
+ * `access_token`, `refresh-token`, `clientSecret`, `x-amz-signature`, and the
54
+ * rest of the long tail no exact list keeps up with.
55
+ */
56
+ const CREDENTIAL_PARAM_FRAGMENTS: readonly string[] = [
57
+ 'token',
58
+ 'secret',
59
+ 'password',
60
+ 'passwd',
61
+ 'credential',
62
+ 'apikey',
63
+ 'accesskey',
64
+ 'privatekey',
65
+ 'signature',
66
+ 'authorization',
67
+ 'sessionid',
68
+ ];
69
+
70
+ function normalizeParamName(raw: string): string {
71
+ let decoded = raw;
72
+ try {
73
+ decoded = decodeURIComponent(raw.replace(/\+/g, ' '));
74
+ } catch {
75
+ decoded = raw;
76
+ }
77
+ return decoded.toLowerCase().replace(/[^a-z0-9]/g, '');
78
+ }
79
+
80
+ /** Whether a query/fragment parameter name names a credential. */
81
+ export function isCredentialParamName(raw: string): boolean {
82
+ const name = normalizeParamName(raw);
83
+ if (name === '') return false;
84
+ if (CREDENTIAL_PARAM_NAMES.has(name)) return true;
85
+ return CREDENTIAL_PARAM_FRAGMENTS.some((fragment) => name.includes(fragment));
86
+ }
87
+
88
+ /** Redacts credential values in one `a=1&b=2` parameter section. */
89
+ function redactParamSection(section: string): string {
90
+ return section
91
+ .split('&')
92
+ .map((pair) => {
93
+ const eq = pair.indexOf('=');
94
+ if (eq < 0) return pair;
95
+ const name = pair.slice(0, eq);
96
+ return isCredentialParamName(name) ? `${name}=${REDACTED_VALUE}` : pair;
97
+ })
98
+ .join('&');
99
+ }
100
+
101
+ /**
102
+ * Returns the URL with credential-like query (and parameter-shaped fragment)
103
+ * values replaced by `REDACTED`. Everything else — scheme, host, path, other
104
+ * parameters, ordering — is returned verbatim; a URL carrying no credential
105
+ * parameter comes back byte-identical. Operates on the raw string rather than
106
+ * `new URL()` so a relative or malformed URL is never re-encoded or dropped.
107
+ */
108
+ export function redactUrlCredentials(url: string): string {
109
+ const hashIndex = url.indexOf('#');
110
+ const base = hashIndex < 0 ? url : url.slice(0, hashIndex);
111
+ const fragment = hashIndex < 0 ? null : url.slice(hashIndex + 1);
112
+
113
+ const queryIndex = base.indexOf('?');
114
+ const head = queryIndex < 0 ? base : base.slice(0, queryIndex);
115
+ const query = queryIndex < 0 ? null : base.slice(queryIndex + 1);
116
+
117
+ const renderedQuery = query === null ? '' : `?${redactParamSection(query)}`;
118
+ // A fragment is only treated as parameters when it actually looks like them;
119
+ // an ordinary `#section-2` anchor is left exactly as captured.
120
+ const renderedFragment = fragment === null
121
+ ? ''
122
+ : `#${fragment.includes('=') ? redactParamSection(fragment) : fragment}`;
123
+
124
+ return `${head}${renderedQuery}${renderedFragment}`;
125
+ }