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:
@@ -0,0 +1,67 @@
|
||||
# Sanitizer for rich text that a human authored in the admin panel and that the
|
||||
# panel later renders with `dangerouslySetInnerHTML` (BlogReviewPage).
|
||||
#
|
||||
# آدیت ۲۰۲۶-۰۸-۰۷: بدنهٔ مقاله همانطور که میآمد ذخیره و رندر میشد. CSP فعلی
|
||||
# (`script-src 'self'`) اسکریپت تزریقی را اجرا نمیکند، ولی هندلرهای inline و
|
||||
# `javascript:` را کامل نمیبندد — و CSP لایهٔ دوم است، نه اولین دفاع. پاکسازی
|
||||
# هنگام **ذخیره** انجام میشود نه هنگام نمایش، چون یک نقطهٔ ورود دارد و هر
|
||||
# مصرفکنندهٔ بعدی (پنل، سایت عمومی، فید) خودبهخود امن میشود.
|
||||
#
|
||||
# فهرست عناصر = چیزی که CKEditor 5 واقعاً تولید میکند. عنصری که اینجا نیست حذف
|
||||
# میشود ولی متنش میماند، پس محتوای قدیمی نامفهوم نمیشود.
|
||||
framework:
|
||||
html_sanitizer:
|
||||
sanitizers:
|
||||
blog.body:
|
||||
allow_safe_elements: true
|
||||
allow_elements:
|
||||
p: []
|
||||
br: []
|
||||
hr: []
|
||||
strong: []
|
||||
b: []
|
||||
em: []
|
||||
i: []
|
||||
u: []
|
||||
s: []
|
||||
sub: []
|
||||
sup: []
|
||||
mark: []
|
||||
h1: []
|
||||
h2: []
|
||||
h3: []
|
||||
h4: []
|
||||
h5: []
|
||||
h6: []
|
||||
ul: []
|
||||
ol: ['start', 'reversed']
|
||||
li: []
|
||||
blockquote: []
|
||||
pre: []
|
||||
code: []
|
||||
figure: ['class']
|
||||
figcaption: []
|
||||
span: []
|
||||
div: []
|
||||
a: ['href', 'title', 'target', 'rel']
|
||||
img: ['src', 'alt', 'title', 'width', 'height']
|
||||
table: []
|
||||
thead: []
|
||||
tbody: []
|
||||
tfoot: []
|
||||
tr: []
|
||||
td: ['colspan', 'rowspan']
|
||||
th: ['colspan', 'rowspan', 'scope']
|
||||
# فقط طرحهای امن. `javascript:` عمداً نیست.
|
||||
allowed_link_schemes: ['http', 'https', 'mailto']
|
||||
allowed_media_schemes: ['http', 'https', 'data']
|
||||
allow_relative_links: true
|
||||
# لینک بیرونی در تب جدید باز میشود؛ بدون اینها tabnabbing باز است.
|
||||
force_attributes:
|
||||
a:
|
||||
rel: 'noopener noreferrer'
|
||||
# `drop` نه `block`: block فقط تگ را برمیدارد و متنِ داخلش را نگه
|
||||
# میدارد، یعنی `<script>alert(1)</script>` به متنِ `alert(1)` تبدیل
|
||||
# میشد. برای این عناصر، خودِ محتوا هم باید برود.
|
||||
drop_elements: ['script', 'style', 'iframe', 'object', 'embed', 'form', 'input', 'button', 'noscript']
|
||||
max_input_length: 500000
|
||||
@@ -653,7 +653,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* time_based_uuid_node?: scalar|Param|null,
|
||||
* },
|
||||
* html_sanitizer?: bool|array{ // HtmlSanitizer configuration
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* enabled?: bool|Param, // Default: true
|
||||
* sanitizers?: array<string, array{ // Default: []
|
||||
* allow_safe_elements?: bool|Param, // Allows "safe" elements and attributes. // Default: false
|
||||
* allow_static_elements?: bool|Param, // Allows all static elements and attributes from the W3C Sanitizer API standard. // Default: false
|
||||
|
||||
@@ -118,6 +118,11 @@ services:
|
||||
$terminalId: '%env(default::MELLAT_TERMINAL_ID)%'
|
||||
$username: '%env(default::MELLAT_USERNAME)%'
|
||||
$password: '%env(default::MELLAT_PASSWORD)%'
|
||||
# اعتبارنامهٔ نمایشیِ banktest.ir — عمومی است، ولی از `src/` بیرون
|
||||
# کشیده شد تا در کد رشتهٔ پسوردمانند نماند (آدیت ۲۰۲۶-۰۸-۰۷).
|
||||
$sandboxTerminalId: '%env(default::MELLAT_SANDBOX_TERMINAL_ID)%'
|
||||
$sandboxUsername: '%env(default::MELLAT_SANDBOX_USERNAME)%'
|
||||
$sandboxPassword: '%env(default::MELLAT_SANDBOX_PASSWORD)%'
|
||||
|
||||
App\Payment\Gateway\SepGateway:
|
||||
arguments:
|
||||
|
||||
Reference in New Issue
Block a user