feat: add BlogBodySanitizer for HTML sanitization on article save

- Implemented BlogBodySanitizer to clean HTML content before saving articles, ensuring security against XSS attacks.
- Added tests for BlogBodySanitizer to verify that unsafe tags and attributes are stripped from the content.
- Introduced ApiLeastPrivilegeTest to ensure that unauthorized users cannot access sensitive API routes, maintaining strict access control.
This commit is contained in:
hamed
2026-08-07 21:13:38 +03:30
parent a4a24c51af
commit 6876135a53
114 changed files with 2067 additions and 269 deletions
+37
View File
@@ -0,0 +1,37 @@
<?php
namespace App\Blog\Service;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HtmlSanitizer\HtmlSanitizerInterface;
/**
* پاک‌سازی HTML بدنهٔ مقاله در **لحظهٔ ذخیره**.
*
* بدنهٔ مقاله را ادمین با CKEditor می‌نویسد و پنل بعداً با
* `dangerouslySetInnerHTML` رندرش می‌کند (BlogReviewPage). تا پیش از این، هرچه
* می‌آمد همان ذخیره و همان رندر می‌شد.
*
* چرا هنگام ذخیره و نه هنگام نمایش: بدنه چند مصرف‌کننده دارد — پنل ادمین، سایت
* عمومی `nobat724_front` و فید. اگر پاک‌سازی در لایهٔ نمایش بود، هر مصرف‌کنندهٔ
* تازه دوباره آسیب‌پذیر شروع می‌کرد. یک نقطهٔ ورود، یک تضمین.
*
* چرا با وجود CSP: هدر فعلی `script-src 'self'` است و `<script>` تزریقی را اجرا
* نمی‌کند، ولی CSP لایهٔ دوم است نه اولین دفاع، و هندلرهای inline و لینک
* `javascript:` را کامل نمی‌بندد.
*
* سیاست عناصر در `config/packages/html_sanitizer.yaml` است، نه اینجا: همان‌جا
* جای پیکربندی است و تغییرش نباید کد لازم داشته باشد.
*/
class BlogBodySanitizer
{
public function __construct(
#[Autowire(service: 'html_sanitizer.sanitizer.blog.body')]
private readonly HtmlSanitizerInterface $sanitizer,
) {}
public function clean(string $html): string
{
return $this->sanitizer->sanitize($html);
}
}