fix: 修复学生代码窃取 token、提示词链 XSS 和打分没有上限的问题

- 运行提交代码的 iframe(编辑器预览、随机评分弹窗、/submission/:id、全屏预览)
  加上 sandbox,不给 allow-same-origin,代码读不到 localStorage 里的 token
- 提示词和 AI 回复的 markdown 渲染时转义原始 HTML,链接只放行 http(s)/mailto;
  ChainModal 也改用这个渲染函数
- 打分限定 1-5 分(超出返回 422),不能给自己的提交打分

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-26 21:33:26 +08:00
1 parent 4014aaabbf
commit 73788c4595
8 files changed
+78 -34

No files matched your search

+17 -5
View File
@@ -42,7 +42,11 @@
</n-flex>
</n-flex>
<div class="iframe-wrapper" :style="iframeWrapperStyle">
<iframe class="iframe" :srcdoc="previewContent"></iframe>
<iframe
class="iframe"
:sandbox="PREVIEW_SANDBOX"
:srcdoc="previewContent"
></iframe>
</div>
</template>
<script lang="ts" setup>
@@ -54,7 +58,10 @@ import { submission } from "../../store/submission"
import { useMessage } from "naive-ui"
import { Icon } from "@iconify/vue"
import copy from "copy-text-to-clipboard"
import { buildPreviewDocument } from "../../utils/previewDocument"
import {
buildPreviewDocument,
PREVIEW_SANDBOX,
} from "../../utils/previewDocument"
interface Props {
html: string
@@ -145,9 +152,14 @@ function open() {
} else {
const newTab = window.open("about:blank", "_blank")
if (!newTab) return
newTab.document.open()
newTab.document.write(getContent())
newTab.document.close()
// 新标签页和本站同源,代码要放进带 sandbox 的 iframe 里跑
const doc = newTab.document
doc.open()
doc.write(
`<!DOCTYPE html><title>预览</title><style>html,body,iframe{margin:0;width:100%;height:100%;border:0;display:block}</style><iframe sandbox="${PREVIEW_SANDBOX}"></iframe>`,
)
doc.close()
doc.querySelector("iframe")!.srcdoc = getContent()
}
}