在Node.js中使用eval/Function构建HTML模板引擎是否安全及有无最佳实践
安全性评估
- 存在严重的高危安全漏洞,绝对不可直接用于生产环境
- 漏洞原因1:代码注入风险
你直接将外部传入的
template字符串拼接进Function构造函数的代码体中,如果template是用户可控的,攻击者可以通过构造特殊字符串闭合模板字符串,插入任意JavaScript代码执行,可实现窃取用户Cookie、篡改页面内容、调用接口执行高危操作等恶意行为。 - 漏洞原因2:XSS跨站脚本风险
就算模板完全由你自己可控,渲染时传入的
props如果包含用户输入的内容,直接插入HTML不会做任何转义,也会触发存储型或反射型XSS漏洞。 - 可使用场景限制
仅在你能100%保证模板字符串完全由你自己编写、无任何外部可控输入、且传入的props内容全部为你可控的安全静态内容时才可临时使用,否则绝对不要使用。
符合最佳实践的安全实现
该实现解决了上述两个安全问题:完全摒弃动态代码生成逻辑,避免代码注入;默认对所有插入内容做HTML转义,从根源避免XSS漏洞。
// HTML特殊字符转义工具函数 const escapeHtml = (content) => { if (typeof content !== 'string') return String(content ?? '') const escapeMap = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '`': '`' } return content.replace(/[&<>"'`]/g, match => escapeMap[match]) } // 安全模板编译函数 const createTemplate = (template) => { // 预编译模板匹配规则,仅匹配 ${props.xxx} 格式的合法占位符 const placeholderRule = /\$\{\s*props\.([a-zA-Z0-9_]+)\s*\}/g // 返回渲染函数 return (props = {}) => { return template.replace(placeholderRule, (_, propKey) => { const value = props[propKey] ?? '' // 默认自动转义所有插入内容 return escapeHtml(value) }) } } // 测试用例 const render = createTemplate('<h1>${ props.title }</h1>') // 正常渲染 const html = render({ title: 'Welcome!' }) console.log(html) // 输出: <h1>Welcome!</h1> // 恶意输入测试 const safeHtml = render({ title: '<script>alert("被入侵")</script>' }) console.log(safeHtml) // 输出: <h1><script>alert("被入侵")</script></h1>,不会执行脚本
内容的提问来源于stack exchange,提问作者Grizzly
相关产品推荐
相关产品推荐

