# allowed_classes_callback option for unserialize()

- Thread: https://externals.io/message/128395
- Original archive: https://news-web.php.net/php.internals/128395
- Started by Casper Langemeijer on 2025-08-05T09:14:26+00:00
- Messages: 2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #128395 — Casper Langemeijer — 2025-08-05T09:14:26+00:00

URL: https://externals.io/message/128395#128395

I'm writing a this email to propose adding allowed_classes_callback option to `unserialize()`. 

The class name as parsed from the serialized string is passed as a parameter to the callback, it should return a boolean. true would allow the class, false would block it. This blocks classes the same way 'allowed_classes' would, but by callback instead. The callback will be triggered *after* allowed_classes is evaluated (if present). Blocking will have the same effect as allowed_classes, using __PHP_Incomplete_Class.

This callback would solve a few problems where allowed_classes is not sufficient:

- This would also allow for fixing legacy applications where it is not exactly clear what is being unserialized. In my use-case the callable returns a true value but a E_USER_DEPRECATION is triggered. This way data can be collected about what classes to allow through monitoring these deprecations, providing a non-disrupting way to secure unserialize calls. This is especially helpful in very generic unserialize usages like caches.

- It would allow for an `is_subclass_of()` check where for example an interface can be added to classes that are safe to get unserialized. Current allowed_classes array only matches the exact class, not it's children. 

Note that these problems are not resolvable by using unserialize_callback_func because that call only happens for unloaded classes, where the PHP Object Injection vulnerability https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection affects classes that might already have been loaded.

In de pull request Jakub wrote:
> Personally I don't see any issue here and it seems quite self contained and small so I wouldn't mind to get it merged without RFC. It might be worth to email internals first to double check that there are no objections first.

Out of scope: I understand that __PHP_Incomplete_Class is not very 2025. Adding an option throw_for_unknown_classes has been suggested on this list. I'm happy to implement that, but for now I'd like to keep it at allowed_classes_callback.

Feedback is very much appreciated.

The change and some more details live here: https://github.com/php/php-src/pull/19087

---

## #128397 — Larry Garfield — 2025-08-05T13:22:59+00:00

URL: https://externals.io/message/128395#128397 · In reply to: #128395

> I'm writing a this email to propose adding allowed_classes_callback 
> option to `unserialize()`. 
>
> The class name as parsed from the serialized string is passed as a 
> parameter to the callback, it should return a boolean. true would allow 
> the class, false would block it. This blocks classes the same way 
> 'allowed_classes' would, but by callback instead. The callback will be 
> triggered *after* allowed_classes is evaluated (if present). Blocking 
> will have the same effect as allowed_classes, using 
> __PHP_Incomplete_Class.
>
> This callback would solve a few problems where allowed_classes is not 
> sufficient:
>
> - This would also allow for fixing legacy applications where it is not 
> exactly clear what is being unserialized. In my use-case the callable 
> returns a true value but a E_USER_DEPRECATION is triggered. This way 
> data can be collected about what classes to allow through monitoring 
> these deprecations, providing a non-disrupting way to secure 
> unserialize calls. This is especially helpful in very generic 
> unserialize usages like caches.
>
> - It would allow for an `is_subclass_of()` check where for example an 
> interface can be added to classes that are safe to get unserialized. 
> Current allowed_classes array only matches the exact class, not it's 
> children. 
>
> Note that these problems are not resolvable by using 
> unserialize_callback_func because that call only happens for unloaded 
> classes, where the PHP Object Injection vulnerability 
> https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection 
> affects classes that might already have been loaded.
>
> In de pull request Jakub wrote:
> > […]
>
> Out of scope: I understand that __PHP_Incomplete_Class is not very 
> 2025. Adding an option throw_for_unknown_classes has been suggested on 
> this list. I'm happy to implement that, but for now I'd like to keep it 
> at allowed_classes_callback.
>
> Feedback is very much appreciated.
>
> The change and some more details live here: 
> https://github.com/php/php-src/pull/19087

I am not opposed to this, but I would like to see it go through an RFC.

--Larry Garfield
