Skip to content

fix(security): fail closed when dependency-review compare is unavailable - #1041

Open
seonghobae wants to merge 6 commits into
mainfrom
cursor/dependency-review-fail-closed-187c
Open

fix(security): fail closed when dependency-review compare is unavailable#1041
seonghobae wants to merge 6 commits into
mainfrom
cursor/dependency-review-fail-closed-187c

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Purpose

Close the fail-open hole in the org-required Security Scan dependency-review job tracked by #810. Current protected main (c47afc2d) still probes GET /repos/{repo}/dependency-graph/compare/{base}...{head}, treats HTTP 403/404 as supported=false, skips actions/dependency-review-action, and exits 0.

This is the single integration vehicle for that repair. It continues #1033 and supersedes #897 (which still left the action independently skippable via if: supported == 'true'). It also absorbs the identity-validation follow-up that #1045 started, including the later review findings on ./.. segments, HTTP 000, and not echoing raw invalid values.

Canary (do not treat as fixed until a post-merge consumer run)

ContextualWisdomLab/EgressWeave#66, Security Scan run 31108241013, job 92638903658:

  • compare 10d0c51daf2ad278d66f43be479df8cf6b08ba6d...c038a9509d1a8eae8561cc9081e67e12bd373d42
  • curl: (22) The requested URL returned error: 403
  • warning: Dependency review is unavailable for ContextualWisdomLab/EgressWeave; skipping dependency-review hard gate.
  • job conclusion: success (pinned action skipped)

Downstream: ContextualWisdomLab/EgressWeave#76.

What changed

  • Only transport exit 0 plus exact HTTP 200 may reach the pinned actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 (fail-on-severity: moderate, unchanged).
  • HTTP 403/404/empty/malformed status, HTTP 000, transport failure (including curl exit 18 with a printed 200), and timeouts fail the job.
  • Revisions must be 40- or 64-character hex, and the repository must be canonical owner/name without ./.. segments, before curl runs (curl exit uncalled). Identity failures name the class only and do not echo raw invalid values.
  • After a successful probe the pinned action is not independently skippable.
  • OSV and Trivy remain separate hard gates; Scorecard stays soft.

Tests

Local pytest tests/test_required_workflow_queue_contract.py: 72 passed.

Executable regressions cover the EgressWeave #66 403 skip-was-success canary, 404/empty/malformed/000, transport failure, curl exit 18 + printed 200, malformed identity before curl, and argv recording on the success path.

CI note

The required Noema Review failure on 22a23981 (run 32046375681) was a same-SHA flake: a later pull_request_target run on that head succeeded, and this head (051ba5e0) retires that stale check. Noema is a pull_request_target gate from trusted main and is not part of this workflow change.

Acceptance

Do not close #810 from this change alone. Keep it open until a protected-main public-repository consumer run proves a non-200 or failed-transfer comparison cannot produce a green Dependency Review gate.

Open in Web Open in Cursor 

seonghobae and others added 3 commits August 17, 2026 00:19
Replay unique #897 source onto current origin/main. Skip shared
ARCHITECTURE/CLAUDE trees. Treat non-200 or failed transport as
unavailable evidence rather than a clean skip.
Close the remaining #810 diagnostic gap:
allowlist public/private/internal/unknown visibility in probe
diagnostics, execute 403/404/empty/malformed regressions, and stop
making the pinned action independently skippable after a successful
probe.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Add executable regressions for the EgressWeave #66 canary (HTTP 403
skip-was-success), a bare transport failure, and curl exit 18 with a
printed 200. Record exact SHAs and allowlisted visibility without
leaking the probe token.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review available on request

  • 🔍 Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5e0e8aed-9996-4c61-a5cd-c17eb8dbefe3


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…arness

Invoke the extracted support probe with an absolute bash path and keep
the fake curl first on PATH so isolated executable regressions can run
without calling the real binary.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

@cursor cursor Bot 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.

Verdict

COMMENT on exact head fbb8432345ac6565724668afdbf9e3259475b94b.

The 403/404/transport fail-closed path, allowlisted visibility, exact-head checkout, discarded bodies, and unskippable pinned action are source-correct for #810. This draft still interpolates unvalidated BASE_SHA, HEAD_SHA, and REPOSITORY into the compare URL, so an empty revision or ../ repository can mint supported=true from a forged HTTP 200. The success test also does not record curl argv, so a hardcoded supported=true would pass.

Prefer #1045 (6a7103a4) for integration. It rejects malformed identity before the socket, records the exact compare argv, and keeps the pinned action ungated. Keep this draft and #897/#1033/#1042 out of the merge queue. Keep #810 open until a protected-main public consumer run proves a non-200 cannot go green.

Do not self-approve. Do not merge this draft.

Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

public|private|internal) visibility="${REPOSITORY_VISIBILITY}" ;;
*) visibility="unknown" ;;
esac
set +e

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.

The probe starts curl immediately after the visibility allowlist. An empty BASE_SHA, a 39-character hex string, or ../ in HEAD_SHA is interpolated into /dependency-graph/compare/{base}...{head}. The executable harness then returns HTTP 200 and the step writes supported=true.

Reject 40- or 64-character hex revisions and canonical owner/name before set +e, and fail with HTTP unavailable / curl exit uncalled. Landed on #1045.

combined = f"{result.stdout}{result.stderr}"
assert result.returncode == 0
assert (tmp_path / "github-output").read_text(encoding="utf-8") == (
"supported=true\n"

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.

This success contract only checks return code and supported=true. It does not record curl argv, so a probe that skips the compare URL and hardcodes the output still passes.

Record the fake curl argv and require https://api.example.invalid/repos/{owner}/{name}/dependency-graph/compare/{base}...{head} plus -o /dev/null. Landed on #1045.

@cursor cursor Bot 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.

Verdict

COMMENT on exact head 6a7103a48a814ab4892cf9a4aabc9c07177c8147.

The pre-network 40/64-hex and owner/name checks close the forged-200 hole that blocked #1041. A remaining identity case still matches that regex: ContextualWisdomLab/.. is syntactically owner/name. Named refs such as main are also rejected only as non-hex, and rejection logs still echoed the raw values.

Prefer #1049, which continues this head, rejects ./.. segments, treats curl 000 as unavailable, and stops echoing raw invalid identity. Do not merge #1045. Keep #810 open until a protected-main public consumer run proves a non-200 cannot go green.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

…pare

Validate 40- or 64-character hex revisions and canonical owner/name
without . or .. segments before opening a socket. Treat curl's 000
no-status sentinel as unavailable. Identity failures name the class
only and do not echo raw invalid values. Record compare argv so a
hardcoded supported=true path cannot satisfy the success contract.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
@seonghobae
seonghobae marked this pull request as ready for review August 18, 2026 01:31
@cursor

cursor Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Keep malformed-revision and malformed-repository errors from
interpolating untrusted BASE_SHA, HEAD_SHA, or REPOSITORY into the
Actions annotation. A new head also retires the stale same-SHA
Noema failure on #1041.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
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.

security: make central dependency-review unavailability fail closed

2 participants