fix(security): reject named refs before dependency-review compare - #1048
fix(security): reject named refs before dependency-review compare#1048cursor[bot] wants to merge 6 commits into
Conversation
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>
…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>
Classify curl's no-status 000 write-out as unavailable instead of a three-digit HTTP code, and lock private/internal visibility plus raw visibility non-leakage with executable regressions. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
GitHub's compare API resolves named revisions to moving HEADs. Require exact 40- or 64-character hexadecimal object IDs and an owner/name repository identity before any compare request. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
There was a problem hiding this comment.
Stale comment
Verdict
COMMENT on exact head
83e7cd38.This successor keeps the curl
000classification and rejects named revisions, empty SHAs, and non-owner/namerepository values before the compare request. Local contract:tests/test_required_workflow_queue_contract.py67 passed.Operator next step
- Mark this pull request ready for review so required checks and the merge scheduler see the head.
- Wait only for exact-current-head required checks and a counted non-author formal approval.
- Prefer this branch over #897, #1033, #1041, #1042, and #1044.
- After merge, run the ContextualWisdomLab/EgressWeave#76 public consumer proof before closing #810.
Automated review is not qualifying approval or merge authority.
Sent by Cursor Automation: Fix Issues
|
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. |
There was a problem hiding this comment.
Stale comment
Remaining gap on
83e7cd38Named-ref rejection is correct. A single-slash
owner/namewhose owner or name is.or..still reaches curl.RFC 3986 remove-dot-segments would turn
/repos/../.github/dependency-graph/compare/...into/.github/dependency-graph/compare/...(Berners-Lee et al., 2005). On this head,REPOSITORY=../.githuborContextualWisdomLab/..plus a synthetic HTTP 200 writessupported=true.Operator next step
Prefer #1050 (
29a20baa) for integration. Keep this pull request open as historical evidence. Do not merge this head. Keep #810 open until a protected-main public consumer run proves a non-200 cannot go green.Sent by Cursor Automation: Fix Issues
There was a problem hiding this comment.
Verdict
COMMENT on exact head 83e7cd38. Do not merge this head as the fail-closed landing vehicle.
Named-ref rejection is real: HEAD_SHA=main and an empty base SHA fail before curl and do not echo the raw invalid revision. Curl 000 (exit 0 and exit 6), HTTP 403/404, empty/malformed status, and curl exit 18 with a printed 200 all fail closed. The pinned action has no step-level if: or continue-on-error. Job token stays contents: read + pull-requests: read with persist-credentials: false.
Remaining gap
A single-slash owner/name whose owner or name is . or .. still reaches curl. Local replay of the extracted probe on this head:
REPOSITORY |
curl invoked | supported=true |
|---|---|---|
ContextualWisdomLab/.github |
yes (legal) | yes |
ContextualWisdomLab/.. |
yes | yes |
../.github |
yes | yes |
ContextualWisdomLab/. |
yes | yes |
../evil |
yes | yes |
ContextualWisdomLab/../evil |
no | no |
RFC 3986 remove-dot-segments can collapse /repos/../.github/dependency-graph/compare/... to a different API path (Berners-Lee et al., 2005). github.repository is not attacker-controlled today, but this pull request claims path injection cannot reach the compare URL. The contract test uses the two-slash case, so it stays green while the two-segment .. case is untested. Doctoring prose is also unpinned.
Landing vehicle
Prefer #1049 (e4a7dffa) over this head and over #897, #1033, #1041, #1042, #1044, #1045, and draft #1050. #1049 rejects . / .. segments, keeps .github legal, and hides raw invalid identity. Do not open a third overlapping dependency-review workflow pull request from this run.
Keep #810 open until a protected-main public consumer run on ContextualWisdomLab/EgressWeave#76 proves a non-200 or failed-transfer comparison cannot go green.
Automated review is not qualifying approval or merge authority.
Operator next step
- Leave this pull request open only as historical evidence. Do not approve or merge
83e7cd38. - Move counted non-author formal approval to #1049 after that head's exact-current-head required checks are terminal and clean.
- After #1049 merges, run the EgressWeave#76 public consumer proof before closing #810.
Sent by Cursor Automation: Fix Issues
| *) visibility="unknown" ;; | ||
| esac | ||
| git_object_id='^[0-9a-f]{40}([0-9a-f]{24})?$' | ||
| repository_identity='^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$' |
There was a problem hiding this comment.
repository_identity='^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$' is a single-slash shape check. Local replay on this head: ContextualWisdomLab/.., ../.github, ContextualWisdomLab/., and ../evil all invoked curl and wrote supported=true. RFC 3986 remove-dot-segments can collapse /repos/../.github/dependency-graph/compare/... (Berners-Lee et al., 2005). After the shape match, reject an owner or name that is exactly . or .. (keep .github). Prefer #1049, which already has that reject.
| ) -> None: | ||
| """owner/name is required before the compare path is interpolated.""" | ||
|
|
||
| raw_repository = "ContextualWisdomLab/../evil" |
There was a problem hiding this comment.
ContextualWisdomLab/../evil has two slashes, so it fails the shape regex and never exercises .. as a segment. This test stays green while ContextualWisdomLab/.. still reaches curl. Assert ContextualWisdomLab/.. and ../.github do not create the curl-invoked marker, and keep the three-segment case as a separate pin. #1049 already parametrizes those two-segment cases.


Purpose
Continue #1044. The
000classification is necessary, but GitHub's dependency-graph compare API still resolves named revisions such asmainto the current HEAD of that name. A syntheticHEAD_SHA=mainwith HTTP 200 previously wrotesupported=trueand would have reached the pinned action against a moving revision.Prefer this branch over #897, #1033, #1041, #1042, and #1044 for integration. Keep #821 draft. Do not close #810 until a protected-main public consumer run proves a non-200 or failed-transfer comparison cannot produce a green Dependency Review gate.
What changed
owner/namerepository identity and exact 40- or 64-character hexadecimal Git object IDs before any compare request.000with transport exit 0 is locked asunavailable.if:orcontinue-on-error).Acceptance
Merge only after exact-current-head deterministic, security, dependency, and required workflows are terminal and clean, current automated review has no valid unresolved finding, and a qualifying counted non-author formal approval exists.
Automated review is not qualifying approval or merge authority.
Operator next step