Skip to content

v3.0.1

Choose a tag to compare

@labudzinski labudzinski released this 25 Apr 07:37
· 10 commits to main since this release

Security

  • Validator/TransactionValidator

    • Reject CRLF, percent-encoded CRLF and NULL bytes in URI; fix the
      previously broken backslash regex (/\\\/) that matched nothing
      relevant. Mitigates HTTP Response Splitting / smuggling (A03).
    • Reject protocol-relative URIs (//host, /\host) which Symfony's
      Request::create() interprets as having host as authority.
      Mitigates SSRF / Open Redirect (A10).
    • New validateHeaders(): enforce RFC 7230 §3.2.6 tchar header names
      and forbid CR/LF/NULL in header values (A03).
  • Validator/BatchRequestValidator

    • Drop the "skip per-transaction validation for batches >1000" path.
      Security must not depend on batch size; the maxBatchSize cap is the
      only correct performance lever (A04 Insecure Design).
  • Parser/JsonBatchRequestParser

    • json_decode now uses depth=32 and JSON_THROW_ON_ERROR, plus a
      configurable maxContentLength (default 5 MiB) checked before
      decoding. Mitigates billion-laughs / memory-exhaustion DoS (A04).
    • Add a denylist of sensitive context headers that must not be
      propagated from the parent request to sub-requests: Host,
      X-Forwarded-*, X-Real-IP, Forwarded, and RFC 7230 §6.1
      hop-by-hop headers (A01 BAC + A03 spoofing).
  • Bridge facades and executors

    • SymfonyBatchRequestFacade / LaravelBatchRequestFacade: replace raw
      $e->getMessage() in 500 responses with a generic
      "Internal server error" message; full context is still logged
      (A09 Information Disclosure).
    • SymfonyTransactionExecutor: keep informative error type/message for
      HttpExceptionInterface (NotFound, etc.) but return a generic
      payload for all other Throwable (A09).
    • LaravelTransactionExecutor: stop returning get_class($e) and the
      raw exception message in the per-transaction response (A09).

Bugs

  • Parser/JsonBatchRequestParser::extractParameters

    • parse_str is no longer applied to JSON-looking bodies. Previously
      a body like {"a":1} was silently mangled into
      ['{"a":1}' => '']. The raw body still flows through
      prepareContent.
  • Bridge/Symfony/SymfonyBatchRequestFacade

    • Remove the redundant "isLargeBatch" branch in extractContext that
      decoded the entire payload a second time, and remove the rate-limit
      decode that ran without depth/throw flags. Rate-limit decode is now
      safe and tolerant of invalid input (count=1 fallback).
    • Remove the unused getErrorType() method (dead code).
    • logError no longer allocates a fresh NullLogger on each call.
  • Handler/BatchRequestHandler

    • Stop disabling the logger for batches >1000. Silently dropping
      validation-error logs hid both bugs and DoS attempts.
  • Bridge/Laravel/LaravelServiceProvider

    • Actually load config/batch-request.php via mergeConfigFrom,
      publish it under the batch-request-config tag, and read
      batch-request.max_batch_size (with a safe fallback to 50 when the
      config repository is not bound, so test containers keep working).
      The config file existed and was documented but had no effect.
    • Mark the provider as final.

Tests

  • Update Symfony/LaravelTransactionExecutor tests to assert the new
    generic error contract.
  • Replace the PHPUnit-12 $this->isType('callable') (removed in
    PHPUnit 13) with a callback constraint in
    LaravelServiceProviderTest.