5.20.3 (2026-08-26)
Tools
- Zephir 1.3.0
Changed
- ACL role, component and access names can no longer contain
!, the internal key delimiter;Phalcon\Acl\Exceptions\ForbiddenDelimiteris thrown instead. - Cache file names of
Phalcon\Annotations\Adapter\Stream,Phalcon\Mvc\Model\MetaData\StreamandPhalcon\Storage\Adapter\Streamget a hash suffix when the key contains the character that the separator replacement produces (_for class names;/,\,:for storage keys), so two different keys can no longer share one file. Names of all other keys are unchanged. Phalcon\Auth\Guard\Sessionsets theSecureflag of the remember-me cookie from the newrememberSecureoption (defaulttrue) instead of the request scheme, so a TLS-terminating proxy that reports plain HTTP to the backend cannot downgrade it.Phalcon\Auth\Guard\Sessionvalidates the "remember me" token against the user agent of the current request instead of the one stored in the cookie; a browser user-agent change now ends a remembered session.Phalcon\Encryption\Security::CRYPT_MD5,CRYPT_SHA256andCRYPT_SHA512are documented as weak legacy algorithms to be removed in a future major version; use bcrypt or Argon2 and rehash on login.Phalcon\Storage\Adapter\Streamcreates its shard directories with mode0755instead of0777. Thanks to Ilia Alshanetsky
Added
- Optional fifth argument
stopOnFalseonPhalcon\Events\Manager::fire()(not on the interface), a per-call override ofsetStopOnFalse();EventsAwareTrait::fireManagerEvent()gained a matching fourth argument. Phalcon\Acl\Exceptions\ForbiddenDelimiter, thrown when an ACL role, component or access name contains!.Phalcon\Auth\Exceptions\InvalidCredentialKey, thrown when a credential key passed toPhalcon\Auth\Adapter\Model::retrieveByCredentials()is not a plain identifier.Phalcon\Http\Request\Bag\AbstractBag::clear(), removing all elements of a request bag.allowedClassesoption for the Storage adapters (true,falseor a list of class names), forwarded to the newPhalcon\Storage\Serializer\Php::setAllowedClasses(): restricts the classesunserialize()may instantiate for stored values, including the nested content of theStreamadapter. A class outside the list makes the read fail instead of building an object. Thanks to Ilia AlshanetskyrememberSecureoption for the session guard (Phalcon\Auth\Guard\Config\SessionGuardConfig,Session::fromOptions()).
Fixed
- "Remember me" cookie of another account surviving
Phalcon\Auth\Guard\Session::logout()when the current user does not implementAuthRemember. - A
falsereturned by a listener ofacl:beforeCheckAccess,dispatch:beforeDispatch,dispatch:beforeExecuteRoute,micro:beforeHandleRouteormicro:beforeExecuteRoutebeing overwritten by a later listener that returned a non-null value; these boundaries now fire with stop-on-false, so a denial is final. - Asset output following a symbolic link at the target file and writing outside the assets directory.
- Backslash path traversal in
Phalcon\Mvc\View::partial()andPhalcon\Mvc\View\Simple::render()on Windows. - Cached user surviving
Phalcon\Auth\Guard\Token::setRequest(), so a replaced request inherited the previous authentication. - Column comment concatenated unescaped into the
CREATE TABLE/ALTER TABLEDDL of the MySQL dialect; it is now escaped like the DEFAULT clause. Thanks to Ilia Alshanetsky - Credential keys interpolated unvalidated into the PHQL built by
Phalcon\Auth\Adapter\Model::retrieveByCredentials(). - Distinct ACL tuples colliding on the same internal key when a role, component or access name contained
!. - Fixed shared memory leak of response headers into other callers
- JWT audience validated with a loose comparison, so a numeric or boolean
audclaim satisfied a string audience. - Length-dependent HMAC work on the CBC decrypt failure path of
Phalcon\Encryption\Crypt, which could still tell a padding failure from a MAC mismatch by timing. - Malformed ACL snapshot loaded by
Phalcon\Acl\Adapter\StorageraisingTypeErroror leaving the adapter half loaded, and deep or cyclic object graphs recursing without limit;InvalidSnapshotis now thrown before any state changes. - Memory leak in the PHQL parser for every rejected literal when
phalcon.orm.enable_literalsis off. - Memory leak of the error message on every failed
Phalcon\Mvc\Model\Query\Lang::parsePHQL()call (syntax and scanner errors); the string was only released at request shutdown. - Memory leak of the message buffer on every Volt syntax error (
Phalcon\Mvc\View\Engine\Volt\Compiler); the buffer was only released at request shutdown. - Namespace middleware bypass in the ADR
Routerthrough case-variant or separator-injected paths that PHP resolves to the canonical Action class; only the exact declared class name is a match. - Non-string elements passed to
Phalcon\Acl\Adapter\Memory::addInherit()raising a warning and aTypeErrorinstead ofInvalidRoleType. - Out-of-bounds read in the Annotations scanner when a docblock ends outside an annotation (for example
@!); the scanner now stops at the end of the input andReader::parseDocBlock()returnsfalseinstead of an unset value for a docblock without annotations. - Out-of-bounds read in the Annotations, Volt and PHQL scanners when a quoted string ends with a backslash: the escape rule could consume the string terminator.
- Quadratic list building in the Annotations, Volt and PHQL parsers; argument lists,
INlists and array literals with tens of thousands of items now parse in linear time. - Request attributes of the previous route surviving on a reused request in
Phalcon\ADR\Application::handle(). - Scheme allow-list bypass in the Filter
urlsanitizer through HTML-entity obfuscated schemes (javascript:) and URLs thatparse_url()cannot parse; the sanitizer now fails closed. Thanks to Ilia Alshanetsky - Validators
Alpha,Alnum,Confirmation,CreditCard,Digit,Numericality,Regex,StringLength\MinandStringLength\Maxcast an array value to the constant"Array", sofield[]=xpassed alphabetic, alphanumeric, length and confirmation checks; a value that cannot be a string is now rejected with the validator's message. Thanks to Ilia Alshanetsky - Volt extends-mode cache unserialized without a class restriction.
ReflectionException/TypeErrorfrom ACL rule callbacks with builtin-typed parameters, array callables or static-method strings.acl:afterCheckAccessreporting the static rule instead of the finalisAllowed()decision (rule callback and default action were not applied).only()/except()action filters leaking betweenPhalcon\Auth\Manager::access()activations when the access gate was registered as a shared service in the legacyDi.