如何解决Express用res.send返回axios获取的数组时Checkmarx报XSS风险问题
解决方案
首先明确风险本质:你调用的外部API返回的response.data属于不可信数据源,Checkmarx误判的核心原因是默认res.send可能返回HTML类型响应,浏览器如果将内容当做HTML解析时,恶意脚本会被执行。你返回的是数组对象用于列表渲染,完全不需要执行任何HTML/JS代码,通过以下方式即可解决问题,且不影响前端正常解析:
- 方案1:优先使用
res.json替代res.send
Express内置的res.json方法会自动做两件事:将传入的对象/数组序列化为标准JSON格式,自动设置响应头Content-Type: application/json; charset=utf-8,明确告诉浏览器当前响应是JSON数据,不会当做HTML解析,从根源避免XSS风险,同时大部分安全扫描工具会识别该方法的语义,不会误报。
代码示例:
router.post(someurl, (req, res) => { axios.get(someurl) .then(response => { res.json(response.data); }) })
前端收到响应后可直接解析使用,不需要做任何额外处理。
- 方案2:显式设置响应头(适配特殊扫描规则)
如果因为业务原因必须使用res.send,可以手动显式声明JSON响应头,让扫描工具识别到你返回的不是HTML内容:
router.post(someurl, (req, res) => { axios.get(someurl) .then(response => { res.setHeader('Content-Type', 'application/json; charset=utf-8'); res.send(response.data); }) })
- 方案3:对数据做HTML转义(满足最严格的扫描要求)
如果你们的安全规则要求必须对所有不可信数据做编码处理,可以递归转义数据中所有字符串的HTML特殊字符,编码后的数据前端可以正常解析,渲染列表时不会出现格式问题:
// HTML特殊字符转义函数 function escapeHtml(str) { return typeof str === 'string' ? str.replace(/[&<>"']/g, char => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[char])) : str; } // 递归处理所有嵌套对象/数组的字符串值 function sanitizeData(data) { if (Array.isArray(data)) return data.map(item => sanitizeData(item)); if (data && typeof data === 'object') { return Object.fromEntries( Object.entries(data).map(([k, v]) => [k, sanitizeData(v)]) ); } return escapeHtml(data); } // 接口中使用 router.post(someurl, (req, res) => { axios.get(someurl) .then(response => { const safeData = sanitizeData(response.data); res.json(safeData); }) })
注意:如果前端有富文本渲染需求,不要在后端做全局转义,改为前端渲染富文本时做标签白名单过滤即可。
内容的提问来源于stack exchange,提问作者Vicky Singh Gill
相关产品推荐
相关产品推荐

