From ff83474742ff961bc468f063c97536a941ef37ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brian=20Sch=C3=A4ffner?= Date: Fri, 16 Oct 2026 14:30:18 +0200 Subject: [PATCH 1/2] fix: require patched expression and YAML parsers --- CHANGELOG.md | 6 ++ composer.json | 7 +- .../SymfonySecurityCompatibilityTest.php | 76 +++++++++++++++++++ 3 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 tests/Security/SymfonySecurityCompatibilityTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c6f8a5..9d4a188 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html) where applicable. +## 1.0.7 — 2026-10-16 + +- Require Symfony ExpressionLanguage 8.1.9 and YAML 8.1.6 or newer to exclude CVE-2026-109449 and CVE-2026-109413. +- Require SymPress Kernel 1.1.10 or newer to retain the corrected HttpFoundation 8.1.9 minimum in lowest-version installations. +- Verify dependency version boundaries and rejection of excessively nested expressions and inline YAML collections. + ## 1.0.6 — 2026-10-09 - Require maintained Symfony Routing and YAML 8.1 or newer, excluding the vulnerable 8.0 releases covered by the May 2026 advisories. diff --git a/composer.json b/composer.json index ef0f7d3..d11e386 100644 --- a/composer.json +++ b/composer.json @@ -20,17 +20,18 @@ "symfony/console": "^8.1", "symfony/dependency-injection": "^8.1.8", "symfony/error-handler": "^8.1", - "symfony/expression-language": "^8.0", + "symfony/expression-language": "^8.1.9", "symfony/filesystem": "^8.0", "symfony/framework-bundle": "^8.1", "symfony/http-kernel": "^8.1", "symfony/routing": "^8.1", "symfony/service-contracts": "^3.6", - "symfony/yaml": "^8.1", - "sympress/kernel": "^1.1.1" + "symfony/yaml": "^8.1.6", + "sympress/kernel": "^1.1.10" }, "require-dev": { "brain/monkey": "^2.6", + "composer/semver": "^3.4", "sympress/qa": "^0.1.2" }, "suggest": { diff --git a/tests/Security/SymfonySecurityCompatibilityTest.php b/tests/Security/SymfonySecurityCompatibilityTest.php new file mode 100644 index 0000000..f1f9ecd --- /dev/null +++ b/tests/Security/SymfonySecurityCompatibilityTest.php @@ -0,0 +1,76 @@ +} $manifest */ + $manifest = json_decode((string) file_get_contents(dirname(__DIR__, 2) . '/composer.json'), true, flags: JSON_THROW_ON_ERROR); + + self::assertFalse(Semver::satisfies($rejected, $manifest['require'][$package])); + self::assertTrue(Semver::satisfies($accepted, $manifest['require'][$package])); + } + + /** @return iterable */ + public static function dependencyBoundaries(): iterable + { + yield 'expression initial incomplete fix' => ['symfony/expression-language', '8.1.6', '8.1.9']; + yield 'expression last affected patch' => ['symfony/expression-language', '8.1.8', '8.1.9']; + yield 'yaml inline lexer' => ['symfony/yaml', '8.1.5', '8.1.6']; + yield 'kernel header parser floor' => ['sympress/kernel', '1.1.9', '1.1.10']; + } + + #[DataProvider('deepExpressions')] + public function testDependencyInjectionRejectsDeepExpressions(string $expression): void + { + try { + (new ExpressionLanguage())->lint($expression, []); + self::fail('An excessively nested expression was accepted.'); + } catch (SyntaxError $exception) { + self::assertStringContainsString('maximum nesting level is 256', $exception->getMessage()); + } + } + + /** @return iterable */ + public static function deepExpressions(): iterable + { + yield 'unary nesting' => [str_repeat('!', 300) . '1']; + + $expression = '1'; + for ($level = 0; $level < 60; ++$level) { + $expression = '(' . $expression . str_repeat(' + 1', 60) . ')'; + } + yield 'chained binary nesting missed by 8.1.6' => [$expression]; + } + + public function testOrdinaryDependencyInjectionExpressionStillWorks(): void + { + self::assertSame(3, (new ExpressionLanguage())->evaluate('1 + 2')); + } + + public function testInlineYamlLexerHonorsConfiguredNestingLimit(): void + { + $parser = new Parser(8); + self::assertSame(['root' => [[1]]], $parser->parse('root: [[1]]')); + + try { + $parser->parse('root: ' . str_repeat('[', 9)); + self::fail('The inline YAML lexer exceeded its configured nesting limit.'); + } catch (ParseException $exception) { + self::assertStringContainsString('Maximum nesting depth of 8 exceeded', $exception->getMessage()); + } + } +} From 161ac60ddb73a83b4bdc82dff42e3007793e11a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brian=20Sch=C3=A4ffner?= Date: Fri, 16 Oct 2026 14:35:53 +0200 Subject: [PATCH 2/2] fix: retain native debug cache warmer at lowest versions --- CHANGELOG.md | 1 + composer.json | 2 +- tests/Security/SymfonySecurityCompatibilityTest.php | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d4a188..f798625 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ where applicable. - Require Symfony ExpressionLanguage 8.1.9 and YAML 8.1.6 or newer to exclude CVE-2026-109449 and CVE-2026-109413. - Require SymPress Kernel 1.1.10 or newer to retain the corrected HttpFoundation 8.1.9 minimum in lowest-version installations. +- Require Symfony FrameworkBundle 8.1.8 or newer so the native development cache warmer is registered when the profiler is disabled. - Verify dependency version boundaries and rejection of excessively nested expressions and inline YAML collections. ## 1.0.6 — 2026-10-09 diff --git a/composer.json b/composer.json index d11e386..a75f13d 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "symfony/error-handler": "^8.1", "symfony/expression-language": "^8.1.9", "symfony/filesystem": "^8.0", - "symfony/framework-bundle": "^8.1", + "symfony/framework-bundle": "^8.1.8", "symfony/http-kernel": "^8.1", "symfony/routing": "^8.1", "symfony/service-contracts": "^3.6", diff --git a/tests/Security/SymfonySecurityCompatibilityTest.php b/tests/Security/SymfonySecurityCompatibilityTest.php index f1f9ecd..c42abff 100644 --- a/tests/Security/SymfonySecurityCompatibilityTest.php +++ b/tests/Security/SymfonySecurityCompatibilityTest.php @@ -31,6 +31,7 @@ public static function dependencyBoundaries(): iterable yield 'expression last affected patch' => ['symfony/expression-language', '8.1.8', '8.1.9']; yield 'yaml inline lexer' => ['symfony/yaml', '8.1.5', '8.1.6']; yield 'kernel header parser floor' => ['sympress/kernel', '1.1.9', '1.1.10']; + yield 'native development cache warmer' => ['symfony/framework-bundle', '8.1.7', '8.1.8']; } #[DataProvider('deepExpressions')]