update lock clucknut
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 14s
Build, Push and Deploy / build-and-push (push) Successful in 3m14s
Build, Push and Deploy / deploy-staging (push) Successful in 25s
Build, Push and Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-04-18 20:32:18 +07:00
parent 4554035227
commit dcaf267458
3359 changed files with 153185 additions and 205489 deletions

View File

@@ -6,6 +6,21 @@ # Change Log
## [Unreleased][unreleased]
## [2.8.2] - 2026-03-19
This is a **security release** to address an issue where the `allowed_domains` setting for the `Embed` extension can be bypassed, resulting in a possible SSRF and XSS vulnerabilities.
### Fixed
- Fixed `DomainFilteringAdapter` hostname boundary bypass where domains like `youtube.com.evil` could match an allowlist entry for `youtube.com` (GHSA-hh8v-hgvp-g3f5)
## [2.8.1] - 2026-03-05
This is a **security release** to address an issue where `DisallowedRawHtml` can be bypassed, resulting in a possible cross-site scripting (XSS) vulnerability.
### Fixed
- Fixed `DisallowedRawHtmlRenderer` not blocking raw HTML tags with trailing ASCII whitespace (GHSA-4v6x-c7xx-hw9f)
- Fixed PHP 8.5 deprecation (#1107)
## [2.8.0] - 2025-11-26
### Added
@@ -717,7 +732,9 @@ ### Deprecated
- Alternative 1: Use `CommonMarkConverter` or `GithubFlavoredMarkdownConverter` if you don't need to customize the environment
- Alternative 2: Instantiate a new `Environment` and add the necessary extensions yourself
[unreleased]: https://github.com/thephpleague/commonmark/compare/2.8.0...HEAD
[unreleased]: https://github.com/thephpleague/commonmark/compare/2.8.2...HEAD
[2.8.2]: https://github.com/thephpleague/commonmark/compare/2.8.1...2.8.2
[2.8.1]: https://github.com/thephpleague/commonmark/compare/2.8.0...2.8.1
[2.8.0]: https://github.com/thephpleague/commonmark/compare/2.7.1...2.8.0
[2.7.1]: https://github.com/thephpleague/commonmark/compare/2.7.0...2.7.1
[2.7.0]: https://github.com/thephpleague/commonmark/compare/2.6.2...2.7.0

View File

@@ -42,9 +42,9 @@
"phpstan/phpstan": "^1.8.2",
"phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0",
"scrutinizer/ocular": "^1.8.1",
"symfony/finder": "^5.3 | ^6.0 | ^7.0",
"symfony/process": "^5.4 | ^6.0 | ^7.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
"symfony/finder": "^5.3 | ^6.0 | ^7.0 || ^8.0",
"symfony/process": "^5.4 | ^6.0 | ^7.0 || ^8.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0 || ^8.0",
"unleashedtech/php-coding-standard": "^3.1.1",
"vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
},

View File

@@ -45,7 +45,7 @@ public function render(Node $node, ChildNodeRendererInterface $childRenderer): ?
return $rendered;
}
$regex = \sprintf('/<(\/?(?:%s)[ \/>])/i', \implode('|', \array_map('preg_quote', $tags)));
$regex = \sprintf('/<(\/?(?:%s)[\s\/>])/i', \implode('|', \array_map('preg_quote', $tags)));
// Match these types of tags: <title> </title> <title x="sdf"> <title/> <title />
return \preg_replace($regex, '&lt;$1', $rendered);

View File

@@ -17,16 +17,16 @@ class DomainFilteringAdapter implements EmbedAdapterInterface
{
private EmbedAdapterInterface $decorated;
/** @psalm-var non-empty-string */
private string $regex;
/** @var string[] */
private array $allowedDomains;
/**
* @param string[] $allowedDomains
*/
public function __construct(EmbedAdapterInterface $decorated, array $allowedDomains)
{
$this->decorated = $decorated;
$this->regex = self::createRegex($allowedDomains);
$this->decorated = $decorated;
$this->allowedDomains = \array_map('strtolower', $allowedDomains);
}
/**
@@ -34,20 +34,29 @@ public function __construct(EmbedAdapterInterface $decorated, array $allowedDoma
*/
public function updateEmbeds(array $embeds): void
{
$this->decorated->updateEmbeds(\array_values(\array_filter($embeds, function (Embed $embed): bool {
return \preg_match($this->regex, $embed->getUrl()) === 1;
})));
$this->decorated->updateEmbeds(\array_values(\array_filter($embeds, [$this, 'isAllowed'])));
}
/**
* @param string[] $allowedDomains
*
* @psalm-return non-empty-string
*/
private static function createRegex(array $allowedDomains): string
private function isAllowed(Embed $embed): bool
{
$allowedDomains = \array_map('preg_quote', $allowedDomains);
$url = $embed->getUrl();
$scheme = \parse_url($url, \PHP_URL_SCHEME);
if ($scheme === null || $scheme === false) {
// Bare domain (no scheme) - assume https:// so parse_url can extract the host
$url = 'https://' . $url;
} elseif (\strtolower($scheme) !== 'http' && \strtolower($scheme) !== 'https') {
return false;
}
return '/^(?:https?:\/\/)?(?:[^.]+\.)*(' . \implode('|', $allowedDomains) . ')/';
$host = \parse_url($url, \PHP_URL_HOST);
$host = \strtolower(\rtrim((string) $host, '.'));
foreach ($this->allowedDomains as $domain) {
if ($host === $domain || \str_ends_with($host, '.' . $domain)) {
return true;
}
}
return false;
}
}

View File

@@ -56,7 +56,7 @@ public static function unescapeAndEncode(string $uri): string
}
}
if (\ord($code) < 128) {
if (\strlen($code) === 1 && \ord($code) < 128) {
$result .= self::ENCODE_CACHE[\ord($code)];
continue;
}

View File

@@ -1,4 +1,4 @@
Copyright (c) 2013-2024 Frank de Jonge
Copyright (c) 2013-2026 Frank de Jonge
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,4 +1,4 @@
Copyright (c) 2013-2024 Frank de Jonge
Copyright (c) 2013-2026 Frank de Jonge
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -48,7 +48,7 @@ ### Third party Adapters
* **[Uploadcare](https://github.com/vormkracht10/flysystem-uploadcare)**
* **[Useful adapters (FallbackAdapter, LogAdapter, ReadWriteAdapter, RetryAdapter)](https://github.com/ElGigi/FlysystemUsefulAdapters)**
* **[Metadata Cache](https://github.com/jgivoni/flysystem-cache-adapter)**
* **[Migration adapter (lazy)](https://github.com/antonsacred/flysystem-lazy-migration-adapter)**
You can always [create an adapter](https://flysystem.thephpleague.com/docs/advanced/creating-an-adapter/) yourself.