release: bind sealed evidence to a canonical root path - #58
Conversation
📝 WalkthroughWalkthrough릴리스 증거 루트에 정규 절대 경로와 심볼릭 링크가 없는 경로를 요구합니다. 검증기와 CLI는 확인된 루트를 사용합니다. 부모 심볼릭 링크, 경로 해석 실패, CLI 출력 생성을 테스트합니다. Changes정규 증거 루트 바인딩
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant main
participant _require_canonical_evidence_root
participant _select_evidence_paths
CLI->>main: evidence 경로 전달
main->>_require_canonical_evidence_root: 경로 안전성 검증
_require_canonical_evidence_root-->>main: 확인된 canonical root 반환
main->>_select_evidence_paths: 확인된 root 전달
_select_evidence_paths-->>CLI: manifest 출력 경로 반환
Possibly related issues
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review Review exact current stacked head |
|
@opencode-agent @cwl-noema-review Please independently inspect exact current head The RED exact head Review whether the lexical absolute path versus strict resolved path comparison is a complete fail-closed defense for the stated ancestor-link threat; whether the returned real root is consistently used for payload selection and manifest-output exclusion; whether root resolution errors are normalized safely; and whether the documentation, CHANGELOG, POSIX/CWE-59 citations, public docstrings, standalone behavior, and credential-neutral trust boundary are accurate. No |
|
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/egressweave/release_evidence.py`:
- Around line 149-150: Extend tests in
test_sealed_release_evidence_root_binding.py to create a symlink at the final
evidence directory path itself, then invoke _build() and assert it raises
SystemExit with the existing “release evidence directory is missing or unsafe”
message. Keep the existing parent-directory symlink coverage unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: ba1df6e4-6b44-4de1-978d-22bbb28cda1d
📒 Files selected for processing (4)
CHANGELOG.mddocs/sealed-release-evidence.mdsrc/egressweave/release_evidence.pytests/test_sealed_release_evidence_root_binding.py
|
@coderabbitai review Review exact current stacked head Focus on whether lexical-absolute versus strict-resolved root binding rejects every symlinked ancestor, whether all subsequent evidence reads and manifest-output exclusion use the same real root, stable fail-closed root-resolution behavior, documentation accuracy, Python 3.10–3.13 compatibility, 100% production statement and branch coverage, beginner-readable docstrings, APA 7th primary-source guidance, and unchanged workflow/credential boundaries. Do not treat absent SAST Semgrep, Security Scan, prerequisite stack integration, draft state, or independent approval as satisfied. |
|
@opencode-agent @cwl-noema-review Please independently inspect exact current head The exact RED head Review whether the lexical absolute path versus strict resolved path comparison fully closes the stated root-authority gap; whether the canonical root is consistently reused for payload selection and manifest-output exclusion; whether root-resolution errors remain fail-closed and stable; and whether the documentation, CHANGELOG, POSIX/CWE-59 citations, public docstrings, standalone behavior, and credential-neutral boundary are accurate. No |
|
CodeRabbit finding |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
head='ccfd7809b352e95f4f6e646d0e886ac28e773698'
base='eb2cba679ff1202866850cb24049efad885f0dc8'
printf '%s\n' '== Checked-out commit =='
git rev-parse HEAD
printf '%s\n' '== Requested commits =='
git show -s --format='%H%n%P%n%s' "$base"
git show -s --format='%H%n%P%n%s' "$head"
printf '%s\n' '== Changed paths: base...head =='
git diff --name-status "$base...$head"
printf '%s\n' '== Diff: implementation and tests =='
git diff --find-renames --unified=80 "$base...$head" -- \
src/egressweave/release_evidence.py \
tests/test_sealed_release_evidence_root_binding.py
printf '%s\n' '== Diff: documentation and automation boundaries =='
git diff --find-renames --unified=40 "$base...$head" -- \
CHANGELOG.md \
docs/sealed-release-evidence.md \
.github
printf '%s\n' '== Source map =='
ast-grep outline src/egressweave/release_evidence.py --items all --view expanded
printf '%s\n' '== Relevant symbol references =='
rg -n -C 4 \
'(_require_canonical_evidence_root|_select_evidence_paths|resolve\(|absolute\(|manifest|evidence_root|output)' \
src/egressweave/release_evidence.py testsLength of output: 110459 🏁 Script executed: #!/bin/bash
set -euo pipefail
head='ccfd7809b352e95f4f6e646d0e886ac28e773698'
base='eb2cba679ff1202866850cb24049efad885f0dc8'
printf '%s\n' '== Base relationship =='
git merge-base --is-ancestor "$base" "$head" && echo 'base is an ancestor of head'
git log --format='%H %s' --ancestry-path "$base..$head"
printf '%s\n' '== Complete canonical-root and output-boundary flow =='
sed -n '142,190p;487,585p;614,692p' src/egressweave/release_evidence.py
printf '%s\n' '== All direct callers and tests =='
rg -n -C 3 \
'(_require_canonical_evidence_root|_select_evidence_paths|build_evidence_manifest\(|write_evidence_manifest\(|_require_output_outside_verified_set\()' \
src tests
printf '%s\n' '== Python support and CI declarations =='
rg -n -C 4 '(python_requires|requires-python|3\.10|3\.11|3\.12|3\.13|coverage|branch)' \
pyproject.toml .github/workflows README.md tests/test_quality_contracts.py \
2>/dev/null || true
printf '%s\n' '== Exact-head pull request checks =='
gh pr view 58 --repo ContextualWisdomLab/EgressWeave \
--json number,isDraft,headRefOid,baseRefOid,statusCheckRollup \
--jq '{number, isDraft, headRefOid, baseRefOid, checks: [.statusCheckRollup[] | {name, status, conclusion, startedAt, completedAt, detailsUrl}]}'
printf '%s\n' '== Changed workflow, credential, and release-boundary paths =='
git diff --name-only "$base...$head" | rg '(^|/)(\.github|.*workflow.*|.*credential.*|.*release.*|.*attest.*)' || trueLength of output: 54713 🤖 web_search executed:
Length of output: 13964 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Citation line numbers =='
nl -ba docs/sealed-release-evidence.md | sed -n '175,215p'
printf '%s\n' '== Current-head CI run summary =='
gh run view 31056179578 --repo ContextualWisdomLab/EgressWeave \
--json databaseId,headSha,status,conclusion,event,jobs \
--jq '{databaseId, headSha, status, conclusion, event, jobs: [.jobs[] | {name, status, conclusion, startedAt, completedAt}]}'
printf '%s\n' '== Coverage and test-report lines from the exact-head CI logs =='
gh run view 31056179578 --repo ContextualWisdomLab/EgressWeave --log 2>&1 |
rg -n -C 2 '([0-9]+ passed|TOTAL|100%|coverage report|FAILED|ERROR)' || trueLength of output: 1047 🤖 web_search executed:
Length of output: 8914 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Citation line numbers =='
awk 'NR >= 180 && NR <= 215 { printf "%d\t%s\n", NR, $0 }' \
docs/sealed-release-evidence.md
printf '%s\n' '== Current-head CI run summary =='
gh run view 31056179578 --repo ContextualWisdomLab/EgressWeave \
--json databaseId,headSha,status,conclusion,event,jobs \
--jq '{databaseId, headSha, status, conclusion, event, jobs: [.jobs[] | {name, status, conclusion, startedAt, completedAt}]}'
printf '%s\n' '== Coverage and test-report lines from the exact-head CI logs =='
gh run view 31056179578 --repo ContextualWisdomLab/EgressWeave --log 2>&1 |
rg -n -C 2 '([0-9]+ passed|TOTAL|100%|coverage report|FAILED|ERROR)' || trueLength of output: 28098 🏁 Script executed: #!/bin/bash
set -euo pipefail
awk 'NR >= 214 && NR <= 250 { printf "%d\t%s\n", NR, $0 }' \
docs/sealed-release-evidence.mdLength of output: 2189
I found two documentation findings.
No implementation finding was identified. The lexical-absolute versus strict-resolved comparison rejects the tested symlinked ancestor case. Selected payload reads and manifest-output exclusion use the canonical root. Root-resolution failures fail closed. The exact-head CI run completed successfully for Python 3.10–3.13 and package acceptance. Each Python job reported 716 passing tests and 100% coverage over 1,601 statements and 550 branches. No I did not treat SAST Semgrep, Security Scan, prerequisite integration, draft status, or independent approval as satisfied.
|
|
@coderabbitai review @opencode-agent @cwl-noema-review Please independently inspect exact current head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
base='eb2cba679ff1202866850cb24049efad885f0dc8'
head='ccfd7809b352e95f4f6e646d0e886ac28e773698'
repo='ContextualWisdomLab/EgressWeave'
printf '%s\n' '== Requested revisions and ancestry =='
git show -s --format='%H%n%P%n%s' "$base" "$head"
git merge-base --is-ancestor "$base" "$head" && echo 'base is an ancestor of head'
git log --format='%H %s' --ancestry-path "$base..$head"
printf '%s\n' '== Complete diff file list =='
git diff --name-status "$base...$head"
printf '%s\n' '== Boundary-sensitive path changes =='
git diff --name-only "$base...$head" |
rg '(^|/)(\.github|.*credential.*|.*provider.*|.*transport.*|.*naruon.*|.*msa.*|.*publish.*|.*release.*|.*api.*)' || true
printf '%s\n' '== Changed source and test diff =='
git diff --find-renames --unified=100 "$base...$head" -- \
src/egressweave/release_evidence.py \
tests/test_sealed_release_evidence_root_binding.py \
tests/test_sealed_release_evidence_symlink_boundary.py
printf '%s\n' '== Changed documentation diff =='
git diff --find-renames --unified=60 "$base...$head" -- \
CHANGELOG.md docs/sealed-release-evidence.md
printf '%s\n' '== Source structure =='
ast-grep outline src/egressweave/release_evidence.py --items all --view expanded
printf '%s\n' '== Canonical-root implementation and all direct flow references =='
rg -n -C 8 \
'(_require_canonical_evidence_root|_select_evidence_paths|_require_output_outside_verified_set|build_evidence_manifest|write_evidence_manifest|\.absolute\(\)|\.resolve\()' \
src/egressweave/release_evidence.py
printf '%s\n' '== Relevant test implementations =='
for f in \
tests/test_sealed_release_evidence_root_binding.py \
tests/test_sealed_release_evidence_symlink_boundary.py
do
echo "-- $f"
cat -n "$f"
done
printf '%s\n' '== Exact-head PR checks =='
gh pr view 58 --repo "$repo" \
--json headRefOid,baseRefOid,isDraft,statusCheckRollup \
--jq '{headRefOid,baseRefOid,isDraft,checks:[.statusCheckRollup[]|{name,status,conclusion}]}'Length of output: 58125 🤖 web_search executed:
Length of output: 12711 🤖 web_search executed:
Length of output: 7352 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== Relative evidence-path and output-exclusion tests =='
rg -n -C 6 \
'(relative|cwd|chdir|output.*verified|verified.*output|outside.*verified|manifest output)' \
tests/test_sealed_release_evidence*.py
printf '%s\n' '== Public entry-point and writer call sites =='
rg -n -C 5 \
'(build_evidence_manifest\(|write_evidence_manifest\(|_select_evidence_paths\()' \
src tests
printf '%s\n' '== Python version and coverage configuration =='
rg -n -C 4 \
'(requires-python|python_requires|3\.10|3\.11|3\.12|3\.13|branch)' \
pyproject.toml .github/workflows tests/test_quality_contracts.py 2>/dev/null || trueLength of output: 42531
I found two documentation findings.
I found no implementation defect in the requested scope.
I did not approve this draft PR. The two documentation findings remain. SAST Semgrep, Security Scan, completed current-head automated review, independent approval, prerequisite stack integration, and repository-policy gates also remain unsatisfied. You are interacting with an AI system. |
Scope
This stacked draft addresses #57 without changing any workflow or credential boundary.
eb2cba679ff1202866850cb24049efad885f0dc8from PR release: bind sealed evidence to exact source identity #56.4f94a8228e18b12a65785a72ff7ae712a7b37d3c.103ad121c9cfb165d5fae960fadadb1c59a45dd2.ccfd7809b352e95f4f6e646d0e886ac28e773698.The regressions prove that an otherwise valid sealed evidence set reached through a symlinked ancestor was accepted by both the public verifier and CLI. At the RED head, the read-only exact-head CI failed on Python 3.10–3.13 only because those two attacks did not raise; package acceptance and Ruff passed.
The implementation now compares the lexical absolute form of the supplied path with its strict filesystem-resolved path, returns that canonical root, and uses it for every payload read and manifest-output exclusion. A stable fail-closed error covers root canonicalization failure.
CHANGELOG.mdand operator guidance document the boundary and cite the 2018 edition of IEEE Std 1003.1-2017 and current CWE-59 in APA 7th form. The final documentation-only commit corrected the distinction between accepting a relative real path and binding its computed absolute form.Exact-head verification
Exact current head
ccfd7809b352e95f4f6e646d0e886ac28e773698passed the credential-free, read-onlyciworkflow:The workflow checked out the exact head with persisted credentials disabled and only
contents: read/metadata: readtoken permissions.CodeRabbit reviewed the implementation head
103ad121c9cfb165d5fae960fadadb1c59a45dd2and raised one request for final-directory symlink coverage. That finding was verified as duplicate: the exact stacked base already containstest_public_verifier_rejects_a_symlinked_evidence_directory, and exact-current-head CI executes it. The duplicate thread was resolved with the existing regression identified. A fresh review has been requested for exact current headccfd7809b352e95f4f6e646d0e886ac28e773698; review latency is not treated as success.Remaining gates
This PR remains draft and stacked. It must not be retargeted or merged before prerequisite exact-tree integration, exact-head SAST Semgrep, Security Scan, completed exact-current-head automated review, qualifying independent approval, and repository-policy acceptance. A successful CodeRabbit commit-status context alone is not treated as a completed review, and no absent or queued gate is treated as successful.
No
.githubfile, publication permission, signing identity, ref-writing behavior, model-executing credential path, dependency contract, transport API, or naruon/MSA integration contract is changed.