Security Notes
Security considerations for wpzylos-container.
Binding Security
Don't Bind User Input Directly
Never use user input to determine what class to instantiate:
// Bad: DANGEROUS: Remote code execution
$class = $_GET['service'];
$container->bind('service', $class);
// Good: Whitelist allowed classes
$allowed = [
'json' => JsonFormatter::class,
'xml' => XmlFormatter::class,
];
$type = $_GET['format'] ?? 'json';
if (isset($allowed[$type])) {
$container->bind(Formatter::class, $allowed[$type]);
}
Validate Factory Closures
When factories come from configuration:
// Bad: Don't execute arbitrary callbacks
$factory = get_option('custom_factory');
$container->bind('service', $factory);
// Good: Use known, safe factories
$container->bind('service', function ($c) {
$config = $c->get(Config::class);
return new Service($config->get('service.option'));
});
Resolution Security
Scope Service Access
Don't expose the container globally:
// Bad: Global access allows bypassing authorization
global $container;
// Good: Inject only what's needed
class Controller
{
public function __construct(
private UserRepository $users,
private Gate $gate
) {}
}
Immutable After Boot
Prevent rebinding after application boots:
class SecureContainer extends Container
{
private bool $locked = false;
public function lock(): void
{
$this->locked = true;
}
public function bind(string $abstract, $concrete = null): void
{
if ($this->locked) {
throw new \RuntimeException('Container is locked');
}
parent::bind($abstract, $concrete);
}
}