Skip to content

fix(pingora): exempt documentation raster evidence - #1420

Open
seonghobae wants to merge 17 commits into
mainfrom
fix/pingora-binary-doc-assets-20260830
Open

fix(pingora): exempt documentation raster evidence#1420
seonghobae wants to merge 17 commits into
mainfrom
fix/pingora-binary-doc-assets-20260830

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Outcome

Keep the Pingora required gate fail-closed for runtime candidates while allowing non-executable raster acceptance evidence beneath documentation directories.

Root cause

GitHub omits patches for binary files. The scanner treated every patchless file as a runtime candidate, fetched a PNG screenshot as UTF-8, and blocked LineageWeave PR 780 before the actual review workflow could run.

Changes

  • classify structurally validated PNGs only beneath documentation directories as documentation assets
  • retain binary fail-closed behavior outside that boundary
  • add a regression proving a docs screenshot skips while the same suffix outside docs remains a candidate
  • clarify the binding Pingora policy

Validation

  • 51 focused Pingora policy and workflow tests passed
  • git diff --check passed

Cross-repo trigger: ContextualWisdomLab/LineageWeave#780.


Devin Review

Summary by CodeRabbit

  • 정책 및 보안 개선

    • 문서 디렉터리의 이미지 증거는 파일 확장자가 아닌 실제 콘텐츠로 검증됩니다.
    • 이제 구조적으로 완전히 검증된 PNG만 관련 예외로 인정됩니다.
    • 손상된 PNG, 잘못된 청크·CRC·압축 데이터, 빈 이미지 및 이미지로 위장한 파일은 거부됩니다.
    • 런타임 증거는 유효한 UTF-8 텍스트인지 확인하며, 누락되거나 잘못된 증거는 안전하게 실패합니다.
  • 문서화

    • 관련 정책과 표준 문서에 PNG 검증 기준과 허용 범위를 반영했습니다.

Active repair ownership

Codex resumed exact-head review repair on 2026-08-30 KST; current scope is the unresolved bounded PNG validation findings and protected delivery.

Signed-off-by: Seongho Bae <me@seonghobae.me>
@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

Next included review available in 47 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 823c7f14-af7d-4e8d-9d6a-acdf470276b5

📥 Commits

Reviewing files that changed from the base of the PR and between 78f890e and b4dfa61.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • scripts/ci/pingora_edge_policy.py
  • tests/test_pingora_edge_policy.py
📝 Walkthrough

Walkthrough

정책 스캐너가 문서 디렉터리의 PNG 최종 바이트를 구조적으로 검증합니다. GIF, JPEG, WebP 예외를 제거합니다. 정책 문서와 PNG, PDF, 페이지네이션 회귀 테스트를 갱신합니다.

Changes

Pingora 래스터 증거 검증

Layer / File(s) Summary
정책 예외 및 검증 기준
docs/adr/0019-cloudflare-pingora-edge-standard.md, docs/doctoring/pingora-edge-standard.md, docs/policies/PINGORA_EDGE_POLICY.md, CHANGELOG.md
문서 디렉터리 아래의 구조적으로 검증된 PNG만 Nginx 명명 예외로 허용하도록 기준을 갱신했습니다. 이미지 확장명만으로는 예외가 되지 않습니다. 런타임 후보는 UTF-8로 디코딩해야 합니다.
바이트 로딩 및 PNG 검증
scripts/ci/pingora_edge_policy.py
문서 이미지 예외를 .png로 제한했습니다. PNG의 IHDR, 색상·비트 깊이, 청크 순서, CRC, zlib 스트림, dimensions, scanline 및 팔레트 인덱스를 검증합니다. 검증에 실패한 파일은 PolicyError로 거부합니다.
PNG 및 정책 회귀 검증
tests/test_pingora_edge_policy.py
PNG 생성 헬퍼와 정상·손상·위장 PNG 테스트를 추가했습니다. PDF 면제, 페이지네이션 경계, 파일 콘텐츠 실패-폐쇄 동작을 검증합니다.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Merge Risk: 🟡 Moderate · up to 78f89

The PR allows validated documentation PNGs to bypass runtime scanning, but the validator can allocate unbounded decompressed data before rejecting a crafted image, potentially disrupting the required policy gate; malformed transparency metadata may also be accepted. Merge should wait for bounded finalization and complete PNG validation.

Suggested reviewers: claude

Sequence Diagram(s)

sequenceDiagram
  participant GitHubContentsAPI
  participant evaluate_pull_request
  participant PNGValidator
  GitHubContentsAPI->>evaluate_pull_request: 변경 파일 메타데이터와 최종 raw bytes
  evaluate_pull_request->>PNGValidator: 문서 PNG 검증 요청
  PNGValidator-->>evaluate_pull_request: 유효한 PNG 또는 PolicyError
  evaluate_pull_request-->>GitHubContentsAPI: 스캔 통과 또는 정책 실패
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 문서 디렉터리의 래스터 증거를 Pingora 정책에서 면제하는 주요 변경을 정확하고 간결하게 설명합니다.
Docstring Coverage ✅ Passed Docstring coverage is 93.10% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 29 functions across 2 files. (1 skipped: 1 …
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 93.10% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 29 functions across 2 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pingora-binary-doc-assets-20260830

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.

@seonghobae
seonghobae enabled auto-merge (squash) August 29, 2026 22:53
devin-ai-integration[bot]

This comment was marked as resolved.

@opencode-agent
opencode-agent Bot disabled auto-merge August 29, 2026 22:54
@seonghobae
seonghobae enabled auto-merge (squash) August 29, 2026 22:57
@opencode-agent
opencode-agent Bot disabled auto-merge August 29, 2026 22:58
@seonghobae
seonghobae enabled auto-merge (squash) August 30, 2026 02:34
@opencode-agent
opencode-agent Bot disabled auto-merge August 30, 2026 02:34
Signed-off-by: Codex <codex@localhost>
@seonghobae
seonghobae enabled auto-merge (squash) August 30, 2026 03:41
…260830' into HEAD

# Conflicts:
#	docs/adr/0019-cloudflare-pingora-edge-standard.md
#	docs/policies/PINGORA_EDGE_POLICY.md
#	scripts/ci/pingora_edge_policy.py
#	tests/test_pingora_edge_policy.py
devin-ai-integration[bot]

This comment was marked as resolved.

@opencode-agent
opencode-agent Bot disabled auto-merge August 30, 2026 03:59
coderabbitai[bot]

This comment was marked as resolved.

@seonghobae
seonghobae enabled auto-merge (squash) August 30, 2026 06:04
devin-ai-integration[bot]

This comment was marked as resolved.

@opencode-agent
opencode-agent Bot disabled auto-merge August 30, 2026 06:06
coderabbitai[bot]

This comment was marked as resolved.

@seonghobae
seonghobae enabled auto-merge (squash) August 30, 2026 06:26
@opencode-agent
opencode-agent Bot disabled auto-merge August 30, 2026 06:26
devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae
seonghobae enabled auto-merge (squash) August 30, 2026 06:29
@opencode-agent
opencode-agent Bot disabled auto-merge August 30, 2026 23:50
devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae
seonghobae enabled auto-merge (squash) August 30, 2026 23:54
@opencode-agent
opencode-agent Bot disabled auto-merge August 30, 2026 23:54
Signed-off-by: Seongho Bae <me@seonghobae.me>
@seonghobae
seonghobae enabled auto-merge (squash) August 30, 2026 23:56
@opencode-agent
opencode-agent Bot disabled auto-merge August 30, 2026 23:56
coderabbitai[bot]

This comment was marked as resolved.

@seonghobae
seonghobae enabled auto-merge (squash) August 30, 2026 23:58
@opencode-agent
opencode-agent Bot disabled auto-merge August 31, 2026 01:02
@seonghobae
seonghobae enabled auto-merge (squash) August 31, 2026 04:27
@opencode-agent
opencode-agent Bot disabled auto-merge August 31, 2026 04:29
Signed-off-by: Seongho Bae <me@seonghobae.me>
@seonghobae
seonghobae enabled auto-merge (squash) August 31, 2026 04:38
devin-ai-integration[bot]

This comment was marked as resolved.

@opencode-agent
opencode-agent Bot disabled auto-merge August 31, 2026 04:43
@seonghobae
seonghobae enabled auto-merge (squash) August 31, 2026 05:44
@opencode-agent
opencode-agent Bot disabled auto-merge August 31, 2026 05:44
Signed-off-by: Seongho Bae <me@seonghobae.me>

@devin-ai-integration devin-ai-integration 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.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 1 new potential issue.

Devin Review

Comment on lines +404 to +408
valid_ancillary = (
1 <= separator <= 79
and separator + 2 < length
and chunk_data[separator + 1] == 0
)

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.

🟡 Malformed profile names receive exemptions

An iCCP name with forbidden bytes or spacing passes validation. Malformed PNG evidence then receives the documentation exemption.

Suggested change
valid_ancillary = (
1 <= separator <= 79
and separator + 2 < length
and chunk_data[separator + 1] == 0
)
valid_ancillary = (
1 <= separator <= 79
and all(
32 <= byte <= 126 or 161 <= byte <= 255
for byte in chunk_data[:separator]
)
and chunk_data[0] != 32
and chunk_data[separator - 1] != 32
and b" " not in chunk_data[:separator]
and separator + 2 < length
and chunk_data[separator + 1] == 0
)
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@devin-ai-integration devin-ai-integration 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.

Devin Review found 3 new potential issues.

Devin Review

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.

📝 Info: Image size remains deliberately bounded

_load_raw_file_bytes still rejects PNGs above one megabyte. The policy explicitly requires bounded evidence, so larger screenshots remain unsupported by contract.

(Refers to this code)

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

if width is None or saw_trns or saw_idat or not valid_length:
return False
saw_trns = True
elif chunk_type in {b"cHRM", b"gAMA", b"iCCP", b"sBIT", b"sRGB"}:

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.

🟡 Malformed PNG metadata passes validation

A PNG with malformed zTXt or pHYs data passes _is_recognized_documentation_image. The gate grants an exception without its required complete chunk validation.

Prompt for agents
The PNG validator in scripts/ci/pingora_edge_policy.py validates only five named ancillary chunks. Other standard ancillary chunks pass after CRC checking without their required payload, ordering, cardinality, or compressed-stream contracts. For example, a zTXt chunk containing an invalid zlib stream and a pHYs chunk with the wrong length both pass _is_recognized_documentation_image. Define the supported ancillary-chunk set explicitly and validate each supported chunk completely, including every compressed stream; reject unsupported or malformed chunks so the implementation matches the documented complete PNG validation contract. Add regression tests for malformed zTXt/iTXt payloads and fixed-length ancillary chunks.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +253 to +289
def _png_rows_are_valid(
pixels: bytes,
pass_layouts: list[tuple[int, int, int, int]],
*,
bytes_per_pixel: int,
bit_depth: int,
palette_entries: int | None,
) -> bool:
"""Validate filters and indexed samples for every decoded PNG pass."""

for start, stride, rows, pass_width in pass_layouts:
previous = bytes(stride - 1)
for row in range(rows):
row_start = start + row * stride
filter_type = pixels[row_start]
if filter_type > 4:
return False
encoded = pixels[row_start + 1 : row_start + stride]
reconstructed = bytearray(len(encoded))
for index, value in enumerate(encoded):
left = reconstructed[index - bytes_per_pixel] if index >= bytes_per_pixel else 0
above = previous[index]
upper_left = previous[index - bytes_per_pixel] if index >= bytes_per_pixel else 0
predictor = (0, left, above, (left + above) // 2, _paeth_predictor(left, above, upper_left))[filter_type]
reconstructed[index] = (value + predictor) & 0xFF
previous = bytes(reconstructed)
if palette_entries is None:
continue
samples_seen = 0
for byte in reconstructed:
for shift in range(8 - bit_depth, -1, -bit_depth):
if samples_seen == pass_width:
break
if ((byte >> shift) & ((1 << bit_depth) - 1)) >= palette_entries:
return False
samples_seen += 1
return True

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.

📝 Info: Interlaced scanlines use correct geometry

_png_rows_are_valid resets prior rows per Adam7 pass and uses the defined filter byte distance. Indexed checks exclude only padding samples.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@seonghobae
seonghobae enabled auto-merge (squash) August 31, 2026 09:28
@opencode-agent
opencode-agent Bot disabled auto-merge August 31, 2026 10:29
@seonghobae
seonghobae enabled auto-merge (squash) August 31, 2026 10:39
@opencode-agent
opencode-agent Bot disabled auto-merge August 31, 2026 11:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants