Skip to content

fix(workflows): require consent before loading custom steps - #5182

Open
mnriem wants to merge 4 commits into
github:mainfrom
mnriem:mnriem-workflow-step-trust
Open

mnriem wants to merge 4 commits into
github:mainfrom
mnriem:mnriem-workflow-step-trust

Conversation

@mnriem

@mnriem mnriem commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator

Description

Require explicit, per-invocation consent before importing project custom workflow step Python. Discovered packages and project installation records no longer implicitly authorize execution.

Interactive commands prompt with a default of No; --trust-steps explicitly authorizes all custom step packages for the current invocation, including unattended use. This applies to workflow add, update, run, and resume. Approval is not persisted, and projects without custom steps need no approval.

Preserve JSON failure reporting, add regression coverage, and document the trust boundary and option.

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest
  • Tested with a sample project (if applicable)

Actual commands used the worktree-local environment as recommended in CONTRIBUTING.md:

Command Result
uv sync --extra test --quiet Passed
uv run --no-sync specify --help Passed
LC_ALL=en_US.UTF-8 .venv/bin/python -m pytest tests -q -n 4 Passed: 13,697 passed, 130 skipped, 63 warnings

Sample-project coverage was automated through temporary CLI test projects, covering approval, refusal, noninteractive invocation, explicit opt-in, and JSON output. No manual human testing is claimed.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (fill in the disclosure below)

AI disclosure: Authored with GitHub Copilot using GPT-6.1 Sol, default configured reasoning settings, and autonomous agent execution under user-directed scope. Assistance included code, test, documentation, and PR-text generation, plus automated validation. The initial assessment also used a security-review subagent whose model was not reported.

Require per-invocation approval before importing project custom step code. Prompt interactively or accept --trust-steps for workflow add, update, run, and resume, without persisting approval.

Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI auto review requested due to automatic review settings October 29, 2026 14:26

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.

🟡 Changes recommended

Unattended bundle operations fail in projects with custom steps because required consent cannot be passed through, and a warning assertion is vulnerable to Rich line wrapping.

2 open issues
What changed in this PR

Adds an explicit trust boundary before Spec Kit imports project custom workflow-step Python. Discovered packages and installation records no longer imply permission to execute code.

Changes:

  • Adds per-invocation --trust-steps and default-No interactive approval for workflow add, update, run, and resume.
  • Preserves JSON failure reporting and prevents approval reuse.
  • Adds consent regression coverage and updates trust documentation.

Validation was limited to source inspection; tests and before/after comparisons were not run.

AI assistance: GitHub Copilot for the requesting reviewer; model/settings unavailable; autonomous code review.

File Description
tests/​test_workflows.py Explicitly authorizes existing custom-step loading tests.
tests/​specify_cli/​workflows/​test_custom_steps.py Tests refusal, import prevention, and approval isolation.
tests/​specify_cli/​workflows/​test_command_update.py Tests update consent and explicit opt-in.
tests/​specify_cli/​workflows/​test_command_run.py Tests prompts, refusal, JSON output, and approval reuse prevention.
tests/​specify_cli/​workflows/​test_command_resume.py Tests resume consent and state preservation on refusal.
tests/​specify_cli/​workflows/​test_command_add.py Tests consent before workflow installation.
tests/​specify_cli/​workflows/​step/​test_command_add.py Adds explicit trust to installation-and-execution tests.
tests/​specify_cli/​workflows/​helpers.py Adds stdin controls and an observable import probe.
src/​specify_cli/​workflows/​command_update.py Adds the trust option and consent preflight.
src/​specify_cli/​workflows/​command_run.py Requires consent before loading custom steps.
src/​specify_cli/​workflows/​command_resume.py Requires renewed consent before resuming.
src/​specify_cli/​workflows/​command_add.py Threads consent through workflow installation preflight.
src/​specify_cli/​workflows/​_commands.py Centralizes prompting and refusal handling.
src/​specify_cli/​workflows/​__init__.py Makes custom-step imports default-deny.
docs/​reference/​workflows.md Documents trust options, scope, and JSON behavior.
design/​workflow-step.md Defines the per-invocation consent contract.

Review effort: Max (auto)

cli._validate_workflow_id_or_exit(source)
load_custom_steps(project_root)
try:
cli._load_custom_steps(project_root, trust_steps=trust_steps)
Comment thread tests/specify_cli/workflows/test_command_run.py Outdated
@mnriem mnriem added the triage-must-have Verdict: high-value, important work for Spec Kit — do first label Oct 29, 2026
Expose --trust-steps on bundle add, install, update, and init and forward it through bundled and catalog workflow delegates without granting implicit approval. Cover refusal and opt-in for both sources, and normalize wrapped warning assertions with narrow-console regression coverage.

Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI auto review requested due to automatic review settings October 29, 2026 15: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.

🔵 Needs a closer look

Bundle-wide trust approval is not reused by later workflow delegates, causing repeated prompts whose refusal or end of input can fail the bundle and roll back newly installed components.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Reuse bundle-local trust approval across workflow delegates

src/​specify_cli/​bundles/​primitives.py:546

For a bundle with multiple workflows, accepting “Trust all custom workflow step code for this invocation?” still leaves later delegates receiving False, so they prompt again. A later refusal or end of input fails the bundle and can roll back newly installed components. Carry approval in bundle-invocation-local state and reuse it for both workflow delegate paths (also line 574), without carrying it into later commands.

1 resolved since last review

Review effort: Max (auto)

Share interactive custom-step approval across workflow delegates through invocation-local, project-scoped installer state. Keep consent collection separate from imports, require renewed approval for later commands, and cover mixed bundled/catalog workflows, refusal, and installer isolation.

Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI auto review requested due to automatic review settings October 29, 2026 16:25

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.

🟡 Changes recommended

Both workflow delegates re-resolve relative SPECIFY_INIT_DIR after changing directories, allowing a nested project's custom Python to be imported using approval granted to a different project.

2 open issues

Review effort: Max (auto)

Comment thread src/specify_cli/bundles/primitives.py
Canonicalize workflow manager roots and pin SPECIFY_INIT_DIR to the selected absolute root during delegated commands, restoring the caller's override and working directory afterward. Cover nested-project imports for bundled and catalog workflows, explicit and interactive consent, and relative manager roots.

Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI auto review requested due to automatic review settings October 29, 2026 16: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.

🔵 Needs a closer look

Human assessment is needed because multi-bundle updates can reuse prior approval to import newly installed step-package code without renewed user consent.

1 open issue
1 resolved since last review

Review effort: Max (auto)

This branch has not been deployed

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

Labels

triage-must-have Verdict: high-value, important work for Spec Kit — do first

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants