Skip to content

Commit c9640cb

Browse files
committed
Blocklist rather than allowlist for create()
GHSA-94rc-cqvm-m4pw isn’t really a concern anymore thanks to Twig sandboxing. Fully resolves #18376
1 parent bc71a93 commit c9640cb

2 files changed

Lines changed: 22 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44

5+
- Most classes can now be instantiated via the `create()` Twig function. ([#18376](https://github.com/craftcms/cms/discussions/18376))
56
- Fixed a bug where element search query caches weren’t getting invalidated when elements’ search keywords were indexed. ([#18275](https://github.com/craftcms/cms/issues/18275))
67

78
## 4.17.12 - 2026-03-26

src/web/twig/Extension.php

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,13 @@
6464
use DateTime;
6565
use DateTimeInterface;
6666
use DateTimeZone;
67+
use DirectoryIterator;
68+
use GuzzleHttp\Psr7\FnStream;
6769
use Illuminate\Support\Collection;
6870
use IteratorAggregate;
6971
use Money\Money;
72+
use SimpleXMLElement;
73+
use Symfony\Component\Process\Process;
7074
use Throwable;
7175
use Traversable;
7276
use Twig\DeprecatedCallableInfo;
@@ -82,6 +86,7 @@
8286
use yii\base\BaseObject;
8387
use yii\base\InvalidArgumentException;
8488
use yii\base\InvalidConfigException;
89+
use yii\behaviors\AttributeTypecastBehavior;
8590
use yii\db\Exception;
8691
use yii\db\Expression;
8792
use yii\db\QueryInterface;
@@ -1495,11 +1500,22 @@ public function collectFunction(mixed $var): Collection
14951500
public function createFunction(string|array $type, array $params = []): object
14961501
{
14971502
$class = is_string($type) ? $type : ($type['__class'] ?? $type['class'] ?? null);
1498-
if (
1499-
!is_subclass_of($class, BaseObject::class) &&
1500-
!str_starts_with($class, 'craft\\helpers\\')
1501-
) {
1502-
throw new InvalidArgumentException(sprintf('create() can only be used to create instances of %s.', BaseObject::class));
1503+
if (!$class) {
1504+
throw new InvalidArgumentException('No class specified for create().');
1505+
}
1506+
1507+
$blocklist = [
1508+
AttributeTypecastBehavior::class,
1509+
DirectoryIterator::class,
1510+
FnStream::class,
1511+
Process::class,
1512+
SimpleXMLElement::class,
1513+
];
1514+
1515+
foreach ($blocklist as $c) {
1516+
if (is_a($class, $c, true)) {
1517+
throw new InvalidArgumentException(sprintf('create() cannot be used to create instances of %s.', $class));
1518+
}
15031519
}
15041520

15051521
/** @var BaseObject */

0 commit comments

Comments
 (0)