@unotest/grounder-client 0.42.0 → 0.43.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.43.1] - 2026-09-29
4
+
5
+ ### Patch Changes
6
+
7
+ - 5433bab: Secret field values no longer leak into failures and replies. An
8
+ `assertValue` failure on a field marked as a credential (`type="password"`,
9
+ or `autocomplete` of `current-password`, `new-password` or `one-time-code`)
10
+ reports only the lengths of the two values, for example
11
+ `expected ‹hidden, 12 chars›, got ‹hidden, 32 chars›`. The same fields are
12
+ no longer read by the grounding capture, and show as `‹hidden, N chars›` in
13
+ a failure's page HTML and in a fill recorded by the viewer. MCP replies now
14
+ mask registered secrets as `‹secret:NAME›`, as the session journal already
15
+ did: text, structured content and tool error messages.
16
+
17
+ **What to check if you ran 0.43.0 or earlier.** The value of a password or
18
+ one-time-code field, and the value of a secret from `unotest/.secrets`, could
19
+ appear in plain text in MCP tool replies (for example `assert_text`,
20
+ `check_locator`, `assert_value` and the `get_failure_*` tools), in the text
21
+ of an `assertValue` failure, and in the `page.html` and `failure.json` saved
22
+ with a failed run. Search your MCP client's transcripts and your saved run
23
+ failures for your secrets and credentials; if one is there, rotate it.
24
+
25
+ ## [0.43.0] - 2026-09-27
26
+
3
27
  ## [0.42.0] - 2026-09-24
4
28
 
5
29
  ## [0.41.0] - 2026-09-21
@@ -514,11 +514,18 @@ function captureRawTree(h) {
514
514
  }
515
515
  return h.cap(phrase);
516
516
  }
517
+ const SECRET_AUTOCOMPLETE = ["current-password", "new-password", "one-time-code"];
518
+ function isSecretField(el) {
519
+ if ((el.getAttribute("type") ?? "").trim().toLowerCase() === "password") return true;
520
+ const tokens = (el.getAttribute("autocomplete") ?? "").toLowerCase().split(/\s+/);
521
+ return tokens.some((token) => SECRET_AUTOCOMPLETE.includes(token));
522
+ }
517
523
  function controlValue(el) {
518
524
  const tag = el.tagName.toLowerCase();
525
+ if ((tag === "input" || tag === "textarea") && isSecretField(el)) return void 0;
519
526
  if (tag === "input") {
520
527
  const t = (el.type || "text").toLowerCase();
521
- if (t === "checkbox" || t === "radio" || t === "button" || t === "submit" || t === "reset" || t === "image" || t === "password" || t === "hidden") {
528
+ if (t === "checkbox" || t === "radio" || t === "button" || t === "submit" || t === "reset" || t === "image" || t === "hidden") {
522
529
  return void 0;
523
530
  }
524
531
  const v = h.trim(el.value);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unotest/grounder-client",
3
- "version": "0.42.0",
3
+ "version": "0.43.1",
4
4
  "description": "Client contract for the unotest semantic UI grounder: typed intent/resolution types, the injectable DOM walker (RawCapture), the content hash, and the HTTP client + wire protocol of the grounding service. The grounding engine itself is a private service; this package is everything a consumer needs to capture a page and talk to it.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {