Files
ny-exam-platform/docs/.vitepress/config.mjs.timestamp-1789051213693-e9e6067deebec.mjs
T
nxxy335 a3be81b261 fix(security): 修复上传名单文件可被 URL 直连访问(nginx 下可 getshell)
严重漏洞:roster_import 使用 $_FILES 的原始扩展名拼 roster_YYYYMMDD_HHMMSS.<ext>
落在 Web 根目录内的 data/uploads/,既无扩展名白名单(可上传 .php),文件名又
可按秒枚举;而 bootstrap 只写了 data/.htaccess,nginx 不读 .htaccess,
生产环境(nginx + PHP-FPM)下可直接远程代码执行。

修复(api.php roster_import 四层防护):
- 扩展名白名单:仅 xlsx / xlsm / csv / txt
- 随机文件名:bin2hex(random_bytes(16)),杜绝枚举
- 解析完成后 @unlink 立即删除,Web 目录下不留存任何上传文件
- 20MB 大小限制 + UPLOAD_ERR 检查

加固(bootstrap.php):data 及 cache/uploads/snapshots 每个目录都写
.htaccess(Deny from all)+ index.html 占位;README 与文档补充 nginx
location ^~ /data/ { deny all; return 404; } 规则。

测试:新增 e2e tools/test-upload-guard.js(11 断言,覆盖 .php/.phtml 被拒、
无残留、合法 csv 导入成功且即删、无可枚举文件名),并入 tests/run-all.sh。
全套 90 项通过。

docs: 新增 VitePress 文档站(18 页)
- 使用指南 12 页:简介/部署/快速上手/系统设置/名单管理/统计口径/试卷设置/
  快照趋势异常/导出打印/数据看板/随机抽取/常见问题
- 安全 2 页:安全总览(含本次漏洞复盘)与部署加固清单(P0-P2)
- 开发 4 页:架构与目录/接口一览/SQLite 存储/测试
- 配图迁移至 docs/public/images/;.gitignore 忽略文档构建产物
2026-09-10 22:42:13 +08:00

122 lines
15 KiB
JavaScript

// .vitepress/config.mjs
import { defineConfig } from "file:///C:/Users/Zhang/Documents/jc/ny-exam-platform/docs/node_modules/vitepress/dist/node/index.js";
var base = process.env.DOCS_BASE || "/";
var config_default = defineConfig({
base,
lang: "zh-CN",
title: "NY \u95EE\u5377\u8003\u8BD5\u7CFB\u7EDF\u6570\u636E\u5E73\u53F0",
description: "\u57FA\u4E8E PHP 8 + \u5377\u738B\uFF08SurveyKing\uFF09\u793E\u533A\u7248\u5F00\u653E API \u7684\u96F6\u4F9D\u8D56\u8003\u8BD5\u6570\u636E\u7EDF\u8BA1\u5E73\u53F0",
cleanUrls: true,
ignoreDeadLinks: true,
head: [
["meta", { name: "theme-color", content: "#2563eb" }],
["meta", { name: "referrer", content: "no-referrer" }]
],
themeConfig: {
// outlineTitle: '本页目录',
outline: [2, 3],
lastUpdated: { text: "\u6700\u540E\u66F4\u65B0\u4E8E" },
search: {
provider: "local",
options: {
locales: {
zh: {
translations: {
button: { buttonText: "\u641C\u7D22\u6587\u6863", buttonAriaLabel: "\u641C\u7D22\u6587\u6863" },
modal: {
noResultsText: "\u672A\u627E\u5230\u76F8\u5173\u7ED3\u679C",
resetButtonTitle: "\u6E05\u9664\u67E5\u8BE2\u6761\u4EF6",
footer: {
selectText: "\u9009\u62E9",
navigateText: "\u5207\u6362",
closeText: "\u5173\u95ED"
}
}
}
}
}
}
},
nav: [
{ text: "\u9996\u9875", link: "/" },
{ text: "\u4F7F\u7528\u6307\u5357", link: "/guide/introduction", activeMatch: "/guide/" },
{ text: "\u5B89\u5168", link: "/security/", activeMatch: "/security/" },
{ text: "\u5F00\u53D1", link: "/dev/architecture", activeMatch: "/dev/" }
],
sidebar: {
"/guide/": [
{
text: "\u5F00\u59CB",
items: [
{ text: "\u5E73\u53F0\u7B80\u4ECB", link: "/guide/introduction" },
{ text: "\u73AF\u5883\u8981\u6C42\u4E0E\u90E8\u7F72", link: "/guide/install" },
{ text: "\u5FEB\u901F\u4E0A\u624B", link: "/guide/quickstart" }
]
},
{
text: "\u6838\u5FC3\u529F\u80FD",
items: [
{ text: "\u7CFB\u7EDF\u8BBE\u7F6E", link: "/guide/settings" },
{ text: "\u540D\u5355\u7BA1\u7406", link: "/guide/roster" },
{ text: "\u6210\u7EE9\u660E\u7EC6\u4E0E\u7EDF\u8BA1\u53E3\u5F84", link: "/guide/scores" },
{ text: "\u8BD5\u5377\u8BBE\u7F6E\uFF08\u6EE1\u5206/\u5408\u683C\u7387/\u514D\u8003\uFF09", link: "/guide/project-config" },
{ text: "\u5FEB\u7167\u3001\u8D8B\u52BF\u4E0E\u5F02\u5E38\u68C0\u6D4B", link: "/guide/snapshot" },
{ text: "\u5BFC\u51FA\u4E0E\u6253\u5370", link: "/guide/export-print" }
]
},
{
text: "\u5176\u4ED6\u9875\u9762",
items: [
{ text: "\u6570\u636E\u770B\u677F", link: "/guide/dashboard" },
{ text: "\u968F\u673A\u62BD\u53D6", link: "/guide/draw" }
]
},
{
text: "\u5E2E\u52A9",
items: [
{ text: "\u5E38\u89C1\u95EE\u9898", link: "/guide/faq" }
]
}
],
"/security/": [
{
text: "\u5B89\u5168",
items: [
{ text: "\u5B89\u5168\u603B\u89C8", link: "/security/" },
{ text: "\u90E8\u7F72\u52A0\u56FA\u6E05\u5355", link: "/security/hardening" }
]
}
],
"/dev/": [
{
text: "\u5F00\u53D1",
items: [
{ text: "\u67B6\u6784\u4E0E\u76EE\u5F55", link: "/dev/architecture" },
{ text: "\u63A5\u53E3\u4E00\u89C8", link: "/dev/api" },
{ text: "\u6570\u636E\u5B58\u50A8\uFF08SQLite\uFF09", link: "/dev/database" },
{ text: "\u6D4B\u8BD5", link: "/dev/testing" }
]
}
]
},
socialLinks: [],
footer: {
message: "\u57FA\u4E8E PHP 8 + \u5377\u738B\uFF08SurveyKing\uFF09\u793E\u533A\u7248\u5F00\u653E API \u6784\u5EFA\uFF0C\u96F6\u7B2C\u4E09\u65B9\u8FD0\u884C\u4F9D\u8D56\u3002",
copyright: "Copyright \xA9 NY \u95EE\u5377\u8003\u8BD5\u7CFB\u7EDF\u6570\u636E\u5E73\u53F0"
},
docFooter: {
prev: "\u4E0A\u4E00\u9875",
next: "\u4E0B\u4E00\u9875"
},
returnToTopLabel: "\u56DE\u5230\u9876\u90E8",
sidebarMenuLabel: "\u83DC\u5355",
darkModeSwitchLabel: "\u4E3B\u9898",
lightModeSwitchTitle: "\u5207\u6362\u5230\u6D45\u8272\u6A21\u5F0F",
darkModeSwitchTitle: "\u5207\u6362\u5230\u6DF1\u8272\u6A21\u5F0F"
}
});
export {
config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLnZpdGVwcmVzcy9jb25maWcubWpzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiQzpcXFxcVXNlcnNcXFxcWmhhbmdcXFxcRG9jdW1lbnRzXFxcXGpjXFxcXG55LWV4YW0tcGxhdGZvcm1cXFxcZG9jc1xcXFwudml0ZXByZXNzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJDOlxcXFxVc2Vyc1xcXFxaaGFuZ1xcXFxEb2N1bWVudHNcXFxcamNcXFxcbnktZXhhbS1wbGF0Zm9ybVxcXFxkb2NzXFxcXC52aXRlcHJlc3NcXFxcY29uZmlnLm1qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vQzovVXNlcnMvWmhhbmcvRG9jdW1lbnRzL2pjL255LWV4YW0tcGxhdGZvcm0vZG9jcy8udml0ZXByZXNzL2NvbmZpZy5tanNcIjtpbXBvcnQgeyBkZWZpbmVDb25maWcgfSBmcm9tICd2aXRlcHJlc3MnXG5cbi8vIFx1OTBFOFx1N0Y3Mlx1NTIzMFx1NUI1MFx1OERFRlx1NUY4NFx1NjVGNlx1RkYwQ1x1Njc4NFx1NUVGQVx1NTI0RFx1OEJCRVx1N0Y2RVx1NzNBRlx1NTg4M1x1NTNEOFx1OTFDRlx1NTM3M1x1NTNFRlx1RkYxQVxuLy8gICBET0NTX0JBU0U9L255LWV4YW0tZG9jcy8gbnBtIHJ1biBkb2NzOmJ1aWxkXG5jb25zdCBiYXNlID0gcHJvY2Vzcy5lbnYuRE9DU19CQVNFIHx8ICcvJ1xuXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoe1xuICBiYXNlLFxuICBsYW5nOiAnemgtQ04nLFxuICB0aXRsZTogJ05ZIFx1OTVFRVx1NTM3N1x1ODAwM1x1OEJENVx1N0NGQlx1N0VERlx1NjU3MFx1NjM2RVx1NUU3M1x1NTNGMCcsXG4gIGRlc2NyaXB0aW9uOiAnXHU1N0ZBXHU0RThFIFBIUCA4ICsgXHU1Mzc3XHU3MzhCXHVGRjA4U3VydmV5S2luZ1x1RkYwOVx1NzkzRVx1NTMzQVx1NzI0OFx1NUYwMFx1NjUzRSBBUEkgXHU3Njg0XHU5NkY2XHU0RjlEXHU4RDU2XHU4MDAzXHU4QkQ1XHU2NTcwXHU2MzZFXHU3RURGXHU4QkExXHU1RTczXHU1M0YwJyxcbiAgY2xlYW5VcmxzOiB0cnVlLFxuICBpZ25vcmVEZWFkTGlua3M6IHRydWUsXG5cbiAgaGVhZDogW1xuICAgIFsnbWV0YScsIHsgbmFtZTogJ3RoZW1lLWNvbG9yJywgY29udGVudDogJyMyNTYzZWInIH1dLFxuICAgIFsnbWV0YScsIHsgbmFtZTogJ3JlZmVycmVyJywgY29udGVudDogJ25vLXJlZmVycmVyJyB9XVxuICBdLFxuXG4gIHRoZW1lQ29uZmlnOiB7XG4gICAgLy8gb3V0bGluZVRpdGxlOiAnXHU2NzJDXHU5ODc1XHU3NkVFXHU1RjU1JyxcbiAgICBvdXRsaW5lOiBbMiwgM10sXG4gICAgbGFzdFVwZGF0ZWQ6IHsgdGV4dDogJ1x1NjcwMFx1NTQwRVx1NjZGNFx1NjVCMFx1NEU4RScgfSxcblxuICAgIHNlYXJjaDoge1xuICAgICAgcHJvdmlkZXI6ICdsb2NhbCcsXG4gICAgICBvcHRpb25zOiB7XG4gICAgICAgIGxvY2FsZXM6IHtcbiAgICAgICAgICB6aDoge1xuICAgICAgICAgICAgdHJhbnNsYXRpb25zOiB7XG4gICAgICAgICAgICAgIGJ1dHRvbjogeyBidXR0b25UZXh0OiAnXHU2NDFDXHU3RDIyXHU2NTg3XHU2ODYzJywgYnV0dG9uQXJpYUxhYmVsOiAnXHU2NDFDXHU3RDIyXHU2NTg3XHU2ODYzJyB9LFxuICAgICAgICAgICAgICBtb2RhbDoge1xuICAgICAgICAgICAgICAgIG5vUmVzdWx0c1RleHQ6ICdcdTY3MkFcdTYyN0VcdTUyMzBcdTc2RjhcdTUxNzNcdTdFRDNcdTY3OUMnLFxuICAgICAgICAgICAgICAgIHJlc2V0QnV0dG9uVGl0bGU6ICdcdTZFMDVcdTk2NjRcdTY3RTVcdThCRTJcdTY3NjFcdTRFRjYnLFxuICAgICAgICAgICAgICAgIGZvb3Rlcjoge1xuICAgICAgICAgICAgICAgICAgc2VsZWN0VGV4dDogJ1x1OTAwOVx1NjJFOScsXG4gICAgICAgICAgICAgICAgICBuYXZpZ2F0ZVRleHQ6ICdcdTUyMDdcdTYzNjInLFxuICAgICAgICAgICAgICAgICAgY2xvc2VUZXh0OiAnXHU1MTczXHU5NUVEJ1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG5cbiAgICBuYXY6IFtcbiAgICAgIHsgdGV4dDogJ1x1OTk5Nlx1OTg3NScsIGxpbms6ICcvJyB9LFxuICAgICAgeyB0ZXh0OiAnXHU0RjdGXHU3NTI4XHU2MzA3XHU1MzU3JywgbGluazogJy9ndWlkZS9pbnRyb2R1Y3Rpb24nLCBhY3RpdmVNYXRjaDogJy9ndWlkZS8nIH0sXG4gICAgICB7IHRleHQ6ICdcdTVCODlcdTUxNjgnLCBsaW5rOiAnL3NlY3VyaXR5LycsIGFjdGl2ZU1hdGNoOiAnL3NlY3VyaXR5LycgfSxcbiAgICAgIHsgdGV4dDogJ1x1NUYwMFx1NTNEMScsIGxpbms6ICcvZGV2L2FyY2hpdGVjdHVyZScsIGFjdGl2ZU1hdGNoOiAnL2Rldi8nIH1cbiAgICBdLFxuXG4gICAgc2lkZWJhcjoge1xuICAgICAgJy9ndWlkZS8nOiBbXG4gICAgICAgIHtcbiAgICAgICAgICB0ZXh0OiAnXHU1RjAwXHU1OUNCJyxcbiAgICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAgeyB0ZXh0OiAnXHU1RTczXHU1M0YwXHU3QjgwXHU0RUNCJywgbGluazogJy9ndWlkZS9pbnRyb2R1Y3Rpb24nIH0sXG4gICAgICAgICAgICB7IHRleHQ6ICdcdTczQUZcdTU4ODNcdTg5ODFcdTZDNDJcdTRFMEVcdTkwRThcdTdGNzInLCBsaW5rOiAnL2d1aWRlL2luc3RhbGwnIH0sXG4gICAgICAgICAgICB7IHRleHQ6ICdcdTVGRUJcdTkwMUZcdTRFMEFcdTYyNEInLCBsaW5rOiAnL2d1aWRlL3F1aWNrc3RhcnQnIH1cbiAgICAgICAgICBdXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB0ZXh0OiAnXHU2ODM4XHU1RkMzXHU1MjlGXHU4MEZEJyxcbiAgICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAgeyB0ZXh0OiAnXHU3Q0ZCXHU3RURGXHU4QkJFXHU3RjZFJywgbGluazogJy9ndWlkZS9zZXR0aW5ncycgfSxcbiAgICAgICAgICAgIHsgdGV4dDogJ1x1NTQwRFx1NTM1NVx1N0JBMVx1NzQwNicsIGxpbms6ICcvZ3VpZGUvcm9zdGVyJyB9LFxuICAgICAgICAgICAgeyB0ZXh0OiAnXHU2MjEwXHU3RUU5XHU2NjBFXHU3RUM2XHU0RTBFXHU3RURGXHU4QkExXHU1M0UzXHU1Rjg0JywgbGluazogJy9ndWlkZS9zY29yZXMnIH0sXG4gICAgICAgICAgICB7IHRleHQ6ICdcdThCRDVcdTUzNzdcdThCQkVcdTdGNkVcdUZGMDhcdTZFRTFcdTUyMDYvXHU1NDA4XHU2ODNDXHU3Mzg3L1x1NTE0RFx1ODAwM1x1RkYwOScsIGxpbms6ICcvZ3VpZGUvcHJvamVjdC1jb25maWcnIH0sXG4gICAgICAgICAgICB7IHRleHQ6ICdcdTVGRUJcdTcxNjdcdTMwMDFcdThEOEJcdTUyQkZcdTRFMEVcdTVGMDJcdTVFMzhcdTY4QzBcdTZENEInLCBsaW5rOiAnL2d1aWRlL3NuYXBzaG90JyB9LFxuICAgICAgICAgICAgeyB0ZXh0OiAnXHU1QkZDXHU1MUZBXHU0RTBFXHU2MjUzXHU1MzcwJywgbGluazogJy9ndWlkZS9leHBvcnQtcHJpbnQnIH1cbiAgICAgICAgICBdXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB0ZXh0OiAnXHU1MTc2XHU0RUQ2XHU5ODc1XHU5NzYyJyxcbiAgICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAgeyB0ZXh0OiAnXHU2NTcwXHU2MzZFXHU3NzBCXHU2NzdGJywgbGluazogJy9ndWlkZS9kYXNoYm9hcmQnIH0sXG4gICAgICAgICAgICB7IHRleHQ6ICdcdTk2OEZcdTY3M0FcdTYyQkRcdTUzRDYnLCBsaW5rOiAnL2d1aWRlL2RyYXcnIH1cbiAgICAgICAgICBdXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICB0ZXh0OiAnXHU1RTJFXHU1MkE5JyxcbiAgICAgICAgICBpdGVtczogW1xuICAgICAgICAgICAgeyB0ZXh0OiAnXHU1RTM4XHU4OUMxXHU5NUVFXHU5ODk4JywgbGluazogJy9ndWlkZS9mYXEnIH1cbiAgICAgICAgICBdXG4gICAgICAgIH1cbiAgICAgIF0sXG4gICAgICAnL3NlY3VyaXR5Lyc6IFtcbiAgICAgICAge1xuICAgICAgICAgIHRleHQ6ICdcdTVCODlcdTUxNjgnLFxuICAgICAgICAgIGl0ZW1zOiBbXG4gICAgICAgICAgICB7IHRleHQ6ICdcdTVCODlcdTUxNjhcdTYwM0JcdTg5QzgnLCBsaW5rOiAnL3NlY3VyaXR5LycgfSxcbiAgICAgICAgICAgIHsgdGV4dDogJ1x1OTBFOFx1N0Y3Mlx1NTJBMFx1NTZGQVx1NkUwNVx1NTM1NScsIGxpbms6ICcvc2VjdXJpdHkvaGFyZGVuaW5nJyB9XG4gICAgICAgICAgXVxuICAgICAgICB9XG4gICAgICBdLFxuICAgICAgJy9kZXYvJzogW1xuICAgICAgICB7XG4gICAgICAgICAgdGV4dDogJ1x1NUYwMFx1NTNEMScsXG4gICAgICAgICAgaXRlbXM6IFtcbiAgICAgICAgICAgIHsgdGV4dDogJ1x1NjdCNlx1Njc4NFx1NEUwRVx1NzZFRVx1NUY1NScsIGxpbms6ICcvZGV2L2FyY2hpdGVjdHVyZScgfSxcbiAgICAgICAgICAgIHsgdGV4dDogJ1x1NjNBNVx1NTNFM1x1NEUwMFx1ODlDOCcsIGxpbms6ICcvZGV2L2FwaScgfSxcbiAgICAgICAgICAgIHsgdGV4dDogJ1x1NjU3MFx1NjM2RVx1NUI1OFx1NTBBOFx1RkYwOFNRTGl0ZVx1RkYwOScsIGxpbms6ICcvZGV2L2RhdGFiYXNlJyB9LFxuICAgICAgICAgICAgeyB0ZXh0OiAnXHU2RDRCXHU4QkQ1JywgbGluazogJy9kZXYvdGVzdGluZycgfVxuICAgICAgICAgIF1cbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0sXG5cbiAgICBzb2NpYWxMaW5rczogW10sXG5cbiAgICBmb290ZXI6IHtcbiAgICAgIG1lc3NhZ2U6ICdcdTU3RkFcdTRFOEUgUEhQIDggKyBcdTUzNzdcdTczOEJcdUZGMDhTdXJ2ZXlLaW5nXHVGRjA5XHU3OTNFXHU1MzNBXHU3MjQ4XHU1RjAwXHU2NTNFIEFQSSBcdTY3ODRcdTVFRkFcdUZGMENcdTk2RjZcdTdCMkNcdTRFMDlcdTY1QjlcdThGRDBcdTg4NENcdTRGOURcdThENTZcdTMwMDInLFxuICAgICAgY29weXJpZ2h0OiAnQ29weXJpZ2h0IFx1MDBBOSBOWSBcdTk1RUVcdTUzNzdcdTgwMDNcdThCRDVcdTdDRkJcdTdFREZcdTY1NzBcdTYzNkVcdTVFNzNcdTUzRjAnXG4gICAgfSxcblxuICAgIGRvY0Zvb3Rlcjoge1xuICAgICAgcHJldjogJ1x1NEUwQVx1NEUwMFx1OTg3NScsXG4gICAgICBuZXh0OiAnXHU0RTBCXHU0RTAwXHU5ODc1J1xuICAgIH0sXG5cbiAgICByZXR1cm5Ub1RvcExhYmVsOiAnXHU1NkRFXHU1MjMwXHU5ODc2XHU5MEU4JyxcbiAgICBzaWRlYmFyTWVudUxhYmVsOiAnXHU4M0RDXHU1MzU1JyxcbiAgICBkYXJrTW9kZVN3aXRjaExhYmVsOiAnXHU0RTNCXHU5ODk4JyxcbiAgICBsaWdodE1vZGVTd2l0Y2hUaXRsZTogJ1x1NTIwN1x1NjM2Mlx1NTIzMFx1NkQ0NVx1ODI3Mlx1NkEyMVx1NUYwRicsXG4gICAgZGFya01vZGVTd2l0Y2hUaXRsZTogJ1x1NTIwN1x1NjM2Mlx1NTIzMFx1NkRGMVx1ODI3Mlx1NkEyMVx1NUYwRidcbiAgfVxufSlcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBOFcsU0FBUyxvQkFBb0I7QUFJM1ksSUFBTSxPQUFPLFFBQVEsSUFBSSxhQUFhO0FBRXRDLElBQU8saUJBQVEs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