diff --git a/.github/workflows/tasks.yml b/.github/workflows/tasks.yml
index 4827bdf..e6e0c59 100644
--- a/.github/workflows/tasks.yml
+++ b/.github/workflows/tasks.yml
@@ -9,8 +9,10 @@ jobs:
strategy:
fail-fast: false
matrix:
- php: [ '8.2', '8.3', '8.4' ]
+ php: [ '8.2', '8.3', '8.4', '8.5' ]
typo3: [ '12', '13' ]
+ env:
+ COMPOSER_AUTH: ${{ secrets.TYPO3_ELTS_COMPOSER_AUTH }}
steps:
- name: Setup PHP with PECL extension
uses: shivammathur/setup-php@v2
@@ -23,6 +25,14 @@ jobs:
key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.php }}-composer-
- - run: composer require typo3/minimal="^${{ matrix.typo3 }}" --dev --ignore-platform-req=php+
- - run: composer install --no-interaction --no-progress --ignore-platform-req=php+
+ # CI-only alias: TYPO3 still requires ~0.22; 1.0.0 fixes its security advisories.
+ # Remove the alias when TYPO3 accepts ^1.0.
+ - name: Configure TYPO3 ELTS when an authorized test license is available
+ if: (matrix.typo3 == '11' || matrix.typo3 == '12') && vars.TYPO3_ELTS_REPOSITORY_URL != ''
+ env:
+ TYPO3_ELTS_REPOSITORY_URL: ${{ vars.TYPO3_ELTS_REPOSITORY_URL }}
+ run: composer config --global repositories.typo3-elts composer "$TYPO3_ELTS_REPOSITORY_URL"
+ - run: TYPO3_SKIP_ASSET_PUBLISH=true composer require typo3/minimal="^${{ matrix.typo3 }}" "enshrined/svg-sanitize:1.0.0 as 0.22.99" --dev --no-scripts --sort-packages -W
+ - run: composer install --no-interaction --no-progress
+ - run: bash tests/typo3-svg-sanitizer.sh
- run: ./vendor/bin/grumphp run --ansi
diff --git a/composer.json b/composer.json
index a1ba01f..5c92c6f 100644
--- a/composer.json
+++ b/composer.json
@@ -6,7 +6,7 @@
],
"type": "typo3-cms-extension",
"require": {
- "php": "~8.2.0 || ~8.3.0 || ~8.4.0",
+ "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
"typo3/cms-core": "^12.4 || ^13.4",
"typo3/cms-frontend": "^12.4 || ^13.4"
},
diff --git a/docs/php85-ci.md b/docs/php85-ci.md
new file mode 100644
index 0000000..bd3e0d0
--- /dev/null
+++ b/docs/php85-ci.md
@@ -0,0 +1,5 @@
+PHP 8.5 CI retains the existing TYPO3 support. Public TYPO3 11/12 releases are currently blocked by security advisories.
+
+To run these jobs with a license authorized for extension testing, configure the GitHub Actions repository variable `TYPO3_ELTS_REPOSITORY_URL` with the Composer repository URL supplied by the license provider, and the Actions secret `TYPO3_ELTS_COMPOSER_AUTH` with the Composer auth JSON for that repository. CI does not print credential values. A customer license must be authorized for this use before being configured.
+
+Do not disable Composer security blocking or remove older supported TYPO3 versions to pass CI. Keep the PR as a draft until all retained jobs pass.
diff --git a/tests/typo3-svg-sanitizer.sh b/tests/typo3-svg-sanitizer.sh
new file mode 100644
index 0000000..9ae3fdd
--- /dev/null
+++ b/tests/typo3-svg-sanitizer.sh
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+# Exercise TYPO3's adapter against the actual security-fixed release, not its CI alias.
+php <<'PHP'
+'
+ . ''
+ . '';
+$clean = $sanitizer->sanitizeContent($svg);
+check(str_contains($clean, 'id="safe"'), 'Valid SVG content was removed');
+check(!str_contains($clean, 'onload'), 'Event handler was not removed');
+check(!str_contains($clean, 'example.invalid'), 'Remote reference was not removed');
+
+$entity = ']>'
+ . '';
+check($sanitizer->sanitizeContent($entity) === '', 'DTD entity bypass was not rejected');
+
+$document = new DOMDocument();
+check($document->loadXML($svg), 'Failed to load SVG fixture');
+$node = $sanitizer->sanitizeNode($document->documentElement);
+$cleanNode = $document->saveXML($node);
+check(str_contains($cleanNode, 'id="safe"'), 'sanitizeNode removed valid content');
+check(!str_contains($cleanNode, 'onload'), 'sanitizeNode retained an event handler');
+check(!str_contains($cleanNode, 'example.invalid'), 'sanitizeNode retained a remote reference');
+
+$file = tempnam(sys_get_temp_dir(), 'typo3-svg-');
+check($file !== false, 'Failed to create temporary SVG fixture');
+try {
+ check(file_put_contents($file, $svg) !== false, 'Failed to write SVG fixture');
+ $sanitizer->sanitizeFile($file);
+ check(file_get_contents($file) === $clean, 'sanitizeFile produced unexpected output');
+} finally {
+ unlink($file);
+}
+
+echo "PASS: TYPO3 SVG content, node, file and DTD entity regression checks\n";
+PHP