fix: XSS prevention and frontend timer cleanup
- Add DOMPurify to sanitize all v-html content - Create sanitize.js utility with sanitizeHtml() - Wrap renderMarkdown output in Step4Report and Step5Interaction - Guard all setInterval calls with clearInterval to prevent timer leaks
This commit is contained in:
parent
985f89f49a
commit
af5c1c6841
|
|
@ -11,6 +11,7 @@
|
|||
"dependencies": {
|
||||
"axios": "^1.13.2",
|
||||
"d3": "^7.9.0",
|
||||
"dompurify": "^3.3.3",
|
||||
"vue": "^3.5.24",
|
||||
"vue-router": "^4.6.3"
|
||||
},
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -464,10 +464,12 @@ let statusTimer = null
|
|||
let detailTimer = null
|
||||
|
||||
const startStatusPolling = () => {
|
||||
if (statusTimer) clearInterval(statusTimer)
|
||||
statusTimer = setInterval(fetchRunStatus, 2000)
|
||||
}
|
||||
|
||||
const startDetailPolling = () => {
|
||||
if (detailTimer) clearInterval(detailTimer)
|
||||
detailTimer = setInterval(fetchRunStatusDetail, 3000)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -393,6 +393,7 @@
|
|||
import { ref, computed, watch, onMounted, onUnmounted, nextTick, h, reactive } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { getAgentLog, getConsoleLog } from '../api/report'
|
||||
import { sanitizeHtml } from '../utils/sanitize.js'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
|
|
@ -1968,7 +1969,7 @@ const renderMarkdown = (content) => {
|
|||
}
|
||||
html = tokens.join('')
|
||||
|
||||
return html
|
||||
return sanitizeHtml(html)
|
||||
}
|
||||
|
||||
const getTimelineItemClass = (log, idx, total) => {
|
||||
|
|
|
|||
|
|
@ -413,6 +413,7 @@
|
|||
<script setup>
|
||||
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
|
||||
import { chatWithReport, getReport, getAgentLog } from '../api/report'
|
||||
import { sanitizeHtml } from '../utils/sanitize.js'
|
||||
import { interviewAgents, getSimulationProfilesRealtime } from '../api/simulation'
|
||||
|
||||
const props = defineProps({
|
||||
|
|
@ -635,7 +636,7 @@ const renderMarkdown = (content) => {
|
|||
}
|
||||
html = tokens.join('')
|
||||
|
||||
return html
|
||||
return sanitizeHtml(html)
|
||||
}
|
||||
|
||||
// Chat Methods
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
import DOMPurify from 'dompurify'
|
||||
|
||||
export function sanitizeHtml(html) {
|
||||
if (!html) return ''
|
||||
return DOMPurify.sanitize(html)
|
||||
}
|
||||
|
|
@ -292,6 +292,7 @@ const startBuildGraph = async () => {
|
|||
const startGraphPolling = () => {
|
||||
addLog('Started polling for graph data...')
|
||||
fetchGraphData()
|
||||
if (graphPollTimer) clearInterval(graphPollTimer)
|
||||
graphPollTimer = setInterval(fetchGraphData, 10000)
|
||||
}
|
||||
|
||||
|
|
@ -315,6 +316,7 @@ const fetchGraphData = async () => {
|
|||
|
||||
const startPollingTask = (taskId) => {
|
||||
pollTaskStatus(taskId)
|
||||
if (pollTimer) clearInterval(pollTimer)
|
||||
pollTimer = setInterval(() => pollTaskStatus(taskId), 2000)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue