Skip to content

🐛 fix(sanitize): recognize ECMA-48 control strings - #419

Merged
hivecommons-hive[bot] merged 2 commits into
hivecommons:mainfrom
Karibhou:fix/418-terminal-conformance
Oct 29, 2026
Merged

hivecommons-hive[bot] merged 2 commits into
hivecommons:mainfrom
Karibhou:fix/418-terminal-conformance

Conversation

@Karibhou

Copy link
Copy Markdown
Contributor

Summary

Recognize 8-bit ST and the 7-bit and 8-bit CSI and control-string forms, preserving text between terminated strings. Add a generated ECMA-48 grammar-state corpus that checks removal and surrounding text, including the reported watcher evasion.

Fixes #418

Validation

  • npm run lint, npm run build, and node --test dist/sanitize.test.js passed.
  • npm test: 435 passed, one unrelated home-directory path test failed (expected one custom excuse, got two).
  • TMPDIR=/tmp npm run test:coverage was interrupted after it stalled in the local environment; CI will run the coverage gate.

— hive: backend=codex

Hive-Run: hivecommons#418
Hive-Plan: ECMA-48 conformance gate
Hive-Spec: issue-418#conformance
Signed-off-by: Karibhou <157208370+Karibhou@users.noreply.github.com>
@kubestellar-prow kubestellar-prow Bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Oct 29, 2026
@kubestellar-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign kellyaa for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubestellar-prow kubestellar-prow Bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Oct 29, 2026

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Read src/sanitize.ts at 0e6501b and ran the new recogniser against the reproduction from #418: "\x1b]0;title\x9c I cannot run the tests \x1b]2;x\x07 tail" now yields " I cannot run the tests tail" (text between the two terminated strings preserved), and the 8-bit CSI \x9b1;2m is removed by the rule at src/sanitize.ts:50. The terminator advance at src/sanitize.ts:14 (start[0].length instead of the hard-coded 2) is what makes the single-byte C1 introducers safe — a \x9d followed directly by \x9c would otherwise have skipped past its own terminator. Looks correct to me.

One behaviour change to be aware of, not a defect (src/sanitize.ts:7,47): DCS (ESC P) was previously terminated only by ST (\x1bP[^\x1b]*\x1b\\); it now shares the BEL/ST/8-bit-ST terminator set. So ESC P …BEL keep ESC \ used to drop keep, and now prints it as plain text (escape bytes still stripped). That is the lenient direction for both trust boundaries — more text reaches the watcher matcher, and nothing unescaped reaches the terminal — so I think it is fine, just noting it since the CHANGELOG line does not mention it.

Test corpus in src/sanitize.test.ts:148-176 is generated independently of the recognisers and covers the three terminators for all ten string introducers, which is the gate #418 asked for.

— hive: agent=reviewer-2 backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks correct to me.

Read src/sanitize.ts at the PR head and both callers (src/watcher.ts:302, src/cli.ts:229), and ran the suite locally: the new "ECMA-48 conformance corpus" block fails 2 tests against main's sanitize.ts and passes with this change, so the test does gate the fix. The #418 reproduction (\x1b]0;title\x9c … \x1b]2;x\x07 tail) is covered by the second new test.

What I checked in replaceControlStrings:

  • terminator.lastIndex = start.index + start[0].length (src/sanitize.ts:14) replaces the hard-coded + 2, which is what makes the single-byte C1 introducers (\x90 \x98 \x9d \x9e \x9f) safe — with + 2 a C1 introducer immediately followed by a terminator byte would have skipped over it.
  • Merging OSC/DCS/APC/PM/SOS into one pass (src/sanitize.ts:47) is what fixes the swallow: terminators are now consumed in input order, so an 8-bit-ST-closed string can no longer run to a later BEL.
  • The "unterminated → break" early-exit remains valid since all introducers now share one terminator set.

One behaviour change worth knowing, not a defect: DCS/SOS were previously ST-only (\x1bP[^\x1b]*\x1b\\); they now also end at BEL and may span embedded ESC bytes. That is the more conservative direction for the watcher (less text hidden on an early BEL, and a stray ESC [ … inside a DCS payload no longer splits the string), so I think it is the right call.

Docblock at src/sanitize.ts:33-36 still lists only OSC/CSI/DCS; a mention of SOS/PM/APC and the 8-bit forms would keep it current. Suggestion only.

— hive: agent=reviewer backend=copilot model=claude-fable-5.1 copilot=1.0.88

Signed-off-by: Karibhou <157208370+Karibhou@users.noreply.github.com>
@Karibhou

Copy link
Copy Markdown
Contributor Author

Updated the docblock in bdae07d to cover SOS, PM, APC, the 8-bit forms, and the shared BEL/ST terminators. Thanks for noting the documentation gap and the DCS/SOS behavior change. — hive: backend=codex

@hivecommons-hive

Copy link
Copy Markdown
Contributor

stage 060-reviewed → 050-review-pending: contributor-lane:claim-tier-untrusted

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed — no findings from this perspective.

— hive: agent=adjudicator-3 backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed — no findings from this perspective.

— hive: agent=adjudicator backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed — no findings from this perspective.

— hive: agent=adjudicator-2 backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed — no findings from this perspective.

— hive: agent=adjudicator-4 backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed — no findings from this perspective.

— hive: agent=reviewer backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Ready for a human merge: verdict approved @bdae07d, 10/10 checks green, DCO yes, soak 30m0s elapsed. Blocked only by role/contributor (below require_tiers).

The hive never approves on your behalf: /lgtm /approve (or merge) if you accept it.

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Mutation check (quality) — ran Stryker scoped to src/sanitize.ts (runner: node --test dist/sanitize.test.js) at main@10e3012 and at this PR's head bdae07d.

rev mutants killed survived score
main@10e3012 47 41 (+3 timeout) 3 93.6%
pr#419bdae07d 47 41 (+3 timeout) 2 95.7%
  • The mutant this PR newly kills is the + on the nF intermediate run (/\x1b[ -/]+[0-~]/ → /\x1b[ -/][0-~]/), which was unpinned on main after 🐛 fix(sanitize): strip nF intermediate-byte ESC sequences #417. The ' /' entry in the escIntermediate corpus state pins it — so merging this closes a real gap, and I am not opening a separate test PR for it.
  • The two remaining survivors are both on the charset rule /\x1b[()][A-Z0-9]/ ([^()], [^A-Z0-9]). They are equivalent mutants, not test gaps: (/) are 0x28/0x29, inside the nF intermediate range [ -/], so the 🐛 fix(sanitize): strip nF intermediate-byte ESC sequences #417 nF rule already strips every ESC ( X form and the charset arm is shadowed. Not a blocker; a follow-up could drop the redundant arm (production change, outside my lane).

No findings against this PR.


🐝 Hive Agent: quality | Instance: hosted-available-oke-11-placeholder-r05x | SHA: bdae07d

— hive: agent=quality backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved by @clubanderson for Hive auto-merge on green CI.

Approved from the Hive dashboard by @clubanderson as the owner decision on a Ready-for-human-merge pull request; the hive's merge sweep merges it on green CI.

@kubestellar-prow

Copy link
Copy Markdown

@hivecommons-hive[bot]: changing LGTM is restricted to collaborators

Details

In response to this:

Approved by @clubanderson for Hive auto-merge on green CI.

Approved from the Hive dashboard by @clubanderson as the owner decision on a Ready-for-human-merge pull request; the hive's merge sweep merges it on green CI.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@hivecommons-hive hivecommons-hive Bot added the lgtm Indicates that a PR is ready to be merged. label Oct 29, 2026
@hivecommons-hive

Copy link
Copy Markdown
Contributor

Hive queued this PR but could not set the prow/lgtm commit status, so Prow may strip the lgtm label and the auto-merge queue may not hold.

@hivecommons-hive
hivecommons-hive Bot merged commit 0cd4566 into hivecommons:main Oct 29, 2026
14 of 15 checks passed
@hivecommons-hive

Copy link
Copy Markdown
Contributor
Evidence bundle `#419bdae07d` sha256:30feb3535d5feb49a495980d9cb23dea3f22a323eb2fe6deb27e2d28f984adc4 — download from the dashboard or `hivectl review evidence #419`.

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Merged by hive contributor-lane auto-merge: CI green for ≥30m, reviewer verdict approve, @clubanderson approved this head as the owner decision (admitted_by: operator-approval:clubanderson) — merged as-is on that approval.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has signed the DCO. lgtm Indicates that a PR is ready to be merged. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[scanner] Gate proposal: ECMA-48 conformance test for stripTerminalEscapes (3rd recogniser gap: 8-bit ST U+009C over-strips)

1 participant