Skip to content

feat: cap the discovery document and JWKS at 1 MiB - #60

Merged
turegjorup merged 1 commit into
developfrom
feature/cap-json-resource-size
Aug 26, 2026
Merged

feat: cap the discovery document and JWKS at 1 MiB#60
turegjorup merged 1 commit into
developfrom
feature/cap-json-resource-size

Conversation

@turegjorup

Copy link
Copy Markdown
Collaborator

The discovery document and the JWKS were decoded and cached with no size limit, so a hostile or misconfigured endpoint could hand this library an unbounded body. Both are a few kilobytes in practice, so a mebibyte is generous.

Changes

fetchJsonResource() gains a MAX_JSON_RESOURCE_BYTES cap of 1 MiB and raises HttpException above it. Both documents are fetched through that one method, so a single cap covers the discovery document and the JWKS together.

Two checks, because one is not enough:

  • the declared body size, where the response reports one — cheap, and it fires before the body is retrieved
  • the retrieved content, unconditionally — a chunked response declares no size at all

What the cap does and does not do

It bounds what gets json_decoded and written to the PSR-6 cache. It does not bound peak memory: Guzzle has already buffered the whole body by the time this library sees it. Bounding the transfer itself would mean a streaming read against a stream => true request, which is a larger change than the exposure warrants for a document fetched from a configured host over TLS. That limitation is written into the method docblock rather than left for the next reader to discover.

Verification

134 tests, all green. Coverage 100% (30/30 methods, 191/191 lines). Mutation: 239 generated, 235 killed, 4 ignored, zero escaped, MSI 100%.

The boundary is tested from both sides — exactly at the limit accepted, one byte over refused — for the declared size and for the content. That pairing is what pins the constant: without an exact-limit test, a mutation shifting 1048576 by one survives.

PHPStan max clean at the ceiling and at the dependency floor, php-cs-fixer, markdownlint, prettier and composer normalize all clean.

Both documents were decoded and cached with no size limit, so a hostile or
misconfigured endpoint could hand over an unbounded body. Both are a few
kilobytes in practice, so a mebibyte is generous.

The declared body size is checked first where the response reports one, and
the retrieved content unconditionally, because a chunked response reports no
size. Both resources go through fetchJsonResource(), so one cap covers them.

The cap bounds what gets decoded and written to the cache, not peak memory:
Guzzle has already buffered the body by the time it is visible here.
Bounding the transfer itself would need a streaming read against a
`stream => true` request, which is a larger change than the exposure
warrants for a document fetched from a configured host over TLS. That
limitation is stated in the method docblock rather than left implied.

The boundary is tested from both sides — exactly at the limit is accepted,
one byte over is refused — for the declared size and for the content, which
is also what pins the constant against a mutation off by one.
@turegjorup turegjorup self-assigned this Aug 26, 2026
@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (aa772be) to head (61265cd).

Additional details and impacted files
@@             Coverage Diff             @@
##             develop       #60   +/-   ##
===========================================
  Coverage     100.00%   100.00%           
- Complexity        83        87    +4     
===========================================
  Files              1         1           
  Lines            208       220   +12     
===========================================
+ Hits             208       220   +12     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@turegjorup
turegjorup merged commit 507b1be into develop Aug 26, 2026
18 checks passed
@turegjorup
turegjorup deleted the feature/cap-json-resource-size branch August 26, 2026 10:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant