Web Storage 本身不执行代码,但若写入前未过滤不可信数据或读取后误执行(如 innerHTML、eval),会成为 XSS 跳板;须白名单校验输入、DOMPurify 清洗 HTML、禁用动态执行、配合 CSP 并避免存储敏感信息。

Web Storage(localStorage 和 sessionStorage)本身不执行代码,但若使用不当,极易成为 XSS 攻击的跳板。它的风险不在“存储”动作本身,而在于“怎么存”和“怎么用”——写入前未过滤、读取后误执行,才是真正的突破口。
写入前必须做可信校验
所有进入 Web Storage 的数据,只要来源不可控(如 URL 参数、表单输入、API 返回内容),就必须视为潜在恶意输入:
- 优先采用白名单机制:例如用户 ID 只允许数字+字母,用正则或 schema 明确约束格式,拒绝任何例外
- 富文本或 HTML 片段不能原样存入:必须经 DOMPurify 等成熟库清洗后再保存,禁用 innerHTML 直接拼接
- 服务端下发的脚本字符串(如含
<script>、javascript:、onerror=的内容)严禁直接塞进 storage
读取后禁止动态解析执行
从 storage 中取出的数据默认是字符串,浏览器不会自动判断其安全性。危险操作包括:
- ❌ element.innerHTML = localStorage.getItem('raw') —— 可能触发脚本注入
- ❌ setTimeout(localStorage.getItem('code'), 100) —— 直接执行任意字符串
- ❌ eval(localStorage.getItem('data')) —— 完全放弃语法边界
- ✅ 推荐用 textContent 渲染纯文本
- ✅ JSON.parse() 解析结构化数据(前提是确认内容为合法 JSON)
- ✅ createElement + setAttribute 构造元素,避免属性值拼接
配合 CSP 形成纵深防御
即使 storage 被污染,CSP 也能大幅削弱攻击效果:
- 设置
Content-Security-Policy: script-src 'self'; object-src 'none'; base-uri 'self' - 坚决避免
'unsafe-eval'和'unsafe-inline'—— 它们会让 XSS 利用成本骤降 - CSP 不防写入,但能阻断内联脚本、eval、动态创建 script 标签等关键执行路径
敏感信息绝不落地到 Web Storage
localStorage 是持久、可读、同源可见的客户端存储,天然不适合保管以下内容:
- 用户密码、JWT token(应由 HttpOnly Cookie 承载)
- 银行卡号、身份证号等 PII 数据
- 权限标识(如
{"isAdmin": true})—— 前端篡改无效,服务端必须重新鉴权 - 短期状态优先用 sessionStorage;必要缓存可加密后存储,但密钥管理需格外审慎

















