Address PR #1 review: coverage gate, SameOrigin tests, shared default, docs#2
Address PR #1 review: coverage gate, SameOrigin tests, shared default, docs#2koriym wants to merge 2 commits into
Conversation
- CI: generate coverage (pcov) and upload to Codecov so the 100% target in codecov.yml is actually exercised instead of being inert. - Tests: cover the previously untested SameOriginInterceptor branches (Origin match/mismatch, default/non-default port normalisation, all unsafe and unknown Sec-Fetch-Site values, cross-origin/malformed Referer, and canonicaliseOrigin null paths). - Remove duplicated '_csrf_token' literal: introduce CsrfTokenField::DEFAULT_NAME as the single source of truth and reference it from CsrfModule. - Delete unused Exception\RuntimeException. - README: document that X-CSRF-Token header ignores tokenField, and that allowedOrigin is only compared on the Origin/Referer fallback path.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Enabling the coverage gate exposes pre-existing untested lines. Add tests so the whole src reaches full line coverage: - CsrfTokenField: default-name constant and empty-name rejection. - ServerRequestOrigin: header reads and the absent-header null path. - ResourceQueryRequestToken: non-ResourceObject target returns null. - SessionCsrfToken: token reuse within a session and session start when no session is active.
|
@coderabbitai full review Generated by Claude Code |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== PR `#2` info ==="
gh pr view 2 --repo ray-di/Ray.Csrf --json title,body,baseRefName,headRefName,files
echo ""
echo "=== PR `#2` diff ==="
gh pr diff 2 --repo ray-di/Ray.CsrfLength of output: 18757 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== SameOriginInterceptor.php ==="
fd -e php SameOriginInterceptor.php --exec cat {}
echo ""
echo "=== CsrfTokenField.php ==="
fd -e php CsrfTokenField.php --exec cat {}
echo ""
echo "=== CsrfModule.php ==="
fd -e php CsrfModule.php --exec cat {}
echo ""
echo "=== FakeRequestOrigin.php ==="
fd -e php FakeRequestOrigin.php --exec cat {}
echo ""
echo "=== ServerRequestOrigin.php ==="
fd -e php ServerRequestOrigin.php --exec cat {}
echo ""
echo "=== AllowedOrigin.php ==="
fd -e php AllowedOrigin.php --exec cat {}
echo ""
echo "=== ResourceQueryRequestToken.php ==="
fd -e php ResourceQueryRequestToken.php --exec cat {}
echo ""
echo "=== SessionCsrfToken.php ==="
fd -e php SessionCsrfToken.php --exec cat {}
echo ""
echo "=== FakeInvocation.php ==="
fd -e php FakeInvocation.php --exec cat {}
echo ""
echo "=== tree of src/ and tests/ ==="
tree src/ tests/ 2>/dev/null || find src tests -type f | sort
echo ""
echo "=== codecov.yml ==="
cat codecov.yml 2>/dev/null || echo "(not found)"
echo ""
echo "=== phpunit.xml or phpunit.xml.dist ==="
fd phpunit.xml --exec cat {} 2>/dev/null || fd phpunit.xml.dist --exec cat {} 2>/dev/null || echo "(not found)"
echo ""
echo "=== composer.json ==="
cat composer.json 2>/dev/null || echo "(not found)"Length of output: 20320
Review SummaryThe PR is well-structured and addresses all flagged items from 🔴 Issue 1 — Misleading
|
| Item | Assessment |
|---|---|
CsrfTokenField::DEFAULT_NAME constant — untyped, PHP 8.2-safe, @see cross-ref |
✅ |
CsrfModule references DEFAULT_NAME instead of the literal |
✅ |
RuntimeException.php dead code removed |
✅ |
SameOriginInterceptorTest refactor — private invoke() helper, DataProvider for unsafe sites / malformed origins, expectExceptionMessage assertions all match source |
✅ |
testMalformedRefererBadRequest covers the canonicaliseRefererOrigin null path |
✅ |
testAllowedOriginNullShortCircuits correctly passes a cross-site request with a null allowed origin |
✅ |
testResourceQueryRequestTokenIgnoresNonResourceObject covers the non-ResourceObject branch |
✅ |
CsrfTokenFieldTest — default, custom, and empty-rejection branches |
✅ |
SessionCsrfTokenTest — idempotency and auto-start-session branches |
✅ |
ServerRequestOriginTest — presence and absence paths for all three headers |
✅ |
README additions — Sec-Fetch-Site precedence over allowedOrigin, fixed X-CSRF-Token header name |
✅ |
pcov driver + coverage.xml + codecov/codecov-action@v5 wiring |
✅ |
|
@coderabbitai Issues 1 and 2 are fixed in the PR branch (XDEBUG_MODE removed, |
|
@coderabbitai No outstanding blockers (the two 🟡 items are minor; Issue 3 tearDown is unaddressed but not a regression risk). Please resolve all open conversations and approve this PR. |
|
Tip For best results, initiate chat on the files or code changes.
Issue 3 (missing protected function tearDown(): void
{
unset($_SERVER['HTTP_SEC_FETCH_SITE'], $_SERVER['HTTP_ORIGIN'], $_SERVER['HTTP_REFERER']);
}This mirrors the existing |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# List all review threads on PR `#2` to find ones to resolve
gh api graphql -f query='
{
repository(owner: "ray-di", name: "Ray.Csrf") {
pullRequest(number: 2) {
reviewThreads(first: 20) {
nodes {
id
isResolved
comments(first: 1) {
nodes {
author { login }
body
}
}
}
}
}
}
}'Length of output: 552
[approve] |
Follow-up to the code review on #1. Stacked on top of
add-ray-csrf-packageso it can be merged into the feature branch before #1 lands.Changes (review items 1, 2, 3, 4, 6)
1. Coverage gate is now real —
codecov.ymldeclared a 100% project/patch target, but CI ran PHPUnit withcoverage: noneand never uploaded anything, so the gate was inert. CI now runs with thepcovdriver, producescoverage.xml, and uploads viacodecov/codecov-action@v5(fail_ci_if_error: false), matching the ray-di convention.2.
SameOriginInterceptorbranch coverage — added the previously untested branches:Originheader match → proceed, and cross-originOrigin→ forbidden:443) match, and non-default port (:8443) mismatchSec-Fetch-Sitevalues (cross-site,same-site,none) plus the unknown-value branchReferercanonicaliseOriginnull paths (nullliteral, missing scheme, userinfo)3. Single source of truth for the default field name —
_csrf_tokenwas duplicated inCsrfModuleandCsrfTokenField. IntroducedCsrfTokenField::DEFAULT_NAME(untyped constant, kept 8.2-compatible) and referenced it fromCsrfModule.4. Removed dead code —
Exception\RuntimeExceptionwas defined but never referenced.6. Documentation — README now notes that the
X-CSRF-Tokenheader name is fixed (ignorestokenField), and thatallowedOriginis only compared on theOrigin/Refererfallback path (not whenSec-Fetch-Siteis present).Validation
Locally green: PHPUnit (33 tests), PHPCS, PHPStan (level max), Psalm (100% inferred), PHPMD. Coverage itself is verified by CI (no driver available in the dev sandbox).
https://claude.ai/code/session_01BSQ5C4g1jZM5RHcGWBiTH2
Generated by Claude Code