Fixes
- Allow-list the
exttoken parsed out of the on-disk cache header.extractCacheInfo()previously fed whatever it found in<!--cachetime:.../...;ext:...-->straight intoResponse::withType()— anything able to write totmp/cache/views/(a misconfiguredCACHEconstant pointing at a public path, a compromised plugin, a bug elsewhere that let user input control a cache filename) could therefore force an arbitraryContent-Type, opening a MIME-confusion / XSS surface. The token is now restricted to a fixed list (html, json, xml, csv, txt, rss, atom, js, css) with the regex tightened to[a-z0-9]{1,8}. Mirrored in bothCacheMiddlewareandFileCache. - Atomic on-disk writes in
CacheComponent::_writeFile(). Previouslyfile_put_contents()was used with no lock and no temp-file pattern — under concurrent traffic the middleware could read a half-written file, the regex match failed,cacheTimeparsed to0, and the torn entry never got invalidated by$cacheEnd < time(). Writes now go throughtempnam()+LOCK_EX+rename()(atomic on the same filesystem). - Reset per-request state at the top of
CacheMiddleware::process()._cacheContent/_cacheInfowere previously not cleared between requests — latent under PHP-FPM (one request per worker), but a correctness landmine on long-lived runtimes (Swoole, RoadRunner, FrankenPHP, ReactPHP) where content from request N could leak into request N+1.
Full Changelog: 2.2.0...2.2.1