feat: create SanitizeBlogBodiesCommand to clean existing blog bodies according to current HTML sanitization policies test: add AppointmentTreatmentSessionLinkTest to ensure appointment booking functionality works correctly with treatment session links
73 lines
3.9 KiB
YAML
73 lines
3.9 KiB
YAML
# 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']
|
|
# سه attributeِ ظاهریِ قدیمیِ جدول عمداً مجازند. هیچکدام
|
|
# نمیتوانند حاملِ اسکریپت یا URL باشند — مقدارشان عدد است — و
|
|
# بدونشان جدولِ صدها مقالهٔ موجود حاشیه و فاصلهاش را از دست
|
|
# میداد. `style` همچنان ممنوع است: تنها attributeِ ظاهریِ این
|
|
# جمع که میتواند بارِ اجرایی حمل کند.
|
|
table: ['border', 'cellpadding', 'cellspacing']
|
|
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
|