fix(triage-panel): add DIFC read-integrity exemption for external issues#1462
Conversation
The triage-panel workflow's write-class safe-outputs (add-comment, add-labels, remove-labels, assign-milestone, dispatch-workflow) cause gh-aw's DIFC policy to elevate the minimum integrity for MCP reads to HIGH. Issues filed by external contributors are assigned LOW integrity by DIFC, so search_issues and get_issue silently drop them -- making the triage panel blind to external contributor issues. Changes: - Add difc: read-integrity: low in the workflow frontmatter so MCP reads accept LOW-integrity content (external contributor issues). - Switch OPT_IN_RETRIAGE and MANUAL_DISPATCH from unauthenticated gh CLI bash commands to MCP get_issue/list_issue_comments calls, which are authenticated via the gh-aw runtime and now visible under the DIFC exemption. - Correct the SCHEDULED_SWEEP commentary that incorrectly claimed search_issues sidesteps DIFC filtering (it does not). - Add DIFC note explaining the exemption and its safety rationale. Fixes #1344 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes the triage-panel gh-aw workflow being unable to triage issues authored by external contributors due to DIFC read-integrity filtering, and removes reliance on an unauthenticated gh CLI in the agent sandbox.
Changes:
- Adds a workflow-level DIFC exemption (
difc: read-integrity: low) so MCP reads can see LOW-integrity issues even when write-classsafe-outputsare enabled. - Updates SCHEDULED_SWEEP guidance to correctly describe DIFC behavior and the rationale for using
search_issues. - Switches OPT_IN_RETRIAGE and MANUAL_DISPATCH Step 1 reads from
gh issue viewto MCPget_issue/list_issue_comments.
APM Review Panel:
|
| Persona | B | R | N | Takeaway |
|---|---|---|---|---|
| Python Architect | 0 | 0 | 2 | DIFC read-integrity exemption is architecturally sound; frontmatter-prompt consistency is maintained; MCP tool migration eliminates an unauthenticated shell path. Ship. |
| CLI Logging Expert | 0 | 0 | 0 | No CLI output paths touched; triage-panel prompt-body wording uses ASCII bullet/code-block conventions already. |
| DevX UX Expert | 0 | 0 | 1 | Fix restores the contributor-facing triage promise for external issues; no ergonomic regressions. Ship. |
| Supply Chain Security Expert | 0 | 1 | 1 | DIFC read-integrity exemption is justified by defense-in-depth rails (BATCH_ALLOW_LIST, label allow-list, body-size cap, spam filter). No blocking exploit chain found. One hardening recommendation on assign-milestone. |
| OSS Growth Hacker | 0 | 1 | 1 | Contributor-funnel fix unblocks triage for external issues; recommend amplifying in CHANGELOG and crediting the external author. |
| Doc Writer | 0 | 2 | 2 | Prose is accurate and internally consistent; two stale gh issue view references in the apm-triage-panel SKILL.md now drift from the workflow's MCP-based reads. |
B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.
Top 5 follow-ups
- [Doc Writer] Update SKILL.md line 295: replace
gh issue view --jsonwith MCPget_issue/list_issue_commentsto match the workflow. -- Direct contradiction between workflow and skill prose; reader cross-referencing gets a wrong mental model. Same class of silent drift this PR eliminates elsewhere. - [Doc Writer] Update SKILL.md line 322: switch duplicate-check instruction from
gh issue view N --jsonto MCPget_issue. -- Workflow now states gh is unauthenticated in the agent sandbox; the skill still tells the agent to shell out to gh. Either the duplicate-check is broken at runtime or the workflow statement is overstated. - [Supply Chain Security Expert] Add an
allowedlist to the assign-milestone safe-output (or document accepted risk in an inline comment). -- Under read-integrity:low, attacker-controlled body could influence milestone via prompt injection. Impact is low (milestones are human-ratified) but parity with add-labels would close the gap. - [OSS Growth Hacker] CHANGELOG entry crediting @sergio-sisternes-epam with the contributor-funnel narrative angle. -- Adoption signal: external contributor fixing external-contributor experience is a story worth amplifying in release notes.
- [Python Architect] Add explicit MCP call code block to MANUAL_DISPATCH section (mirroring OPT_IN_RETRIAGE) instead of prose cross-reference. -- Agents are literal readers; duplicated fenced block is more robust than 'same as above, substituting...' at runtime.
Architecture
classDiagram
direction LR
class GhAwRuntime {
<<Runtime>>
+evaluate_frontmatter()
+enforce_difc_policy()
+dispatch_mcp_call()
}
class DIFCPolicy {
<<Policy>>
+read_integrity_floor str
+elevate_for_write_class()
+apply_exemption(level)
}
class SafeOutputs {
<<AllowList>>
+add_comment
+add_labels
+remove_labels
+assign_milestone
+dispatch_workflow
}
class MCPReadGate {
<<Gate>>
+filter_by_integrity(issue, floor)
+search_issues(query)
+get_issue(number)
+list_issue_comments(number)
}
class TriagePanelWorkflow {
<<Workflow>>
+SCHEDULED_SWEEP
+OPT_IN_RETRIAGE
+MANUAL_DISPATCH
}
class Issue {
<<Entity>>
+integrity str
+author_affiliation str
}
GhAwRuntime *-- DIFCPolicy : enforces
GhAwRuntime *-- SafeOutputs : gates writes
GhAwRuntime *-- MCPReadGate : gates reads
DIFCPolicy ..> SafeOutputs : write-class elevates read floor
MCPReadGate ..> Issue : filters by integrity
TriagePanelWorkflow ..> MCPReadGate : calls search_issues / get_issue
TriagePanelWorkflow ..> SafeOutputs : declares allowed writes
class DIFCPolicy:::touched
class TriagePanelWorkflow:::touched
classDef touched fill:#fff3b0,stroke:#d47600
flowchart TD
A["Trigger: schedule / issues.labeled / workflow_dispatch"] --> B{Mode selection}
B -->|schedule| C["SCHEDULED_SWEEP"]
B -->|issues event| D["OPT_IN_RETRIAGE"]
B -->|workflow_dispatch + issue_number| E["MANUAL_DISPATCH"]
C --> F["MCP search_issues<br/>query: repo:microsoft/apm is:open -label:status/triaged sort:created-asc"]
D --> G["MCP get_issue<br/>issue_number: github.event.issue.number"]
D --> H["MCP list_issue_comments<br/>issue_number: github.event.issue.number"]
E --> I["MCP get_issue<br/>issue_number: inputs.issue_number"]
E --> J["MCP list_issue_comments<br/>issue_number: inputs.issue_number"]
subgraph DIFC["gh-aw DIFC layer"]
direction TB
K{"difc.read-integrity == low?"}
K -->|yes| L["Pass LOW-integrity issues through"]
K -->|no| M["Drop LOW-integrity issues silently"]
end
F --> DIFC
G --> DIFC
H --> DIFC
I --> DIFC
J --> DIFC
L --> N["Step 2: Run triage panel classification"]
N --> O["Step 3: Apply decisions via safe-outputs"]
O --> P["add-comment / add-labels / remove-labels / assign-milestone"]
O --> Q["dispatch-workflow: project-sync"]
Recommendation
Merge as-is. Zero blocking findings, narrow scope, well-rationalized threat model, and it unblocks 9 silently-dropped external-contributor issues today. File a follow-up issue for the two SKILL.md drift lines (295, 322) -- they are the highest-signal post-merge action and should land before the next scheduled triage sweep so the agent does not hit the stale gh issue view instruction at runtime. Remove status/needs-design from #1344 on merge; the design question is answered by the panel's security and architecture confirmation.
Full per-persona findings
Python Architect
- [nit] Design patterns note for architectural record at
.github/workflows/triage-panel.md
Straight-line procedural workflow prose; no OO patterns apply to a gh-aw natural-language workflow file. No abstraction would reduce complexity further. - [nit] MANUAL_DISPATCH section could show the substituted MCP call explicitly (like OPT_IN_RETRIAGE does) to reduce ambiguity for the agent at runtime at
.github/workflows/triage-panel.md:405
OPT_IN_RETRIAGE includes a fenced code block with the literal get_issue and list_issue_comments calls. MANUAL_DISPATCH says 'Same MCP calls ... (substituting ...)'. Agents are literal readers; a duplicated fenced block with ${{ inputs.issue_number }} would be more robust than a prose cross-reference.
Suggested: Add an explicit fenced code block mirroring the OPT_IN_RETRIAGE calls with ${{ inputs.issue_number }} substituted.
CLI Logging Expert
No findings.
DevX UX Expert
- [nit] MANUAL_DISPATCH section lost the inline get_issue/list_issue_comments code blocks at
.github/workflows/triage-panel.md:402
OPT_IN_RETRIAGE now has explicit MCP call examples that a future workflow maintainer can copy-paste. MANUAL_DISPATCH says 'Same MCP calls as OPT_IN_RETRIAGE' with no inline snippet.
Suggested: Add a brief inline example or markdown anchor link.
Supply Chain Security Expert
- [recommended] assign-milestone safe-output lacks an allow-list unlike add-labels -- attacker-controlled body can influence milestone string at
.github/workflows/triage-panel.md
add-labels uses a strictallowedenumeration. assign-milestone has no equivalentallowedconstraint. Under read-integrity:low, an attacker who controls the issue body could craft prompt-injection to coerce a misleading milestone assignment. Impact LOW: milestones are human-ratified, verdict comment makes assignment visible, only existing milestones can be assigned.
Suggested: Add anallowedlist to assign-milestone safe-output, or document accepted risk. - [nit] DIFC rationale comment should name the BATCH_ALLOW_LIST as the primary compensating control at
.github/workflows/triage-panel.md
BATCH_ALLOW_LIST is computed BEFORE body ingestion and is the strongest structural defense against cross-issue write amplification.
Suggested: Append clause (d) BATCH_ALLOW_LIST is computed before body ingestion, preventing cross-issue write amplification via prompt injection.
OSS Growth Hacker
- [recommended] Credit the external contributor explicitly in CHANGELOG and release notes for this fix.
An external contributor fixing the very mechanism that silenced external contributors is a powerful authenticity signal. The story angle is inherently shareable.
Suggested: CHANGELOG: 'fix(triage): external contributor issues are now triaged instead of silently dropped by DIFC read-integrity gate (thanks @sergio-sisternes-epam, fixes [BUG] triage-panel skips external contributor issues due to DIFC integrity policy #1344)'. - [nit] Consider a CONTRIBUTING.md note that the triage panel processes all issues regardless of author org membership.
Sets expectations for new external contributors.
Auth Expert -- inactive
Only .github/workflows/triage-panel.md (a gh-aw workflow prompt) is touched; no AuthResolver, token_manager, or host-classification surface is changed.
Doc Writer
- [recommended] SKILL.md line 295 still tells the skill the orchestrating workflow fetches issue context via
gh issue view --json; after this PR the workflow uses MCPget_issue+list_issue_comments. at.apm/skills/apm-triage-panel/SKILL.md:295
Drift between the workflow (now MCP) and the skill prose that documents how the workflow hands context to the skill. Reader cross-referencing the two files will get a contradictory mental model -- exactly the kind of silent drift this PR set out to remove.
Suggested: Replacegh issue view --jsonwithget_issue/list_issue_comments(MCP), matching the new OPT_IN_RETRIAGE/MANUAL_DISPATCH wording. - [recommended] SKILL.md line 322 instructs the skill to verify a duplicate candidate with
gh issue view N --json state,title, but the workflow's new prose explicitly saysghis not authenticated in the agent sandbox. at.apm/skills/apm-triage-panel/SKILL.md:322
Direct contradiction introduced by the PR: workflow says gh is unauthenticated, skill still tells the agent to shell out to gh. Either the duplicate-check step is broken at runtime or the workflow statement is too strong.
Suggested: Switch duplicate verification to MCPget_issue(owner, repo, issue_number: N). - [nit] The SCHEDULED_SWEEP 'DIFC note' duplicates the safety rationale already in the frontmatter comment. at
.github/workflows/triage-panel.md:311
Non-bloat / state-once principle.
Suggested: Collapse the 8-line DIFC note to a 2-line pointer. - [nit] Voice tighten-up in SCHEDULED_SWEEP intro parenthetical. at
.github/workflows/triage-panel.md:293
'authenticated via the gh-aw runtime; thedifc: read-integrity: lowexemption ensures external contributor issues are not filtered' reads slower than its terse neighbors.
Suggested: Drop the 'authenticated via the gh-aw runtime' clause.
Test Coverage Expert -- inactive
Documentation-only PR -- no src/**/*.py touched; workflow-prompt-only change to .github/workflows/triage-panel.md, no runtime code paths to defend.
This panel is advisory. It does not block merge. Re-apply the panel-review label after addressing feedback to re-run.
…d content_id source - Distinguish search_issues (silent drop) from get_issue (McpError: MCP error 0: [Filtered]) in the DIFC read-integrity frontmatter comment so readers understand the explicit vs silent failure modes. - Replace stale reference to 'gh issue list/view --json id' as the source of the dispatch-workflow content_id with the correct MCP search_issues/get_issue response, consistent with the rest of the workflow which uses MCP reads throughout. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
APM Review Panel:
|
| Persona | B | R | N | Takeaway |
|---|---|---|---|---|
| Python Architect | 0 | 1 | 1 | Architecturally correct fix; MCP call blocks hard-code owner/repo -- use template variables. |
| CLI Logging Expert | 0 | 1 | 2 | No CLI output regressions; add candidate-count logging in SCHEDULED_SWEEP so silent DIFC regressions are detectable. |
| DevX UX Expert | 0 | 2 | 2 | Correctness fix with good prose; silent-drop fix is itself silent -- emit a DIFC-active notice, and replace hardcoded org/repo. |
| Supply Chain Security Expert | 0 | 2 | 2 | DIFC lowering is operationally justified; dispatch_workflow input validation and explicit posture trade-off statement both warrant follow-up. |
| OSS Growth Hacker | 0 | 1 | 1 | Fixing silent issue-drop is a high-leverage contributor funnel repair -- add a CHANGELOG entry. |
| Auth Expert | 0 | 1 | 2 | Exemption is architecturally appropriate; add-comment has no content allow-list; cross-reference injection rail enforcement to the skill file. |
| Doc Writer | 0 | 1 | 2 | DIFC explanations are well-written; restore mid-page pagination-reliability nuance in SCHEDULED_SWEEP. |
B = blocking-severity findings, R = recommended, N = nits.
Counts are signal strength, not gates. The maintainer ships.
Top 5 follow-ups
- [Python Architect + DevX UX Expert] Replace hardcoded
owner: "microsoft", repo: "apm"in OPT_IN_RETRIAGE MCP call blocks with${{ github.repository_owner }}and${{ github.event.repository.name }}template variables -- two panelists independently flagged this; any fork or mirror silently triages the wrong repository; the fix is one-line and the pattern is already used in adjacent blocks. - [Supply Chain Security + Auth Expert] Add an explicit sentence to the
difc:block acknowledging that prompt-level injection rails are LLM-evaluated and weaker than system-level DIFC enforcement, and that the exemption accepts this residual risk in exchange for external-contributor triage coverage -- future editors who remove prompt rails without realizing they are the sole injection barrier will have no written signal that the exemption's security model depends on those rails. - [OSS Growth Hacker] Add a CHANGELOG entry:
fix(triage): external contributor issues were silently dropped by the triage panel due to DIFC integrity filtering; they are now triaged correctly-- the fix is internal in implementation but external in effect; a one-line entry signals the project monitors and repairs its contributor funnel. - [Doc Writer] Restore pagination-reliability nuance in SCHEDULED_SWEEP:
client-side, which is wasteful and unreliable -- DIFC can silently drop non-org-member results mid-page, making "is the next page worth fetching?" reasoning unsound-- the removed sentence carried the precise technical reasonsearch_issuesis structurally superior tolist_issues, not merely faster. - [Auth Expert] Add a cross-reference in the
difc:comment block pointing to the specific skill file and section where body-size caps and BATCH_ALLOW_LIST injection rails are enforced -- if a future edit to the skill removes those rails, this workflow's DIFC exemption loses its stated defence without any warning.
Architecture
classDiagram
direction TB
class TriagePanelWorkflow {
<<WorkflowOrchestrator>>
+mode: SCHEDULED_SWEEP|OPT_IN_RETRIAGE|MANUAL_DISPATCH
+difc_read_integrity: low
+timeout_minutes: 30
+run()
}
class DIFCPolicy {
<<SecurityGateway>>
+write_class_outputs: list
+read_integrity_floor: HIGH|LOW
+filter(content, integrity) bool
}
class SafeOutputsAllowList {
<<WriteGate>>
+add_comment()
+add_labels()
+remove_labels()
+assign_milestone()
+dispatch_workflow()
}
class MCPGitHubServer {
<<IOBoundary>>
+search_issues(query, sort, per_page) list
+get_issue(owner, repo, issue_number) Issue
+list_issue_comments(owner, repo, issue_number) list
}
class ApmTriagePanelSkill {
<<Strategy>>
+run(issue) TriageVerdict
}
class TriageVerdict {
<<ValueObject>>
+labels: list
+milestone: str
+comment: str
}
class TriagePanelWorkflow:::touched
TriagePanelWorkflow *-- SafeOutputsAllowList : write-gated by
TriagePanelWorkflow ..> DIFCPolicy : exempts read-integrity via frontmatter
TriagePanelWorkflow ..> MCPGitHubServer : reads issues via
TriagePanelWorkflow *-- ApmTriagePanelSkill : delegates classification
DIFCPolicy ..> MCPGitHubServer : filters responses
ApmTriagePanelSkill ..> TriageVerdict : produces
SafeOutputsAllowList ..> MCPGitHubServer : writes back via
classDef touched fill:#fff3b0,stroke:#d47600
flowchart TD
A(["Trigger: issues/labeled OR schedule OR workflow_dispatch"]) --> B["Mode selection"]
B -->|"label=status/needs-triage"| C["OPT_IN_RETRIAGE\n[MCP] get_issue + list_issue_comments"]
B -->|"workflow_dispatch"| D["MANUAL_DISPATCH\n[MCP] get_issue + list_issue_comments"]
B -->|"schedule"| E["SCHEDULED_SWEEP\n[MCP] search_issues(sort:created-asc, per_page:30)"]
C --> I["Run apm-triage-panel skill"]
D --> I
E --> H["Apply quota filter, cap to 10"] --> I
I --> J{"TriageVerdict?"}
J -->|yes| K["safe-outputs: add-comment"]
J -->|"empty"| L["Exit cleanly"]
K --> M["safe-outputs: add-labels / remove-labels / assign-milestone"]
M --> O["safe-outputs: dispatch-workflow project-sync (conditional)"]
subgraph DIFC ["DIFC Policy Layer"]
P["Write-class outputs detected\n- normally elevate read-integrity to HIGH"]
Q["difc: read-integrity: low\n- exemption: accept LOW-integrity MCP reads"]
P -. overridden by .-> Q
end
C & D & E -.-> DIFC
DIFC -.->|"External contributor issues now visible"| C & D & E
sequenceDiagram
participant GHEvent as GitHub Event
participant Workflow as triage-panel.md
participant DIFC as gh-aw DIFC
participant MCP as GitHub MCP Server
participant Skill as apm-triage-panel skill
participant SafeOut as safe-outputs
GHEvent->>Workflow: trigger (label / schedule / dispatch)
Workflow->>DIFC: frontmatter difc: read-integrity: low
Note over DIFC: Exemption registered -- LOW-integrity MCP reads permitted
Workflow->>MCP: get_issue / search_issues (authenticated)
MCP-->>DIFC: response with LOW-integrity external issue
DIFC-->>Workflow: passes through (exemption active)
Workflow->>MCP: list_issue_comments
MCP-->>Workflow: comment history
Workflow->>Skill: run panel (issue + comments)
Skill-->>Workflow: TriageVerdict
Workflow->>SafeOut: add-comment (triage verdict)
SafeOut-->>Workflow: comment posted
Workflow->>SafeOut: add-labels / assign-milestone
SafeOut-->>Workflow: labels and milestone applied
Recommendation
This PR fixes a real and significant bug: external contributor issues were silently invisible to the triage panel, which is among the highest-churn contributor experience failures possible. The fix is correct, the DIFC exemption is architecturally sound, and all active panelists agree on the approach. The MCP migration is a net improvement. Nothing in the panel findings warrants holding this change. The five follow-ups above are improvements to portability, security posture transparency, contributor communication, documentation precision, and governance traceability -- all of which can ship as follow-on PRs without holding the core fix. The maintainer should prioritize the hardcoded org/repo fix (follow-up 1) and the explicit posture trade-off statement (follow-up 2) in the next iteration, as both are low-effort and close real gaps. The CHANGELOG entry (follow-up 3) should ideally land in the same release window to capture the contributor-retention signal while the fix is fresh.
Full per-persona findings
Python Architect
-
[recommended] MCP call blocks hard-code owner/repo instead of using workflow template variables at
.github/workflows/triage-panel.md:378
The newget_issueandlist_issue_commentsblocks in OPT_IN_RETRIAGE hard-codeowner: "microsoft", repo: "apm". If this workflow is replicated to a fork or mirror org, these strings will silently route the agent to the upstream org's issue tracker. The existing${{ github.event.issue.number }}template variables in the same blocks show the pattern is available.
Suggested: Replace withowner: "${{ github.repository_owner }}", repo: "${{ github.event.repository.name }}"in both MCP call blocks. -
[nit] Frontmatter comment says
get_issuefails with McpError but PR body says it silently drops -- minor inconsistency at.github/workflows/triage-panel.md:210
The distinction (silent drop vs. explicit McpError) is meaningful for future debuggability. The comment is more precise and should be preserved; the PR body prose is just looser.
CLI Logging Expert
-
[recommended] No operator-visible signal when DIFC previously silently dropped external issues
If gh-aw's DIFC policy changes in future,search_issueswill again silently return a subset of issues with no McpError, no warning, no count discrepancy visible in workflow logs. Operators have no baseline to diff against.
Suggested: Add an observability note in SCHEDULED_SWEEP instructing the agent to log the count of candidates returned bysearch_issuesso operators can spot a sudden drop to org-member-only counts in workflow logs. -
[nit] DIFC note in SCHEDULED_SWEEP is repeated verbatim concept from frontmatter comment
Creates a two-source-of-truth risk: a future editor updating one may miss the other.
Suggested: Collapse the inline DIFC note to a single forward-reference sentence pointing to the frontmatter block. -
[nit] Line length inconsistency in the PGS dispatch paragraph
Cosmetic inconsistency introduced by the edit. Wrap at ~100 chars to match surrounding prose style.
DevX UX Expert
-
[recommended] Silent-drop fix is itself silent -- no triage output signals that external-contributor issues are now visible
If the exemption is ever accidentally removed or misconfigured, regressions will again be invisible. A one-line notice confirmingdifc: read-integrity: lowis active would make the behavior auditable.
Suggested: Add a Step 0 or preamble instructing the agent to emit a single notice line confirming DIFC read-integrity: low is active before the sweep begins. -
[recommended] MCP pseudo-code hardcodes
owner: "microsoft"/repo: "apm"instead of using template variables
Any fork or mirror will silently triage the wrong repository.
Suggested: Replace with${{ github.repository_owner }}and${{ github.event.repository.name }}. -
[nit] DIFC frontmatter block is accurate but opaque to contributors who don't know what DIFC is
No link to DIFC documentation or PRINCIPLES.md. -
[nit] Long line in Step 2 prose exceeds ~100-char wrap used elsewhere
Cosmetic inconsistency.
Supply Chain Security Expert
-
[recommended]
dispatch_workflowis the highest-risk write surface downstream of LOW-integrity input; no system-level guard verifies the dispatchedcontent_idmatches the triggering issue
An adversarial external issue body can attempt prompt injection to steer the agent into passing an unintended node ID todispatch_workflow. In-prompt rails are LLM-evaluated and fail open. Ifproject-synccan move or modify project board items for arbitrary node IDs, a crafted issue body could trigger board manipulation.
Suggested: Audit whatproject-syncdoes with an arbitrarycontent_id. If possible, add a system-level assertion that thecontent_iddispatched must match the node ID returned by the authenticated MCP call for the triggering issue number. -
[recommended] Safety rationale labels in-prompt controls as equivalent to DIFC enforcement; they are not -- this should be acknowledged as a deliberate posture downgrade
DIFC enforcement is system-level and model-blind; prompt-level rails are LLM-evaluated and fail open against sophisticated adversarial payloads.
Suggested: Add:Note: prompt-level injection rails are LLM-evaluated and weaker than DIFC system enforcement. This exemption accepts that residual risk in exchange for triage coverage of external issues. -
[nit]
add-commentwrite action could indirectly echo attacker-influenced classification reasoning into org-visible triage comments
Low severity: attacker gains mislabeling, not code execution. -
[nit]
gh issue view-> MCPget_issuemigration is a net security improvement and the rationale should say so explicitly
Authenticated reads, consistent with the pipeline, no risk of CLI resolving a different token from the environment.
OSS Growth Hacker
-
[recommended] Add a CHANGELOG entry explicitly calling out the external-contributor fix
Silent triage drops are invisible to contributors -- they file an issue, hear nothing, and churn.
Suggested:fix(triage): external contributor issues were silently dropped by the triage panel due to DIFC integrity filtering; they are now triaged correctly. -
[nit] Consider a pinned note on Discussions or social acknowledging the fix for affected contributors
Contributors who filed issues in the affected window and got no response may have written off the project.
Auth Expert
-
[recommended]
add-commenthas no content allow-list, creating a prompt-injection surface via LOW-integrity issue bodies
The safe-outputs block constrains label names via an explicit allow-list and caps comment count (max:12), but does NOT restrict comment text content. The claim that the panel never re-emits raw body text is a prompt instruction, not a runtime enforcement boundary.
Suggested: Add a post-generation reminder in the agent prompt that triage comments MUST be entirely generated from the panel's own analysis, or document the accepted risk in the difc: block. -
[nit] The
unauthenticated gh CLI -> authenticated MCPimprovement is correct but overstated for public repos
Public issues are readable without auth; the MCP path is genuinely better (rate-limit headroom, pipeline consistency) but the framing slightly oversells the risk.
Suggested: Rephrase to note unauthenticated rate-limit (60/hr) vs. gh-aw runtime token. -
[nit] Body-size cap and BATCH_ALLOW_LIST prompt-injection rails referenced in the safety rationale are not visible in this diff
If a future edit to the skill removes those rails, this workflow's DIFC exemption loses its stated defence without any warning.
Suggested: Add a cross-reference in the difc: comment block pointing to the specific skill file and section where those rails are enforced.
Doc Writer
-
[recommended] SCHEDULED_SWEEP loses the specific insight that mid-page DIFC drops make
list_issuespagination unreliable, not just wasteful
The removed sentence carried the precise technical reason whysearch_issuesis structurally superior -- not just slower but semantically broken under DIFC. The replacement 'wasteful and error-prone' is vague.
Suggested: Restore:client-side, which is wasteful and unreliable -- DIFC can silently drop non-org-member results mid-page, making "is the next page worth fetching?" reasoning unsound. -
[nit] MANUAL_DISPATCH cross-reference (
Same MCP calls as OPT_IN_RETRIAGE) is correct and sufficient -- no action needed
PROSE's Orchestrated Composition principle favours cross-references over repetition. -
[nit] CHANGELOG not updated, but this is acceptable for an internal workflow-only fix
No CLI command, config key, or user-facing behavior changed. A CHANGELOG entry is optional unless the team logs internal workflow fixes -- see the OSS Growth Hacker finding for the counter-argument.
Test Coverage Expert -- inactive
documentation-only PR -- no runtime code paths to defend
This panel is advisory. It does not block merge. Re-apply the
panel-review label after addressing feedback to re-run.
Generated by PR Review Panel for issue #1462 · ● 1.9M · ◷
Problem
The triage-panel workflow's write-class safe-outputs (add-comment, add-labels, remove-labels, assign-milestone, dispatch-workflow) cause gh-aw's DIFC policy to elevate the minimum integrity for MCP reads to HIGH. Issues filed by external contributors (non-org-members) are assigned LOW integrity by DIFC, so
search_issuesandget_issuesilently drop them -- making the triage panel blind to the exact issues it exists to triage.Additionally, OPT_IN_RETRIAGE and MANUAL_DISPATCH modes used
gh issue viewbash commands, but theghCLI is not authenticated in the agent sandbox, so those paths also failed for external contributor issues.Fix
DIFC exemption: Added
difc: read-integrity: lowin the workflow frontmatter. This tells the gh-aw runtime to accept LOW-integrity content in MCP reads despite the write-class safe-outputs. Safety is maintained because (a) the panel only reads issue content for classification, (b) prompt-injection rails are enforced in the prompt, and (c) write actions remain gated by safe-outputs allow-lists.MCP-based reads: Switched OPT_IN_RETRIAGE and MANUAL_DISPATCH from unauthenticated
gh issue viewbash commands to MCPget_issue/list_issue_commentstool calls, which are authenticated via the gh-aw runtime and now work correctly under the DIFC exemption.Corrected DIFC commentary: Fixed the SCHEDULED_SWEEP section that incorrectly claimed
search_issuessidesteps DIFC filtering (it does not -- MCP reads are uniformly subject to DIFC regardless of the underlying API).Fixes #1344