mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-09-05 07:27:27 +08:00
fix(frontend): sanitize announcement HTML (#1039)
Sanitize HTML announcements in both the About page and startup notification through a shared DOMPurify helper. Add regression tests and bilingual changelog entries. Co-authored-by: tuanaiseo <tuanaiseo@gmail.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import axios from 'axios'
|
||||
import i18n from '../i18n'
|
||||
import { getFingerprint } from '../utils/fingerprint'
|
||||
import { safeBearerHeader, safeHeaderValue } from '../utils/headers'
|
||||
import { sanitizeHtml } from '../utils/sanitize-html'
|
||||
|
||||
const API_BASE = import.meta.env.VITE_API_BASE || "";
|
||||
const {
|
||||
@@ -123,7 +124,7 @@ const getOpenSettings = async (message, notification) => {
|
||||
notification.info({
|
||||
content: () => {
|
||||
return h("div", {
|
||||
innerHTML: announcement.value
|
||||
innerHTML: sanitizeHtml(announcement.value)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// @vitest-environment jsdom
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { sanitizeHtml } from '../sanitize-html';
|
||||
|
||||
describe('sanitizeHtml', () => {
|
||||
it('preserves safe announcement markup', () => {
|
||||
expect(sanitizeHtml('<strong>Notice</strong>')).toBe('<strong>Notice</strong>');
|
||||
});
|
||||
|
||||
it('removes executable markup and unsafe attributes', () => {
|
||||
const sanitized = sanitizeHtml(
|
||||
'<script>alert(1)</script><img src="x" onerror="alert(1)">'
|
||||
);
|
||||
|
||||
expect(sanitized).not.toContain('<script');
|
||||
expect(sanitized).not.toContain('onerror');
|
||||
expect(sanitized).toContain('<img src="x">');
|
||||
});
|
||||
|
||||
it('returns an empty string for non-string values', () => {
|
||||
expect(sanitizeHtml(null)).toBe('');
|
||||
expect(sanitizeHtml({ value: '<strong>unsafe ref</strong>' })).toBe('');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
export const sanitizeHtml = (html) => {
|
||||
return DOMPurify.sanitize(typeof html === 'string' ? html : '');
|
||||
};
|
||||
@@ -1,13 +1,16 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { GithubAlt, Discord, Telegram } from '@vicons/fa'
|
||||
import { useGlobalState } from '../../store'
|
||||
import { sanitizeHtml } from '../../utils/sanitize-html'
|
||||
const { announcement } = useGlobalState()
|
||||
const safeAnnouncement = computed(() => sanitizeHtml(announcement.value))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="center">
|
||||
<n-card :bordered="false" embedded>
|
||||
<div v-html="announcement"></div>
|
||||
<div v-html="safeAnnouncement"></div>
|
||||
<n-button tag="a" target="_blank" href="https://github.com/dreamhunter2333/cloudflare_temp_email">
|
||||
<template #icon>
|
||||
<n-icon :component="GithubAlt" />
|
||||
|
||||
Reference in New Issue
Block a user