Nessus扫描报前端JS有安全风险,这代码真有问题吗?
最近用Nessus扫我们项目,说前端这段JS存在“客户端脚本注入”风险,但我只是在做URL参数解析啊,这算漏洞吗?
我试过对参数做encodeURIComponent,但Nessus还是报同样的问题,有点懵。
const urlParams = new URLSearchParams(window.location.search);
const token = urlParams.get('token');
if (token) {
document.getElementById('user-token').innerText = token;
}
innerText就安全了,也不是因为没做encodeURIComponent—— 关键问题在于你把用户可控的 URL 参数直接塞进 DOM 了,哪怕只是设置innerText,也仍然可能被利用。先说问题根源:
Nessus 报的是「客户端脚本注入」,本质是 XSS(Cross-Site Scripting)。
虽然你用的是
innerText,它确实不会把字符串当 HTML 解析,但问题出在元素本身的位置和上下文。比如:- 如果这个
div#user-token后面又被其他 JS 用innerHTML拼接进页面(常见于模板渲染)- 或者它被嵌在某个
<a href="xxx">、<img src="xxx">、<script>标签的属性里(比如你这个 token 最终被拼到 redirect URL 里)- 甚至只是被后续的
eval()或Function构造器引用了,都可能触发 XSS举个真实场景:
假设页面后续有这么一段代码:
如果攻击者构造 URL:
那最后生成的 HTML 可能是:
注意,这里
innerText确实不会解析 HTML 标签,但它没做任何转义,所以双引号、空格、属性名都原样保留了,拼接进 HTML 属性时就形成事件劫持。再比如更隐蔽的:
如果这个 token 之后被传给某个第三方 SDK,比如:
而这个 SDK 内部用了
JSON.parse+eval或类似逻辑(不规范的 SDK 很多),那 payload 就能逃逸。正确做法分三步走:
1. 校验参数合法性(白名单过滤)
token 通常应该是固定格式(比如 JWT、UUID、base64 字符串),不要无脑接受任意字符串。
例如只允许字母、数字、短横线、下划线、点号(具体按你业务定),其他一概丢弃或报错。
2. 设置时用
textContent,而不是innerTextinnerText会触发重排(layout),还受 CSS 影响(比如display:none的元素它可能不返回内容),而textContent是纯文本节点操作,更干净。重点不是它和
innerText的区别,而是确保 DOM 插入点本身是安全的。3. 关键:避免把用户输入拼到 HTML 属性、JS 上下文、URL 里
如果 token 最终要用于跳转或作为参数,必须用
encodeURI或encodeURIComponent,但不是在获取时做,而是在使用时做。修正后的代码示例(带防御性校验):
额外提醒几个坑:
- 不要指望
innerHTML+DOMPurify来救场——你这根本不需要 HTML,用textContent就行,别多此一举-
encodeURIComponent只能防 URL 参数注入,防不住 HTML 注入,比如<、>在innerText场景里不会被解析成标签,但如果后续被拼进 HTML 属性,"这种实体还是能逃逸- 真正的防御是:输入校验 + 上下文安全输出。URL 参数 → 文本节点 → 安全;URL 参数 → 属性值 → 用
encodeURI;URL 参数 → JS 字符串 → 用JSON.stringify包一层最后说句实话:
Nessus 的扫描结果很多是“假阳性”,但它报这个确实有道理——你这代码在安全审计里属于「低风险但可优化」的典型,不是现在立刻会炸,但足够让安全扫描工具点名。
按上面改完,再扫基本就过了。