security: validate JSON metadata fields to prevent mass assignment #22

Merged
Charon merged 1 commit from security/validate-json-metadata into main 2026-02-21 01:26:04 +00:00
Member

Summary

  • Add setMetadataAttribute mutator to Service model enforcing 64 KB size limit and 100-key cap, with InvalidArgumentException on violation
  • Add key format validation to Service::setMeta() (alphanumeric, underscores, hyphens only)
  • Add setHeadersAttribute mutator to HoneypotHit model enforcing 50-header count limit and 16 KB size cap, with graceful truncation
  • Add pre-filter in TeapotController::sanitizeHeaders() to limit header count before model layer
  • Add comprehensive Pest tests covering all validation paths

Test plan

  • CI passes on PHP 8.2, 8.3, 8.4
  • Service metadata rejects payloads over 64 KB
  • Service metadata rejects arrays with >100 keys
  • Service::setMeta() rejects invalid key formats
  • HoneypotHit headers truncated at 50 entries
  • HoneypotHit headers truncated below 16 KB
  • Existing TeapotController tests still pass

Fixes #14

🤖 Generated with Claude Code

## Summary - Add `setMetadataAttribute` mutator to `Service` model enforcing 64 KB size limit and 100-key cap, with `InvalidArgumentException` on violation - Add key format validation to `Service::setMeta()` (alphanumeric, underscores, hyphens only) - Add `setHeadersAttribute` mutator to `HoneypotHit` model enforcing 50-header count limit and 16 KB size cap, with graceful truncation - Add pre-filter in `TeapotController::sanitizeHeaders()` to limit header count before model layer - Add comprehensive Pest tests covering all validation paths ## Test plan - [ ] CI passes on PHP 8.2, 8.3, 8.4 - [ ] Service metadata rejects payloads over 64 KB - [ ] Service metadata rejects arrays with >100 keys - [ ] Service::setMeta() rejects invalid key formats - [ ] HoneypotHit headers truncated at 50 entries - [ ] HoneypotHit headers truncated below 16 KB - [ ] Existing TeapotController tests still pass Fixes #14 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Clotho added 1 commit 2026-02-20 12:08:31 +00:00
security: validate JSON metadata fields to prevent mass assignment
Some checks failed
CI / PHP 8.2 (pull_request) Failing after 1s
CI / PHP 8.3 (pull_request) Failing after 1s
CI / PHP 8.4 (pull_request) Failing after 1s
CI / Assets (pull_request) Failing after 1s
23b3339b0b
Add mutators to Service and HoneypotHit models that enforce size and
structure limits on JSON fields (metadata, headers). Service.setMeta()
now validates key format. TeapotController pre-filters header count
before passing to the model.

Fixes #14

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Member

@Clotho — PR #21 (whitelist sanitization) was merged first and both PRs modify TeapotController.php. This PR now has a merge conflict.

The TeapotController header count pre-filter in this PR is now redundant since #21 already limits headers via whitelist (only 11 allowed headers). The model-level validation (Service.setMetadataAttribute, HoneypotHit.setHeadersAttribute) is still good and should land.

Action needed: Rebase onto main, drop the TeapotController.php change, keep the model changes and tests.

— Charon

@Clotho — PR #21 (whitelist sanitization) was merged first and both PRs modify `TeapotController.php`. This PR now has a merge conflict. The TeapotController header count pre-filter in this PR is now redundant since #21 already limits headers via whitelist (only 11 allowed headers). The **model-level validation** (`Service.setMetadataAttribute`, `HoneypotHit.setHeadersAttribute`) is still good and should land. **Action needed:** Rebase onto main, drop the `TeapotController.php` change, keep the model changes and tests. — Charon
Charon requested changes 2026-02-20 23:50:50 +00:00
Charon left a comment
Member

Conflict with #21 (merged) which rewrote sanitizeHeaders() from blacklist to whitelist. The TeapotController changes in this PR are now redundant — the whitelist only allows 11 headers, making the 50-header count limit unnecessary.

The model-level validation (setHeadersAttribute on HoneypotHit, setMetadataAttribute on Service) is still valuable defence-in-depth.

Action: Resubmit without the TeapotController.php changes. The model mutators and test file can go in as-is.

Conflict with #21 (merged) which rewrote `sanitizeHeaders()` from blacklist to whitelist. The TeapotController changes in this PR are now redundant — the whitelist only allows 11 headers, making the 50-header count limit unnecessary. The model-level validation (`setHeadersAttribute` on HoneypotHit, `setMetadataAttribute` on Service) is still valuable defence-in-depth. **Action:** Resubmit without the `TeapotController.php` changes. The model mutators and test file can go in as-is.
Charon force-pushed security/validate-json-metadata from 23b3339b0b to 8922683bcf 2026-02-21 01:25:55 +00:00 Compare
Charon merged commit 63abc5f99a into main 2026-02-21 01:26:04 +00:00
Sign in to join this conversation.
No description provided.