Skip to content

feat(agents): issue-992-p1-workflow-parameters-are-interpolated - #1812

Merged
mashkovd merged 1 commit into
mainfrom
feat/agents-issue-992-p1-workflow-parameters-are-interpolated
Oct 11, 2026
Merged

mashkovd merged 1 commit into
mainfrom
feat/agents-issue-992-p1-workflow-parameters-are-interpolated

Conversation

@mctl-agents

@mctl-agents mctl-agents Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Implements accepted proposal mctl-gitops/issue-992-p1-workflow-parameters-are-interpolated.

Spec: https://github.com/mctlhq/mctl-gitops/tree/main/platform-gitops/agents-state/mctl-gitops/proposals/issue-992-p1-workflow-parameters-are-interpolated/

Generated by mctl-agents Tier 2 implementer. Review carefully — this PR was opened automatically and the spec may have gaps.

Refs #992


Scope note (operator): this PR is the first slice of #992 (proposal tasks 1-5: injection test harness, tpl-validate-tenant, tpl-git-commit, tpl-vault-write, assert-attempt). Still open on #992: task 6 (wft-smoke-test), task 7 (create/delete/deploy/provision/retire sites), task 8 (validator ratchet becomes a ban), task 10 (live smoke). The API-side follow-up from task 9 is mctlhq/mctl-api#559. #992 stays open.

Proposal: platform-gitops/agents-state/mctl-gitops/proposals/issue-992-p1-workflow-parameters-are-interpolated/

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@mctl-agents
mctl-agents Bot requested a review from mashkovd as a code owner October 11, 2026 16:38
@claude

claude Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Claude finished @mctl-agents[bot]'s task in 6m 11s —— View job


Reviewing PR #1812

  • Fetch context and diff (git diff 2189c29f...06b87eba1)
  • Analyze Argo Workflow template changes (tpl-git-commit, tpl-validate-tenant, tpl-vault-write, assert-attempt in the 4 cwft-mctl-agents-* files)
  • Analyze validation script changes (scripts/validate-shell-param-interpolation.py baseline shrink)
  • Analyze test coverage (new tests/test_shell_param_injection.py, updated tests/test_tpl_git_commit_yq.py)
  • Post findings / verdict

Summary

This converts the remaining {{inputs.parameters.X}} direct interpolations into env: bindings read as "$PARAM_X", closing the shell-injection class tracked in #992 for tpl-git-commit, tpl-validate-tenant, tpl-vault-write, and the assert-attempt template in all four cwft-mctl-agents-* files.

Verified:

  • The heredocs switched from quoted (<< 'ENVEOF', literal param text embedded) to unquoted (<<ENVEOF, body is just $PARAM_X). This is safe: a heredoc's terminator is matched against the literal script text at parse time, before the $PARAM_X parameter expansion happens — so a value containing a line like ENVEOF can no longer truncate the heredoc early.
  • Every $PARAM_* read in a script has a matching env: entry in that same template (no missing bindings across any of the 7 edited templates).
  • tpl-vault-write.yaml's write-platform-secret adds a case guard rejecting empty/absolute/../non-allowlisted-char vault_path values before they reach the Vault URL, and json_data is now piped to curl via stdin (--data-binary @-) instead of spliced into the command line.
  • New test tests/test_shell_param_injection.py extracts each template's real prelude/loop text and runs quote-breakout, $()/backtick, and terminator-line payloads against it, plus a control case proving the harness actually detects injection on the old (pre-fix) shape.
  • test_tpl_git_commit_yq.py gained a case (5b) proving a terminator-line value in env_vars is treated as data, not shell.

One P3 posted inline (non-blocking): the new vault_path guard in tpl-vault-write.yaml allows /-sequences like a//b or a trailing / through (not an injection — / is intentionally allowlisted — just a minor hygiene nit).

No P1/P2 findings. Approved.

@github-actions

Copy link
Copy Markdown

Antigravity (agy) review — informational

Model: gemini-3.8-flash-medium · commit 06b87eb.

No significant issues found.

HTTP_CODE=$(curl -sS -o /tmp/vault-write.json -w "%{http_code}" \
# vault_path lands in a URL: reject anything but a plain relative path.
case "$PARAM_VAULT_PATH" in
""|/*|*..*|*[!A-Za-z0-9/_-]*)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: the *..* / char-class guard rejects path traversal and shell/URL metacharacters, but still accepts a leading/embedded/trailing / sequence like a//b or a/. Not an injection (the character / is in the allowlist by design, since vault_path is itself a sub-path), just a minor hygiene gap — Vault will likely just normalize it, but consider also rejecting //* or a leading/trailing / if that matters for the secret/data/${PARAM_VAULT_PATH} URL this feeds.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No P1/P2 findings (1 P3). Converts the remaining direct {{inputs.parameters.X}} interpolations in tpl-git-commit/tpl-validate-tenant/tpl-vault-write and the assert-attempt templates to env-var bindings read as "$PARAM_X" — closing the shell-injection class tracked in #992. Verified: unquoted heredocs (<<ENVEOF etc.) still can't be terminator-injected because the shell matches the delimiter against the literal script text before parameter expansion runs, every $PARAM_* read has a matching env: entry, the new vault_path case-guard correctly blocks empty/absolute/traversal/non-allowlisted-char paths before it reaches the Vault URL, and json_data now goes through curl via stdin instead of being spliced into the command line. Test coverage (tests/test_shell_param_injection.py, plus the terminator-line case added to test_tpl_git_commit_yq.py) exercises quote-breakout, $()/backtick, and terminator-line payloads against the actual extracted template prelude/loop text, with a control case proving the harness detects injection on the old shape. Good to merge.

@mctl-claude-remote mctl-claude-remote Bot added steward:ready-to-merge pr-steward: clean+green, awaiting human merge steward:owned pr-steward owns this PR labels Oct 11, 2026
@mashkovd
mashkovd merged commit 5faf9aa into main Oct 11, 2026
36 checks passed
@mashkovd
mashkovd deleted the feat/agents-issue-992-p1-workflow-parameters-are-interpolated branch October 11, 2026 17:36
mashkovd added a commit that referenced this pull request Oct 11, 2026
The merge with main left validate with two env keys: main's PARAM_*
bindings from #1812 and the branch's PARAM_CONTAINER_REGISTRY. YAML
keeps only the last one, so every PARAM_* read by the script was unset.
One env list now holds all ten bindings (yamllint key-duplicates and
validate-shell-param-interpolation both pass).

Claude-Session: https://claude.ai/code/session_012TfVcukEh7ry8MiLNN89N4
mashkovd added a commit that referenced this pull request Oct 11, 2026
Three cases passed without executing a single parameter read: their
prelude ran `apk add` first, which exits 127 off-cluster, so `set -e`
stopped before the first PARAM_* line and the canary could never appear.
The review flagged cleanup-db-from-gitops; write-service-secrets and
delete-service-secrets from #1812 had the same shape.

Each case now runs once with valid values and must reach a sentinel at
the end of its prelude, and the payload runs render the source the way
Argo does, so a placeholder put back into the script trips the canary
rather than only the static check. A missing jq fails instead of
skipping. validate-local-workdir's smoke check now asserts the jq form
of provision_database, and the ban's docstring states its scope.

Refs #1836

Claude-Session: https://claude.ai/code/session_01XgvCTQf5obEJr8NyKp73jC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

steward:owned pr-steward owns this PR steward:ready-to-merge pr-steward: clean+green, awaiting human merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant