Version 4.7.4
Release Date: Unreleased
4.7.4 release of CodeIgniter4
SECURITY
IncomingRequest: HTTPS detection via client-supplied headers was fixed.
IncomingRequest::isSecure()now trusts theX-Forwarded-ProtoandFront-End-Httpsheaders only when the request comes from a trusted proxy configured inConfig\App::$proxyIPs. See the Security advisory GHSA-7wmf-pw8j-mc78 for more information.Query Builder: Fixed a SQL injection vulnerability in
deleteBatch(). WhendeleteBatch()was used together withwhere()conditions, the bound values from the WHERE clause were substituted into the generated SQL with their escape flag ignored, so they were never escaped or quoted. The WHERE binds are now escaped in the same way as a regulardelete().See the Security advisory GHSA-c9w5-rwh3-7pm9 for more information.
UploadedFile:
UploadedFile::move()now sanitizes the client-provided filename when called without a second argument. Previously, the unsanitized client filename was used as the default, allowing path traversal sequences (e.g.../../public/shell.php) to write the uploaded file outside the intended directory. A name explicitly passed as the second argument is not sanitized and remains the caller’s responsibility. See the Security advisory GHSA-hhmc-q9hp-r662 for more information.Validation: The
is_imageandmime_infile upload validation rules now also verify non-empty client filename extensions. Previously, these rules classified an upload solely by its content-derived MIME type, so a file with a dangerous client extension (for example, a.phpfile prepended with image magic bytes) could pass validation while keeping its original extension on disk. See the Security advisory GHSA-mmj4-63m4-r6h5 for more information.The
is_imagerule now rejects uploads when a non-empty client filename extension is not an image extension. Themime_inrule now rejects uploads when a non-empty client filename extension does not match the detected file content, matching the same extension/content agreement used byext_in. Files uploaded without any extension (such as JavaScriptBlobuploads) are still accepted, since the rules validate the file content.
BREAKING
Message Changes
Changes
Deprecations
Bugs Fixed
API: Fixed a bug in Transformers where the root request’s
fieldsandincludequery parameters leaked into nested transformers created insideinclude*()methods, causing incorrect field filtering, unexpected includes, or infinite recursion.Commands: Fixed a bug where
make:model --return entitydid not preserve sub-namespaces when generating the related Entity class.Common: Fixed a bug in
env()where aTypeErrorcould be thrown when non-string values were passed.Common: Fixed
esc()to propagate encoding correctly and prevent reference leaks.Commands: Fixed a bug where
spark lang:findtreated translation keys already provided by the framework or another namespace (such asErrors.*insystem/Language) as new, listing them under--show-newand writing untranslated placeholders intoapp/Languagethat overrode the existing translations.Config: Fixed a bug where
BaseService::injectMockdid not applystrtolowerconsistently, causing inconsistent Service and Mock registration and resolution.Database: Fixed a bug where
updateBatch()could be called after Query Builderwhere()conditions, even though it’s not supported. In this situation, now theDatabaseExceptionis thrown.Encryption: Fixed bugs in
SodiumHandlerwhere runtimeblockSizeoverrides withoutkeywere handled incorrectly, invalid key lengths could leak native Sodium errors, and mismatched decryptblockSizevalues could throwSodiumExceptioninstead ofEncryptionException.Filters: Fixed a bug in
InvalidCharsfilter where invalid UTF-8 or control characters in array keys were not checked.HTTP: Fixed a bug where the User Agent library reported Safari’s WebKit version instead of the browser version from the
Versiontoken.Model: Fixed a bug in
Model::objectToRawArray()where the$recursiveparameter was ignored.Security: Fixed a bug where
CheckPhpInicould raise a type error whenini_get_all()returnednullfor a configured directive value.Session: Fixed a bug in
RedisHandlerwhere the configured$lockMaxRetriesand$lockRetryIntervalvalues were not respected when acquiring session locks.Testing: Fixed a bug where using
MockInputOutputwithin a test that also usesStreamFilterTraittore down the trait’s stream filters, so CLI output produced after theMockInputOutputinteraction (such as intearDown()) was no longer captured and leaked to the console.Validation: Fixed bugs in the
required_withoutrule logic where using array dot notation caused early exits ignoring subsequent fields and triggered anUndefined array keywarning for missing keys.
See the repo’s CHANGELOG.md for a complete list of bugs fixed.