You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add automatic OCI tag pagination to the library and CLI - #70
Prefer next links, including on short/empty pages; otherwise use exclusive tag cursors and the effective page size of each request.
Preserve tag spelling, opaque query bytes, and relative URI path semantics. The all-pages default is 100; single-page behavior, including n=0, remains unchanged.
Reject duplicate/overlapping tags and returned exclusive-cursor values before aggregation, including across redirects. Output files are not overwritten with partial results.
Validate redirect origins before dispatch and authentication, with bounded same-origin authentication-probe redirects in both transport modes. Shared URL checks require ASCII authorities; punycode remains supported for international names.
Sanitize low-level Requests parser errors before logging and preserve redirect-policy cache isolation, ordinary request defaults, telemetry, and output options.
Bound non-progressing traversal at ten consecutive empty linked pages, with explicit failure rather than a partial result.
Update public exports, source contracts, operations/CLI specifications, examples, and regression coverage.
This branch includes repaired main from #71 and the now-merged referrer feature from #68. Release automation is unchanged.
Main 5fdd598a3233d5cb53b4380c22f104e4a91bf439 (merged Support tag references when listing referrers #68) is integrated without rewriting history or resolving any conflicts. Only the three previously reviewed referrer source/test/specification files were brought in.
Local full suite: PYTHONDONTWRITEBYTECODE=1 python3 -B -m pytest -q -p no:cacheprovider — 1300 passed on Python 3.12.4, validating both features together.
Targeted pagination suite: 229 passed, including 13 boundary/reset/redirect/output-safety cases for the approved limit and 43 malformed-tag/cursor and valid-boundary regressions.
Scoped mypy (--follow-imports=silent) passes for the modified tag operation after restoring missing Requests stubs in an isolated validation environment. Bandit and whitespace checks pass. Default Ruff reports the same 14 pre-existing style diagnostics as the pre-change source, with no additional findings; unrelated style normalization is not included.
Local self-review covers the operation, new fixtures/tests, and library/CLI documentation; no new findings. Single-page behavior, redirect accounting, and output safety remain covered.
Hosted run 40982412596: 1300 passed on each of Python 3.10, 3.11, and 3.12 at the combined head. CodeQL and its Python/Actions analyses pass. Current-head Copilot recommends approval with no active issues; Codex completed with no findings, and there are no unresolved inline threads. Scoped mypy also passes for both the referrer CLI and tag operations.
Tests use mocked network responses, including adapter-level coverage that exercises real Requests parsing. No live registry was used, and no failing tests were skipped or disabled.
Human-approved empty-page safety policy
The owner selected 10, rather than the initially proposed 30, as the maximum consecutive empty linked-page count. Commit a8519be92c6a996161e7f316632f79dc52fd5cdf fails explicitly on the tenth empty page carrying a next link, before requesting its continuation, even when opaque URLs keep changing. Receiving tags resets the counter; an empty page without a next link still completes normally. Redirect responses neither increment nor reset it.
This is a documented RegShape safety policy, not an OCI-mandated limit or a cap on total pages. The error returns no partial list, writes no partial standard output, and leaves output files untouched. Tests check the exact threshold and request count, nine-page success, terminal-empty completion, reset through linked and cursor-only continuation, redirects, and plain/JSON output to stdout or new/existing files.
All previous inline findings have fixes, reproducing tests, SHA-confirmation replies, and resolved threads. The empty-page assessment is addressed by the approved ten-page policy. A refreshed summary also identified malformed tag strings: commit e53b4fd0eeadb9b15a0684cf9729312e285ed2d3 validates returned tags and initial/linked cursors against the OCI grammar before output or encoding, without changing single-page behavior or opaque continuation fields. Bounded offline probes reproduced newline output distortion and an unhandled surrogate-encoding error before the fix; regression tests now verify explicit TagError failures and preserved output. Merged with owner authorization as ed17d2eef64da73528998e5c0917dff4e91820c5, after #68 merged as 5fdd598a3233d5cb53b4380c22f104e4a91bf439. Both GitHub merge signatures are verified, and the final main tree exactly matches the tested/reviewed combined head. Issues #46 and #69 are closed. Post-merge main run 40982870365 passed 1300 tests on each of Python 3.10, 3.11, and 3.12. No release or branch/worktree cleanup was performed; both owned worktrees and remote branches are retained clean and fully pushed.
Add list_tags_all and opt-in tag list --all with Link preference, exclusive cursor fallback, effective page-size handling, same-origin guards, and explicit progress errors. Preserve single-page semantics, exercise library/CLI/transport regressions, and document OCI requirements and client policies.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Cursor fallback corrupts opaque query values, which can cause failed or incorrect page requests and false cycle detection for distinct continuation links.
Decode only n and last for pagination validation. Preserve raw opaque fields during cursor fallback and page identity so non-UTF-8 continuation bytes are neither rewritten nor conflated. Add reproducing regressions and document the preservation rule.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Relative pagination links lose empty path segments during URL resolution, potentially sending valid same-origin continuations to the wrong endpoint and breaking traversal or fetching the wrong page.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Preserve empty path segments in relative next-link resolution
src/regshape/libs/tags/operations.py:256
urljoin() collapses empty segments in relative next links: pages/token//part?n=2 becomes .../tags/pages/token/part?n=2, while the equivalent absolute link preserves the double slash. These are distinct URI paths, so a valid same-origin continuation can reach the wrong endpoint and fail traversal or fetch the wrong page. Preserve empty path segments during relative resolution while retaining dot-segment handling and same-origin checks, and add a relative-link regression.
Resolve references with RFC 3986 component and dot-segment rules instead of collapsing empty path segments. Preserve base-path segments and distinguish empty from absent reference queries. Add reproducing public traversal tests and standard URI-resolution cases.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Pagination redirects can expose stored registry credentials to an off-origin authentication realm, and URL-parser errors can leak embedded credentials to CLI stderr.
No open issues 🎉
2 previously missed issues
In code that hasn't changed since last review
Prevent credential leakage through off-origin pagination redirects
src/regshape/libs/tags/operations.py:139
A same-origin next link can redirect off-origin, and client.get() processes the redirected response's authentication challenge before this origin check runs. An off-origin 401 with a Bearer realm can therefore send stored registry credentials to that realm before pagination rejects the response. Disable automatic redirects for pagination in both transport modes, validate each redirect target before following it or processing authentication, and add a regression asserting that an off-origin redirected challenge triggers no credential exchange.
Sanitize URL parsing errors to prevent credential disclosure
src/regshape/libs/tags/operations.py:260
Forwarding str(exc) can expose credentials before the userinfo check runs: https://user:secret@registry.example.com/ignored/tags makes urlsplit() raise a Unicode normalization error containing user:secret. That text becomes the TagError message and is printed to CLI stderr. Return a sanitized detail for URL-parser failures, suppress the raw exception chain, and add this malformed credential-bearing URL to the redaction regression test.
Disable automatic pagination redirects through both transport modes, authentication probes/retries, and cache variants. Follow only validated same-origin redirects with a bounded hop count. Sanitize URL-parser errors and suppress credential-bearing exception context. Add security regressions and preserve default redirect behavior for other callers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Valid same-origin redirects that only reorder query parameters are incorrectly rejected as pagination cycles, preventing the redirected page from being fetched.
Allow safe redirects that canonicalize pagination query order while retaining separate exact redirect-cycle tracking, completed-page detection, and the redirect limit. Add reproducing success and cycle regressions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Requests can fail while parsing a redirect before URL sanitization, potentially exposing embedded credentials in logs or tracebacks and bypassing handled CLI errors.
Share credential-safe URI resolution with bounded auth-probe redirects in both transport modes. Reject overlapping tag pages without partial output. Sanitize pre-return Requests parser errors before logging and cover the real redirect parser at the adapter boundary. Preserve ordinary request defaults and document the new consistency checks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Retain requested cursor boundaries across redirects and reject any returned cursor tag before aggregation, including short pages. Preserve existing duplicate/no-progress diagnostics and add initial, linked, and redirected cursor regressions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Human assessment is needed because cursor cycles with changing opaque query fields can bypass pagination guards, risking unbounded traversal or misleading partial results.
Fail on the tenth consecutive empty linked page, reset on tags, and preserve terminal-empty completion and atomic CLI output. Document the client policy and test exact boundaries, redirects, and output safety.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixed the remaining empty-page non-progress concern in a8519be92c6a996161e7f316632f79dc52fd5cdf. The owner approved a 10-consecutive-empty-linked-page client safety limit: fail on the tenth before following another link, reset on received tags, and retain successful terminal-empty completion. Redirects do not count as pages or reset progress. Library/CLI documentation and 13 boundary, reset, redirect, and no-partial-output cases are included. Local full suite: 1233 passed; hosted validation is pending.
Validate all-pages tag values and initial/linked cursors against the OCI grammar before output or encoding. Preserve single-page behavior and opaque continuation fields, with valid-boundary and malformed-output regressions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixed the latest malformed-tag assessment in e53b4fd0eeadb9b15a0684cf9729312e285ed2d3. Bounded probes reproduced newline output distortion and an unhandled surrogate-encoding failure. All-pages traversal now validates returned tags and initial/linked tag cursors against the OCI grammar before rendering or encoding; opaque continuation values and single-page behavior remain unchanged. The approved ten-empty-linked-page policy remains intact. Local full suite: 1276 passed; focused pagination suite: 229 passed, including 43 additional malformed-tag/cursor and valid-boundary cases. Scoped mypy/Bandit pass; Ruff matches the unchanged baseline.
Integrate the reviewed referrer feature before validating and merging tag pagination.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Integrated merged #68 into this branch as f0166d0bd0d317f00a38ecd73aa7a9d46221e9b4, with no conflicts or manual source changes. The full combined local suite passes 1300 tests. Existing pagination safety policies are unchanged. Please review this integration before the authorized merge.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implement #69 with
list_tags_all()and the opt-inregshape tag list --allcommand, following the Open Container Initiative (OCI) Distribution Specification v1.1.1 tag-pagination rules.This branch includes repaired main from #71 and the now-merged referrer feature from #68. Release automation is unchanged.
Current validation
Testing mode: hosted. Tested/pushed head:
f0166d0bd0d317f00a38ecd73aa7a9d46221e9b4.5fdd598a3233d5cb53b4380c22f104e4a91bf439(merged Support tag references when listing referrers #68) is integrated without rewriting history or resolving any conflicts. Only the three previously reviewed referrer source/test/specification files were brought in.PYTHONDONTWRITEBYTECODE=1 python3 -B -m pytest -q -p no:cacheprovider— 1300 passed on Python 3.12.4, validating both features together.--follow-imports=silent) passes for the modified tag operation after restoring missing Requests stubs in an isolated validation environment. Bandit and whitespace checks pass. Default Ruff reports the same 14 pre-existing style diagnostics as the pre-change source, with no additional findings; unrelated style normalization is not included.Human-approved empty-page safety policy
The owner selected 10, rather than the initially proposed 30, as the maximum consecutive empty linked-page count. Commit
a8519be92c6a996161e7f316632f79dc52fd5cdffails explicitly on the tenth empty page carrying a next link, before requesting its continuation, even when opaque URLs keep changing. Receiving tags resets the counter; an empty page without a next link still completes normally. Redirect responses neither increment nor reset it.This is a documented RegShape safety policy, not an OCI-mandated limit or a cap on total pages. The error returns no partial list, writes no partial standard output, and leaves output files untouched. Tests check the exact threshold and request count, nine-page success, terminal-empty completion, reset through linked and cursor-only continuation, redirects, and plain/JSON output to stdout or new/existing files.
All previous inline findings have fixes, reproducing tests, SHA-confirmation replies, and resolved threads. The empty-page assessment is addressed by the approved ten-page policy. A refreshed summary also identified malformed tag strings: commit
e53b4fd0eeadb9b15a0684cf9729312e285ed2d3validates returned tags and initial/linked cursors against the OCI grammar before output or encoding, without changing single-page behavior or opaque continuation fields. Bounded offline probes reproduced newline output distortion and an unhandled surrogate-encoding error before the fix; regression tests now verify explicit TagError failures and preserved output. Merged with owner authorization ased17d2eef64da73528998e5c0917dff4e91820c5, after #68 merged as5fdd598a3233d5cb53b4380c22f104e4a91bf439. Both GitHub merge signatures are verified, and the final main tree exactly matches the tested/reviewed combined head. Issues #46 and #69 are closed. Post-merge main run 40982870365 passed 1300 tests on each of Python 3.10, 3.11, and 3.12. No release or branch/worktree cleanup was performed; both owned worktrees and remote branches are retained clean and fully pushed.Closes #69