Skip to content

Gate: quoted gate output in a decisions.md body is parsed as a live finding #306

Description

@piwi3910

What happens

A decision in .procoder/ask/decisions.md whose body quotes gate output (for example as an indented code block) is read back by the commit hook as a live finding. In azrtydxb/novamem a decision section contained:

Every commit in this repo currently fails:

    BLOCKING toml 4.1.1 has 2 known vulnerability(s), max severity 8.2 — upgrade it (security)

From then on every commit that staged decisions.md was blocked with BLOCKING toml 4.1.1 has 2 known vulnerability(s)…. procoder security reported 0 blocking and no manifest in the repo contained toml 4.1.1. It looked intermittent because it appeared only when decisions.md was staged (the ask collector runs in the change-scoped hygiene pass).

Repro (procoder 3.7.0)

  1. .procoder/config.toml with [ask] / policy = "block" (or any other blocking finding, so the gate exits non-zero).
  2. .procoder/ask/decisions.md with a ## heading whose body contains BLOCKING toml 4.1.1 has 2 known vulnerability(s) ... (security).
  3. Stage it and feed {"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"git commit -m x"},"cwd":"<repo>"} to procoder hook pre-tool-use, or run procoder check .procoder/ask/decisions.md.

The deny reason lists three blocking findings; the third is BLOCKING toml 4.1.1 has 2 known vulnerability(s)…, which no check produced.

Cause

internal/ask/gate.go GateFindings builds each finding's Message as q.Text + " (ask)". For a decision, q.Text is the heading plus the whole multi-line body (decisionQuestions). The gate prints a finding as one mark file message line, so the message's embedded newlines become extra output lines. internal/hook/commit.go blockingLines then scans the gate output line by line and keeps any line whose trimmed text starts with BLOCKING , UNCHECKED or unformatted . A quoted body line starting with one of those prefixes is indistinguishable from a real finding.

Impact

A recorded decision can block every commit that touches it with a phantom finding no tool can reproduce or clear; the only way out is hand-editing the decision text. The same applies to UNCHECKED and unformatted lines, and to any consumer that parses gate output line by line.

Expected

Text from a decision body can never be parsed as a gate finding: a finding is exactly one output line.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions