fix(bundle): escape Rich markup in bundle CLI error and status output - #4023
Open
Noor-ul-ain001 wants to merge 1 commit into
Open
fix(bundle): escape Rich markup in bundle CLI error and status output#4023Noor-ul-ain001 wants to merge 1 commit into
Noor-ul-ain001 wants to merge 1 commit into
Conversation
`specify bundle`'s `_fail` helper interpolated its message straight into
`err_console.print`, which has Rich markup enabled. Every caller passes
`str(exc)` from a `BundlerError`, and those messages embed untrusted data
-- including the command's own argument -- so a `[...]` in it was parsed
as a style tag.
Balanced tags were silently swallowed; an unbalanced closer raised
`MarkupError`, which replaced the error message with a traceback and left
the output completely empty. Three commands crashed on user input alone,
with no project state required:
specify bundle catalog add 'ssh://ex[/red]ample.com/c.json'
specify bundle catalog remove 'no[/red]such'
specify bundle update 'no[/red]such'
`bundle validate` had the same failure on both branches: its errors echo
`requires.speckit_version`, and its warnings echo component ids, which are
not charset-validated -- so a structurally *valid* manifest crashed on the
success path too.
Fixed centrally in `_fail`, plus the remaining raw interpolations: the
`validate` warning/error/success lines, the install overlap and plan
warnings, the install/update/remove/catalog-add confirmations, the
`catalog list` id/url, and the `bundle init` project path.
Regression tests cover the four crashing error paths (parametrized) and
both `validate` branches; all six fail without this change.
Assisted-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
specify bundle's_failhelper interpolated its message straight intoerr_console.print, which has Rich markup enabled:All 13 call sites pass
str(exc)from aBundlerError, and those ~109 messages embed untrusted data — a catalog url, abundle.ymlfield, or the command's own CLI argument. A[...]in that data is parsed as a style tag.Balanced tags are silently swallowed. An unbalanced closer raises
MarkupError, which replaces the error message with an uncaught traceback and leaves the output completely empty. Three commands crash on user input alone, with no project state or catalog required:Each exits 1 having printed nothing at all, instead of the intended message (e.g.
Error: Bundle 'no[/red]such' is not installed.).bundle validatehad the same failure on both branches — its errors echorequires.speckit_version, and its warnings echo component ids, which are not charset-validated. So a structurally valid manifest crashed on the success path just as readily as an invalid one.Fix
Escaped centrally in
_fail, which covers all 13 error paths at once, plus the remaining raw interpolations in status output:bundle validate— warning, error, and success linesbundle install— overlap list and plan warnings (line 403 printed the sameoverlapvalues that thebundle infopath at line 301 already escaped — a sibling-branch asymmetry)catalog addconfirmationscatalog listsource id and urlbundle initproject path (directory names may legally contain brackets)Left intentionally unescaped:
_trust_badge()(deliberate markup) and the hardcoded{kind}loop labels.Testing
Six regression tests in
tests/contract/test_bundle_cli.py— a parametrized case per crashing error path, plus bothvalidatebranches. All six fail without this change (verified by reverting the source file and re-running):With the fix,
tests/contract/test_bundle_cli.pyis 40/40 green, andtests/contract tests/integration tests/unitgives 362 passed. The 5 remaining failures are all*_refuses_symlinked_*tests that need symlink-creation privileges on Windows; they fail identically on an unmodified checkout.ruff checkis clean.Related
Continues the markup-escaping work in #3458, #3690, #3731, #3738, #3774 (which escaped this module's discovery output —
search/info— but not the error or status paths), #3826, and #3879.🤖 Generated with Claude Code