Skip to content

fix(workflows): reject non-JSON constants in from_json - #5250

Merged
mnriem merged 1 commit into
github:mainfrom
mschoi0411:fix/reject-non-json-constants
Nov 5, 2026
Merged

mnriem merged 1 commit into
github:mainfrom
mschoi0411:fix/reject-non-json-constants

Conversation

@mschoi0411

Copy link
Copy Markdown

Description

from_json promises an error for invalid JSON, but Python's default decoder accepts the bare tokens NaN, Infinity, and -Infinity. These are not JSON numbers (RFC 8259, section 6). They can reach workflow conditions or downstream shell-step environment values instead of failing conversion.

In a local workflow run with VALUE: "value={{ inputs.payload | from_json }}", each of the three tokens currently produces exit code 0 and runs the consumer with nan, inf, or -inf. With this change, the run exits 1 with from_json: invalid JSON constant: ... and the consumer is not executed.

Pass a rejecting parse_constant callback to json.loads. This covers constants at the root and inside arrays/objects while preserving quoted text such as "NaN", ordinary numbers, booleans and null. Document the boundary explicitly. Previously accepted Python-only numeric constants now raise; numeric range/precision behavior is unchanged.

Testing

  • Tested locally with uv run specify --help

  • Ran existing tests using this checkout's .venv/bin/python after uv sync --extra test

  • Tested with a sample project (local workflow CLI, no model or remote service)

  • New regression cases on unmodified main at ec9a6f3b94c0aa856f77e550785a1ddde1993de1: 12 failed, 9 passed, with no collection errors.

  • .venv/bin/python -m pytest tests/test_workflows.py -q: 882 passed after the fix.

  • .venv/bin/python -m pytest tests -n 4 -q: 13,936 passed, 440 skipped (0 failures; 63 warnings).

  • Five CLI cases: all three invalid constants stop before the consumer runs; quoted "NaN" and true still complete successfully.

  • CI-pinned uvx ruff@0.15.0 check src tests, Markdownlint on the changed documentation, the configured pre-commit hooks for the changed files, and git diff --check: passed.

An earlier --maxfail=1 full run stopped after 13,758 passes and 440 skips on the unchanged TestInitStep::test_failed_init_surfaces_inits_own_message, whose captured output contained catalog-fetch HTTP 403 warnings. That test passed when run alone on this branch, and all 16 TestInitStep tests passed on the unmodified base through an isolated import path. Without further code changes, the complete full-suite rerun passed with the result reported above; it included the previously failing test.

No slash-command templates or scaffolding behavior changed; the affected manual path is the workflow CLI.

Validation environment: Linux, Python 3.12.14. Other OS/Python matrix combinations were not run locally.

Test selection reasoning

Changed file Affects Test Why
src/specify_cli/workflows/expressions/filters.py specify workflow run expression conversion T1, T2, T3 Check root/nested inputs, conditions and actual CLI execution
tests/test_workflows.py Expression regression coverage T1, T3 Pin rejected constants and accepted JSON values
docs/workflows/expressions.md Workflow author guidance T4 Keep documented conversion behavior aligned

Required tests

  • T1: Expression regressions and the workflow test file, including positive and negative cases.
  • T2: Fresh local sample projects through specify workflow run <file> --input payload=<value> --json; check the exit code and whether the consumer created its marker.
  • T3: Full test suite in this checkout's virtual environment.
  • T4: CLI help, CI-pinned Ruff, changed-document Markdownlint and applicable pre-commit hooks.

@mschoi0411 requested this bug-fix contribution and reviewed the explanation before approving submission; Codex (GPT-6, autonomous mode; reasoning-effort setting unavailable) selected and diagnosed the bug, wrote the fix, tests, documentation and this PR description, and ran the automated validation.

Assisted-by: Codex (model: GPT-6, autonomous)
@mschoi0411
mschoi0411 requested a review from mnriem as a code owner November 5, 2026 09:53
Copilot AI auto review requested due to automatic review settings November 5, 2026 09:53

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.

🟢 Approval recommended

No active review issues were identified for the change rejecting non-JSON numeric constants in from_json.

No open issues 🎉

What changed in this PR

This PR tightens the workflow expression filter from_json to reject Python-only numeric constants while preserving valid JSON values and existing numeric range behavior.

Changes:

  • Reject bare NaN, Infinity, and -Infinity, including inside arrays and objects.
  • Add regression coverage for rejected constants, workflow conditions, and accepted JSON values.
  • Document the distinction between bare constants and valid quoted strings.

The PR reports before-and-after regression evidence and a passing full test suite; these results were not independently rerun.

File Description
tests/​test_workflows.py Adds rejection and valid-input regression tests.
src/​specify_cli/​workflows/​expressions/​filters.py Adds a rejecting parse_constant callback to JSON decoding.
docs/​workflows/​expressions.md Documents non-JSON constant rejection and quoted-string acceptance.

Review effort: Balanced (auto)

@mnriem mnriem added the triage-can-wait Verdict: valid and in-scope but deprioritized; held behind the evidence gate label Nov 5, 2026
@mnriem
mnriem requested an auto review from Copilot November 5, 2026 13:52

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.

🟢 Approval recommended

No active review issues were identified for the change rejecting non-JSON numeric constants in from_json.

No open issues 🎉

Review effort: Balanced (auto)

@mnriem

mnriem commented Nov 5, 2026

Copy link
Copy Markdown
Collaborator

Thank you!

@mnriem
mnriem merged commit ede2c68 into github:main Nov 5, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage-can-wait Verdict: valid and in-scope but deprioritized; held behind the evidence gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants