Skip to content

fix(#1835): require file reads before asserting contents in findings#70

Open
guyoron1 wants to merge 196 commits into
mainfrom
mirror/2443-1835-verify-file-contents-before-asserting
Open

fix(#1835): require file reads before asserting contents in findings#70
guyoron1 wants to merge 196 commits into
mainfrom
mirror/2443-1835-verify-file-contents-before-asserting

Conversation

@guyoron1

Copy link
Copy Markdown
Owner

Mirror of upstream fullsend-ai#2443

Ensures file contents are read and verified before asserting their contents in findings.

Benkapner and others added 30 commits June 7, 2026 09:54
Add a new subsection under "CI pipeline for agent configurations"
elaborating on Step 1 (static analysis). Covers component-level
checks (structural integrity, security patterns, token budget),
setup-level analysis (redundancy detection, dependency validation,
token budget distribution, trigger overlap, dimension scoring),
and optional LLM-based rubric scoring. Presents similarity
techniques as options (TF-IDF, embeddings, LLM-based) rather
than prescribing a single approach. Adds three open questions
on thresholds, lint rule universality, and token budgets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Benjamin Kapner <bkapner@redhat.com>
Introduce --vendor to install vendored binaries, reusable workflows,
actions, and agent content. Vendored upstream mirror content is committed
under .defaults/ (same layout as runtime sparse checkout); layered installs
fetch fullsend-ai/fullsend@v0 into .defaults when the marker file is absent.

Reusable workflows use inline workspace preparation and reference infra
from ./.defaults/, matching the pre-vendor layered design. Thin callers
render local reusable paths when --vendor is set.

--fullsend-source pins the source tree for both content and binary
cross-compile; --fullsend-binary remains an explicit ELF override.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Write vendor-manifest.yaml on --vendor installs so cleanup and analyze work
without a local fullsend checkout. Workflows analyze stays embed-only;
vendor layer reports presence, manifest alignment, and optional source
alignment via admin analyze --fullsend-source.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Consolidate thin-stage caller registry, reuse resolved source root for
binary vendoring, reject oversized tar members during extraction, restore
workflows scope comment, fix testing-workflows prose, and introduce
InstallFiles as the canonical collector return type.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Re-add the full download_test.go suite and append extractSourceTree size
limit coverage.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Delete vendored paths atomically via forge.DeleteFiles, reuse resolved
source root for cross-compile, preserve extracted file modes, and tighten
WouldFix deduplication to exact path matches.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Document intentional breaking change: old flag callers should use --vendor;
only known usage was e2e, already updated in this branch.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Document VendorBinaryLayer legacy naming, restore Uninstall/Analyze
comments, and use Title Case for stale-cleanup progress messages.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Batch binary, content, and manifest in one CommitFiles call; validate
manifest version on read; trim leading slash in extractSourceTree; wrap
DeleteFiles ref PATCH in retryOnTransient.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Use the existing blob mode from the recursive tree and set type blob
so deletion entries match GitHub Trees API expectations.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Guard against regressions in delete-entry construction per review.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	internal/forge/fake.go
#	internal/forge/forge.go

Signed-off-by: Barak Korren <bkorren@redhat.com>
Encode CommitFiles tree entries as base64 to preserve ELF binaries,
add tar extract containment check, consolidate stale cleanup with a
manifest/binary quick-check, and deduplicate cleanup between CLI and layer.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	action.yml
#	docs/guides/dev/testing-workflows.md

Signed-off-by: Barak Korren <bkorren@redhat.com>
Clarify removed distribution-mode artifacts, drop e2e vendor line, and
document action.yml source-build fallback.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Empty commit to re-dispatch review; prior synchronize dispatch was cancelled.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Keep enumerateVendoredPaths aligned with CollectVendoredAssets after
main added the composite action (fullsend-ai#2106); fixes CI parity test.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…t dispatch

GitHub Actions may return 422 when repo-maintenance is dispatched immediately
after a separate vendor CommitFiles on a fresh .fullsend repo. Merge scaffold
and vendored assets into one atomic commit and retry dispatch on indexing lag.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…nance

Poll GitHub until repo-maintenance.yml is active before dispatch, re-touch
config.yaml after scaffold so the push trigger can run enrollment when
dispatch is still rejected, and fall back to awaiting a push-triggered run.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…nary

Tree entries with encoding:base64 stored base64 text literally on GitHub,
corrupting YAML workflows and vendor-manifest.yaml. Restore UTF-8 inline
content for text and upload binary via the Git Blob API instead.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Design for a new `prerequisites` triage action that replaces `blocked`.
The agent can now express both existing blockers and new issues that need
to be created upstream before progress can happen. Includes allowlist
configuration for cross-repo issue creation and a degraded path when
targets are not authorized.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
…nd-ai#401)

Seven-task plan covering config structs, JSON schema, agent prompt,
post-script, user docs, and caller updates. TDD approach with exact
file paths and code blocks.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
Add CreateIssuesConfig and AllowTargets types to both OrgConfig and
PerRepoConfig. NewOrgConfig populates defaults with the org and
fullsend-ai/fullsend. NewPerRepoConfig populates with the target repo
and fullsend-ai/fullsend.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
…ues (fullsend-ai#401)

Pass org name and target repo to config constructors so create_issues
defaults are populated at install time.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
)

Replace the blocked action and blocked_by field with a prerequisites
action containing existing[] and create[] arrays. At least one array
must be non-empty.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
…pt (fullsend-ai#401)

The triage agent can now recommend creating upstream issues via the
prerequisites action's create array, in addition to referencing existing
blockers. Adds hard constraint against emitting sufficient when
prerequisites exist.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
…d-ai#401)

Update triage agent docs to explain the new prerequisites action and the
create_issues.allow_targets configuration surface.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
…#401)

Replace the blocked handler with prerequisites. The post-script reads
the create_issues allowlist from config.yaml, creates permitted upstream
issues via gh, and includes collapsed draft bodies for disallowed or
failed creates so humans can file them manually.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
…ullsend-ai#401)

The agent prompt referenced a nonexistent `prerequisites` label when
checking for prior blockers — the post-script actually applies the
`blocked` label. Also removed unused SOURCE_ORG variable from
post-triage.sh.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
QualityFlow and others added 3 commits June 21, 2026 15:03
…[skip ci]

Resolved all 6 review findings (2 major, 4 minor) in 1 iteration:
- Rewrote requirement summaries to user-story format (D1-R-A-001)
- Checked applicable strategy/review checkboxes (D6-001)
- Improved priority distribution with P2 tier (D3-001)
- Simplified subtitle, condensed overview, added scope acknowledgments

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review

Findings

High

  • [scope-tier-mismatch] — The PR is titled as a fix for Review agent should verify file contents before asserting facts about them fullsend-ai/fullsend#1835 but contains 196 commits and 170 changed files (16,811 additions, 2,303 deletions). The actual fix modifies only 2 files with ~30 lines of changes. The remaining 195 commits are upstream mirror content including vendor/distribution features, triage prerequisites, new ADRs (0047–0050), review agent contextual labels, merge queue features, E2E improvements, OpenShell installation, and many more independent features. This is a bulk upstream synchronization masquerading as a targeted bug fix.
    Remediation: Split into a dedicated fix(#1835) PR containing only the 2-file cross-file verification fix, and a separate chore: PR for the upstream sync. Or retitle to accurately reflect scope (e.g., chore: mirror upstream fullsend-ai/fullsend main including fix for #2443).

  • [secrets exposure / workflow attack surface expansion] .github/workflows/e2e.yml:26 — The diff removes the paths: filter from the pull_request_target trigger, causing the e2e workflow to trigger on ALL pull_request_target events regardless of which files changed. This event is security-sensitive (accesses secrets, id-token: write permission). The file-relevance check is now done at runtime inside the job with secret access, and the gh api call to fetch PR files falls through as fail-open on failure (echo relevant=true >> GITHUB_OUTPUT; exit 0).
    Remediation: Consider keeping a broad paths: filter as a declarative first-pass and refining with the runtime check. If removal is intentional, document the rationale for broadening the trigger surface.

  • [protected-path] — This PR modifies 20 protected files: .github/dependabot.yml (removed), .github/scripts/install-openshell.sh (added), .github/scripts/openshell-version.sh (added), 9 workflow files under .github/workflows/, .pre-commit-config.yaml, AGENTS.md, CLAUDE.md, and 5 files under skills/. The PR has no linked issue and the description does not explain why these governance and infrastructure files are being changed. Human approval is required for all protected-path changes.
    Remediation: Link an issue that authorizes the protected-path changes and explain in the PR description why these files need to be modified.

Medium

  • [curl-pipe-sh remote code execution] .github/scripts/install-openshell.sh:15 — The new script fetches and executes a remote install script via curl | sh. While the commit SHA is pinned, there is no integrity verification (checksum) of the downloaded script content before execution.
    Remediation: Add SHA-256 checksum verification: download to a temporary file, verify the checksum, then execute. This matches the pattern already used in post-code.sh for other tool downloads.

  • [token scope change / authentication model] action.yml:39 — The status-token input is replaced with mint-url, changing the authentication model. If a caller provides status-repo and status-number but not mint-url, orphaned status comments will not be reconciled. The base branch version falls back to GITHUB_TOKEN; the new version has no such fallback.
    Remediation: Ensure all callers have been updated to pass mint-url. Verify no external consumers rely on the status-token input or the GITHUB_TOKEN fallback.

Low

  • [secrets handling] .github/workflows/reusable-retro.yml:148 — The diff removes RETRO_SANDBOX_TOKEN and GH_TOKEN from the env block passed to the retro action. The post-retro.sh script requires GH_TOKEN (${GH_TOKEN:?GH_TOKEN is required}). Verify the mint-url flow provides GH_TOKEN to post-scripts.

Info

  • [protected paths update] internal/scaffold/fullsend-repo/skills/pr-review/SKILL.md:610 — The protected paths list adds Containerfile, Dockerfile, and images/ but the enforcement scripts (post-review.sh, post-fix.sh) do not include these in their REVIEW_PROTECTED_PATHS. Agent-side instruction and enforcement-side list are out of sync.

  • [naming-alignment] internal/scaffold/qf_crossfile_verification_consistency_test.go — Test files use a novel qf_ prefix not documented in project conventions. Other test files use standard Go naming.

  • [architectural-coherence] internal/scaffold/fullsend-repo/skills/code-review/SKILL.md — The cross-file verification fix itself aligns well architecturally. The PR scope prevents comprehensive architectural review of the other 168 files.

  • [path traversal defense] internal/scaffold/vendormanifest.go:99 — The isSafeVendoredRepoPath function correctly validates paths, rejecting empty, absolute, and .. traversal paths.

  • [permission manifest change] .pre-commit-config.yaml:77 — New -ignore rule suppresses actionlint warnings for scaffold template placeholders. Narrowly scoped.

Note: The correctness sub-agent did not complete due to an API overload error (HTTP 529). Correctness evaluation was not performed for this PR.

Previous run

Review

Findings

High

Medium

  • [injection-vuln] internal/scaffold/fullsend-repo/scripts/post-triage.sh:226 — When a label name from untrusted agent output (agent-result.json) fails regex validation, it is interpolated into a GHA workflow command '::warning::' without sanitization for '::' sequences, URL-encoded newlines (%0A/%0D), or control characters. An attacker who controls agent-result.json could inject arbitrary workflow commands.
    Remediation: Sanitize the label variable before interpolating into the workflow command. Strip or escape '::' sequences, '%0A', '%0D', and control characters.
  • [privilege-escalation] images/code/Containerfile:122 — Comment on line 119 states '/sandbox/go/bin is placed AFTER system paths so sandbox-user binaries cannot shadow trusted system tools', but the actual PATH construction may not enforce this ordering correctly. If sandbox-user-writable directories appear before system directories, a malicious binary could shadow trusted tools.
    Remediation: Verify that the PATH variable places /usr/local/bin, /usr/bin, and /usr/sbin before any sandbox-user-writable directories. Add a test or assertion that validates PATH ordering.
  • [logic-error] internal/mintcore/handler.go:76 — NewHandler derives roleSet (and ALLOWED_ROLES) by parsing ROLE_APP_IDS keys containing a slash (org/role format). If the PR migrates ROLE_APP_IDS from 'org/role' to bare 'role' keys, the slash-split logic will fail to extract role names correctly, potentially breaking role validation and token minting.
    Remediation: Verify that the key parsing logic in NewHandler handles both 'org/role' and bare 'role' key formats, or update it to match the new key format exclusively.
  • [error-handling-gap] internal/dispatch/gcf/provisioner.go:951 — In mergeRoleAppIDs, if existing ROLE_APP_IDS JSON is malformed, the function silently returns without error, leaving the desired map unmerged with existing entries. This could cause role configuration drift where expected roles are silently dropped.
    Remediation: Return an error when JSON unmarshaling fails, or at minimum log a warning so operators can detect configuration drift.
  • [stale-doc] docs/agents/triage.md:43 — Documentation references the old triage action 'blocked', which was renamed to 'prerequisites' in this PR. Multiple occurrences in this file (lines 43, 83) describe the old action name.
  • [stale-doc] docs/reference/installation.md:583 — Documentation describes ROLE_APP_IDS keys using the old '{org}/{role}' format, which was changed to just '{role}' in this PR.
  • [stale-doc] docs/guides/infrastructure/mint-administration.md:158 — Documentation shows example ROLE_APP_IDS keys using the old '{org}/{role}' format (e.g., 'acme-corp/coder', 'acme-corp/review'), which was changed to bare role keys in this PR.
  • [stale-doc] internal/scaffold/fullsend-repo/agents/triage.md:68 — Scaffold template references the old 'blocked' label and action in multiple locations (lines 68, 203, 205, 211), which was renamed to 'prerequisites' in this PR. These templates are deployed to consumer repos and would propagate stale terminology.
  • [stale-doc] internal/scaffold/fullsend-repo/skills/issue-labels/SKILL.md:23 — Scaffold template references the old 'blocked' label, which was renamed to 'prerequisites' in this PR.

Low

  • [supply-chain] action.yml:281 — OpenShell installation uses 'curl | sh' pattern. While the commit SHA is pinned, the install script could be modified upstream between audits. The pinned SHA mitigates but does not eliminate supply chain risk.
  • [edge-case] internal/mintcore/handler.go:255 — In ServeHTTP, the JSON response from json.NewEncoder(w).Encode is not checked for errors. If encoding fails (e.g., due to a closed connection), the partial response is silently lost.
  • [test-integrity] internal/mintcore/handler_test.go:718 — In TestHandler_FullFlowGrantedScopeAll, the fakePEMAccessor uses key 'test-org/coder' (org-scoped) while other tests use bare role keys like 'coder'. This inconsistency may mask key format migration issues.

Info

  • [sub-agent-failure] N/A — The style-conventions sub-agent could not access PR branch files (only main branch was available in the sandbox). Style review was not completed for this PR.
Previous run (2)

Review

Reason: stale-head

The review agent reviewed commit 858bd8ca7ce7fc70ab5953322cbfe2d506792b31 but the PR HEAD is now fc4106bf052e7d156e861f931a55fa2520e7052a. This review was discarded to avoid approving unreviewed code.

Previous run (3)

Review

Reason: stale-head

The review agent reviewed commit e99fd5f21f6628b64a4a2735ab44998e8e6b798e but the PR HEAD is now 7f22940b1158c8c7113b279321aa6c7afe777ee9. This review was discarded to avoid approving unreviewed code.

Previous run (4)

Review

Reason: stale-head

The review agent reviewed commit 903478e93a3d7f57b2fa388d9b93f64a02ce1787 but the PR HEAD is now 616fe5f3993b937f856f81ffc41f8dd0d69c932f. This review was discarded to avoid approving unreviewed code.

Previous run (5)

Review

Reason: stale-head

The review agent reviewed commit b11081cd94ded72b69f3c4928556476b64541ce2 but the PR HEAD is now 840b252e7d3df5790e8898db8378113f8fb6c386. This review was discarded to avoid approving unreviewed code.

@fullsend-ai-review

Copy link
Copy Markdown

/fs-review

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 21, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 3:30 PM UTC · Completed 3:45 PM UTC
Commit: 0535520 · View workflow run →

QualityFlow and others added 3 commits June 21, 2026 15:36
…p ci]

- Reviewed STD YAML and Go stubs across 7 dimensions
- Fixed 3 MAJOR findings: removed related_prs from metadata,
  corrected import list (embed->io/fs), added v2.1 fields to all scenarios
- Final verdict: APPROVED (0 critical, 0 major, 3 minor)
- 100% STP-STD traceability (12/12 scenarios)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
13 Go tests implementing 12 STD scenarios for cross-file content
verification in code-review SKILL.md and correctness sub-agent.

Co-Authored-By: QualityFlow[bot] <qualityflow[bot]@users.noreply.github.com>
Replaces intermediate pipeline artifacts with organized test files.

Total: 4 test files → qf-tests/fullsend-aiGH-1835/
Jira: fullsend-aiGH-1835
[skip ci]
@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown

QualityFlow Pipeline Summary

Stage Agent Status
1 STP Builder
2 STP Reviewer
3 STP Refiner
4 STD Builder
5 STD Reviewer
6 STD Refiner
7 Test Generator

Test Output

Language Count Location
Go 4 files internal/scaffold/qf_*_test.go

Issue: GH-70


Generated by QualityFlow

@fullsend-ai-review

Copy link
Copy Markdown

/fs-review

@guyoron1

Copy link
Copy Markdown
Owner Author

/fs-qf

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 22, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 4:07 AM UTC · Completed 4:24 AM UTC
Commit: 73a8f7b · View workflow run →

QualityFlow added 2 commits June 22, 2026 04:11
STP refined: APPROVED_WITH_FINDINGS → APPROVED
- Fixed 5 major and 6 minor findings in 1 iteration
- Corrected reference counts, priority distribution, metadata
- Weighted score: 80 → 100
@fullsend-ai-review

Copy link
Copy Markdown

/fs-review

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 22, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 4:27 AM UTC · Completed 5:06 AM UTC
Commit: 73a8f7b · View workflow run →

QualityFlow and others added 4 commits June 22, 2026 04:28
Co-located 13 functional tests in internal/scaffold/ verifying
cross-file verification instructions in SKILL.md and correctness.md.
All tests compile and pass.
Removes intermediate pipeline artifacts (STP, STD, reviews).
Test files (4) are co-located in source tree with qf_ prefix.
Jira: GH-70
[skip ci]
@fullsend-ai-review

Copy link
Copy Markdown

/fs-review

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 22, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 5:09 AM UTC · Completed 5:25 AM UTC
Commit: 73a8f7b · View workflow run →

@fullsend-ai-review fullsend-ai-review 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.

See the review comment for full details.

BLOCKER_LIST=""
for url in ${ALL_URLS}; do
BLOCKER_LIST="${BLOCKER_LIST}
- ${url}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] injection-vuln

When a label name from untrusted agent output (agent-result.json) fails regex validation, it is interpolated into a GHA workflow command '::warning::' without sanitization for '::' sequences, URL-encoded newlines (%0A/%0D), or control characters. An attacker who controls agent-result.json could inject arbitrary workflow commands.

Suggested fix: Sanitize the label variable before interpolating into the workflow command. Strip or escape '::' sequences, '%0A', '%0D', and control characters.

Comment thread images/code/Containerfile
# cannot shadow trusted system tools (go, git, scan-secrets, etc.).
ENV GOPATH="/sandbox/go" \
PATH="/usr/local/go/bin:/sandbox/go/bin:${PATH}"
PATH="/usr/local/go/bin:${PATH}:/sandbox/go/bin"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] privilege-escalation

Comment on line 119 states '/sandbox/go/bin is placed AFTER system paths so sandbox-user binaries cannot shadow trusted system tools', but the actual PATH construction may not enforce this ordering correctly. If sandbox-user-writable directories appear before system directories, a malicious binary could shadow trusted tools.

Suggested fix: Verify that the PATH variable places /usr/local/bin, /usr/bin, and /usr/sbin before any sandbox-user-writable directories. Add a test or assertion that validates PATH ordering.

h.roleAppIDs = ids
h.roleAppIDs = RoleOnlyAppIDs(ids)
h.legacyAppIDsOnly = legacyAppIDsOnly(ids)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] logic-error

NewHandler derives roleSet (and ALLOWED_ROLES) by parsing ROLE_APP_IDS keys containing a slash (org/role format). If the PR migrates ROLE_APP_IDS from 'org/role' to bare 'role' keys, the slash-split logic will fail to extract role names correctly, potentially breaking role validation and token minting.

Suggested fix: Verify that the key parsing logic in NewHandler handles both 'org/role' and bare 'role' key formats, or update it to match the new key format exclusively.

return orgs
return string(merged), nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] error-handling-gap

In mergeRoleAppIDs, if existing ROLE_APP_IDS JSON is malformed, the function silently returns without error, leaving the desired map unmerged with existing entries. This could cause role configuration drift where expected roles are silently dropped.

Suggested fix: Return an error when JSON unmarshaling fails, or at minimum log a warning so operators can detect configuration drift.

Comment thread docs/agents/triage.md
| `triaged` | The issue is fully specified but is a feature or other category that requires human prioritization before coding. |
| `duplicate` | The issue duplicates an existing one. The agent identified the original and the post-script closes the issue. |
| `blocked` | The issue depends on another issue or external condition. The agent identified the blocker. |
| `blocked` | The issue depends on prerequisites — existing issues/PRs or newly created upstream issues. The agent identified or created the blockers. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] stale-doc

Documentation references the old triage action 'blocked', which was renamed to 'prerequisites' in this PR. Multiple occurrences in this file (lines 43, 83) describe the old action name.

--slug=fullsend-ai-coder \
--pem=/path/to/coder.pem
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] stale-doc

Documentation shows example ROLE_APP_IDS keys using the old '{org}/{role}' format (e.g., 'acme-corp/coder', 'acme-corp/review'), which was changed to bare role keys in this PR.

@@ -63,18 +66,18 @@ gh pr list --repo OTHER-ORG/OTHER-REPO --state open --search "relevant keywords"

If a cross-repo search fails or returns an error (e.g., due to access restrictions), note this in your reasoning as an information gap rather than concluding no blocking work exists.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] stale-doc

Scaffold template references the old 'blocked' label and action in multiple locations (lines 68, 203, 205, 211), which was renamed to 'prerequisites' in this PR. These templates are deployed to consumer repos and would propagate stale terminology.

- `triaged`
Control labels are managed by each agent's post-script and will be refused
server-side if recommended. You do not need to track which labels are
control labels -- just recommend what fits and the pipeline will filter.

## Step 1: Discover available labels

```
gh label list --repo OWNER/REPO --json name,description --limit 100
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] stale-doc

Scaffold template references the old 'blocked' label, which was renamed to 'prerequisites' in this PR.

Comment thread action.yml
run: "$GITHUB_ACTION_PATH/.github/scripts/install-openshell.sh"

- name: Restore cached sandbox image
id: sandbox-cache

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] supply-chain

OpenShell installation uses 'curl | sh' pattern. While the commit SHA is pinned, the install script could be modified upstream between audits. The pinned SHA mitigates but does not eliminate supply chain risk.

@@ -255,18 +253,23 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(resp)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] edge-case

In ServeHTTP, the JSON response from json.NewEncoder(w).Encode is not checked for errors. If encoding fails (e.g., due to a closed connection), the partial response is silently lost.

Co-located tests (qf_* prefix) are now in source package directories.
The qf-tests/ directory contained non-compiling tests from the old pipeline.
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 22, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 8:32 AM UTC · Completed 8:50 AM UTC
Commit: 6ead6d0 · View workflow run →

@fullsend-ai-review fullsend-ai-review 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.

See the review comment for full details.

Comment thread .github/workflows/e2e.yml
@@ -24,19 +25,6 @@ on:
- 'scripts/check-e2e-authorization.sh'
pull_request_target:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[high] secrets exposure / workflow attack surface expansion

The diff removes the paths: filter from the pull_request_target trigger, causing the e2e workflow to trigger on ALL pull_request_target events. The pull_request_target event is security-sensitive (accesses secrets, id-token: write). The runtime file-relevance check falls through as fail-open on gh api failure.

Suggested fix: Consider keeping a broad paths: filter as a declarative first-pass and refining with the runtime check. If removal is intentional, document the rationale.

source "${SCRIPT_DIR}/openshell-version.sh"

echo "Installing OpenShell ${OPENSHELL_VERSION} (${OPENSHELL_SHA})"
curl -LsSf "https://raw.githubusercontent.com/NVIDIA/OpenShell/${OPENSHELL_SHA}/install.sh" \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] curl-pipe-sh remote code execution

The new script fetches and executes a remote install script via curl | sh. While the commit SHA is pinned, there is no integrity verification (checksum) of the downloaded script content before execution.

Suggested fix: Add SHA-256 checksum verification of the downloaded install script before piping to sh.

Comment thread action.yml
default: ""
status-token:
description: Token for status comments (defaults to GH_TOKEN env var).
mint-url:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] token scope change / authentication model

The status-token input is replaced with mint-url, changing the authentication model. If a caller provides status-repo and status-number but not mint-url, orphaned status comments will not be reconciled. No GITHUB_TOKEN fallback exists in the new version.

Suggested fix: Ensure all callers have been updated to pass mint-url instead of status-token.

@@ -145,12 +147,10 @@ jobs:
ORIGINATING_URL: ${{ fromJSON(inputs.event_payload).pull_request.html_url || fromJSON(inputs.event_payload).issue.html_url }}
RETRO_COMMENT: ${{ fromJSON(inputs.event_payload).comment.body || '' }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] secrets handling

The diff removes GH_TOKEN from the env block. The post-retro.sh script requires GH_TOKEN. Verify the mint-url flow provides GH_TOKEN to post-scripts.

Suggested fix: Confirm fullsend run with --mint-url correctly populates GH_TOKEN for post-scripts.

@@ -587,7 +610,10 @@ Protected paths (kept in sync with `post-review.sh`):
- `api-servers/`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[info] protected paths update

Protected paths list in SKILL.md adds Containerfile, Dockerfile, and images/ but post-review.sh and post-fix.sh enforcement scripts do not include these. Agent-side and enforcement-side lists are out of sync.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants