Skip to content

fix(workflows): escape remaining untrusted fields in workflow info#3731

Open
Noor-ul-ain001 wants to merge 2 commits into
github:mainfrom
Noor-ul-ain001:fix/workflow-info-escape-fields
Open

fix(workflows): escape remaining untrusted fields in workflow info#3731
Noor-ul-ain001 wants to merge 2 commits into
github:mainfrom
Noor-ul-ain001:fix/workflow-info-escape-fields

Conversation

@Noor-ul-ain001

Copy link
Copy Markdown
Contributor

Problem

Follow-up to #3690, which escaped only the step-graph brackets in workflow info. Every other metadata field the command prints is untrusted content (from workflow.yml or catalog JSON), and console.print has Rich markup enabled — so an unescaped [...] in any of them is parsed as a style tag and silently swallowed.

Affected fields:

  • definition path: name, version, author, description, integration, and each input's name/type
  • catalog path: name, version, description, tags, and the '<id>' not found error id

Concretely, a description of Does [stuff] nicely rendered as Does nicely; an integration of claude [code] rendered as claude ; an input type of str [ing] rendered as str .

Fix

Route every field through _escape_markup (already imported and used by the sibling workflow list and catalog search commands), so bracketed text renders literally. This is the same defect and the same remedy as #3690, extended to the rest of the command.

Tests

Two regression tests added to TestWorkflowInfoStepGraph, covering the definition path and the catalog path. Both fail on the pre-fix source (bracketed fields come back truncated) and pass with the fix. Verified via git stash test-the-test.

tests/test_workflows.py::TestWorkflowInfoStepGraph  3 passed

🤖 Generated with Claude Code

Follow-up to github#3690, which escaped only the step-graph brackets. Every
other metadata field `workflow info` prints is untrusted content
(workflow.yml or catalog JSON), and console.print has Rich markup
enabled, so an unescaped `[...]` in any of them is parsed as a style tag
and silently swallowed:

- definition path: name, version, author, description, integration, and
  each input's name/type
- catalog path: name, version, description, tags, and the "not found"
  workflow id

A description of `Does [stuff] nicely` rendered as `Does  nicely`; an
integration of `claude [code]` rendered as `claude `. Route every field
through _escape_markup, matching the sibling `workflow list` / catalog
`search` commands, so bracketed text renders literally.

Add two regression tests covering the definition and catalog paths; both
fail on the pre-fix source (fields with brackets come back truncated).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI 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.

Pull request overview

Escapes untrusted workflow metadata before Rich rendering to preserve bracketed content.

Changes:

  • Escapes definition, catalog, input, tag, and error fields.
  • Adds definition- and catalog-path regression tests.
Show a summary per file
File Description
src/specify_cli/workflows/_commands.py Escapes workflow-info output fields.
tests/test_workflows.py Tests bracketed metadata rendering.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

tests/test_workflows.py:7993

  • The catalog-path test likewise uses a plain version and has no version assertion, leaving the new escape at _commands.py:2418 uncovered. Make the fixture version contain brackets and assert that literal version in the rendered output.
                "name": "Cat [WF]",
                "version": "2.0.0",
                "description": "From [catalog]",
                "tags": ["a [b]", "c [d]"],
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread tests/test_workflows.py
Comment on lines +7947 to +7950
name="My [WF]",
id="my-wf",
version="1.0.0",
author="Jane [Doe]",
Comment on lines +2426 to +2428
console.print(
f"[red]Error:[/red] Workflow '{_escape_markup(str(workflow_id))}' not found"
)
@mnriem

mnriem commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Please address Copilot feedback

Addresses Copilot review feedback on the workflow-info markup-escape
tests:

- The definition-path and catalog-path regression tests left `version`
  bracket-free and never asserted it, so the version escapes could be
  removed without failing. Use bracketed version values and assert they
  survive verbatim.
- The newly escaped not-found identifier is a separate output path that
  no test reached. Add a case where local load raises FileNotFoundError
  and catalog lookup returns None, invoke `workflow info` with a
  bracketed ID, and assert the literal ID is preserved in the error.

Verified each new assertion fails when its source escape is removed
(test-the-test).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Noor-ul-ain001

Copy link
Copy Markdown
Contributor Author

Addressed both Copilot points in 0069726:

  1. Version field never asserted (test_definition_metadata_fields_escaped, test_catalog_metadata_fields_escaped): both tests now use a bracketed version (1.0.0 [beta] / 2.0.0 [rc]) and assert the exact value survives in the output, so the version escapes at _commands.py L2367/L2418 are now covered.

  2. Not-found identifier path uncovered: added test_not_found_id_escaped, which makes local load raise FileNotFoundError and the catalog lookup return None, invokes workflow info with a bracketed ID (ghost [wf]), and asserts the literal ID is preserved in the "not found" error — covering the escape at L2427.

Verified each new assertion fails when its source escape is removed (test-the-test).

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants