CSS注入是一种安全漏洞,攻击者通过将恶意代码拼入CSS规则(如style属性、动态style标签)窃取敏感信息;link引入外部CSS本身安全,前提是服务端不将用户输入写入该文件。

直接引入外部 CSS 文件本身不会触发样式注入攻击,真正危险的是把不可信的用户输入拼进 CSS 规则里——比如动态生成 <style> 标签、用 document.styleSheets 插入规则,或在 style 属性中拼接字符串。
为什么 link 引入 CSS 通常安全?
浏览器加载 <link rel="stylesheet"> 时,CSS 内容被当作纯样式解析,不执行 JS、不解析 url(javascript:...)(现代浏览器已禁用)、不读取 HTML 属性值。只要服务端不把用户输入写进该 CSS 文件,风险就极低。
- ✅ 安全前提:CSS 文件由你完全控制,且构建过程不拼接用户数据
- ⚠️ 风险点:若后端模板(如 PHP、Jinja)把用户输入直接 echo 进 CSS 文件内容,那文件本身就成了注入载体
- ❌ 错误示例:
body { background: url("= $_GET['bg'] ?>"); }—— 此时link只是“运毒车”,源头在服务端模板
style 属性和 setAttribute('style', ...) 怎么安全使用?
这是最常踩坑的地方。浏览器对 style 属性的解析比 <style> 标签更宽松,某些旧版或边缘语法仍可能触发副作用。
- ✅ 推荐做法:只给单个属性赋值,用原生 DOM API:
el.style.backgroundColor = userInputColor - ⚠️ 避免字符串拼接:
el.setAttribute('style', `background: ${userInput}; color: #000`)—— 若userInput是url("javascript:alert(1)"),部分环境仍可能执行 - ❌ 绝对禁止:
el.style.backgroundImage = 'url("' + userInput + '")'—— 用户输入可能闭合引号并注入恶意内容
动态插入 <style> 标签时必须做什么?
这种场景常见于主题切换、UI 配置导出等,但也是高危操作。
立即学习“前端免费学习笔记(深入)”;
- ✅ 必须对所有用户输入做 CSS 值白名单校验:只允许
#fff、rgb(255,0,0)、16px等已知安全格式,拒绝url(...)、attr(...)、calc(...)中含变量的部分 - ✅ 使用
CSSStyleSheet.insertRule()替代 innerHTML,避免整段字符串解析:sheet.insertRule(`.theme { color: ${safeColor} }`, 0) - ⚠️ 注意:即使用了
insertRule,如果safeColor是未经校验的字符串,仍可能被用于构造选择器级攻击(如通过[data-value="xss"]匹配)
真正起作用的防御不是某一个工具,而是分层控制
没有银弹。MVP.css 或 postcss-cssnext 的“无类”“变量隔离”只是减少攻击面,不能替代输入控制;CSP 的 style-src 'self' 能防外链,但拦不住内联拼接;React CSS Modules 的哈希类名防样式污染,但不防 style 属性注入。
最容易被忽略的一点:**CSS 注入的入口往往不在 CSS 本身,而在你把用户输入喂给 element.style.xxx、insertRule 或服务端模板的那一行代码里。盯住那个“赋值点”,比选什么 CSS 框架重要得多。**


















