如何通过静态分析 AST 自动识别并重写项目中不再符合安全规范的正则定义

大瑶同学_5476

大瑶同学_5476

2026-05-06

902人浏览

原创

真正危险的 regexp 字面量需结合 ast 上下文、字符串内容及作用域引用三重判断:出现在 newexpression(regexp)、敏感调用链赋值、含未校验用户输入等场景;静态定义如 const pattern = /d+/g 通常安全,除非被二次动态构造。

如何通过静态分析 ast 自动识别并重写项目中不再符合安全规范的正则定义

直接用 acorn 或 @babel/parser 解析完就遍历 RegExpLiteral 节点然后替换,大概率会破坏运行时行为——正则的安全风险不在字面量本身,而在其构造方式、动态拼接逻辑、以及是否被用于不安全上下文(如 eval、new Function、location.href 注入)。必须结合 AST 上下文 + 字符串字面量内容 + 作用域引用三重判断,才能准确识别“该改”和“不该动”的正则。

怎么定位真正危险的 RegExp 字面量

不是所有带 /.../ 的节点都该被重写。关键看它是否出现在高风险构造路径中:

  • RegExpLiteral 出现在 NewExpression 中且 callee.name === 'RegExp',且第一个参数是字符串字面量(StringLiteral)或模板字面量(TemplateLiteral),这类极易被绕过静态检测
  • RegExpLiteral 被赋值给变量后,该变量又被传入 eval、setTimeout、setInterval、location.replace 等敏感调用链
  • RegExp 构造函数参数中包含未校验的用户输入(如 req.query.id、document.cookie),需向上追溯 CallExpression 的 arguments 是否含 MemberExpression 或 Identifier 引用外部数据源
  • 跳过 const PATTERN = /\d+/g 这类纯静态定义——除非它后续被 new RegExp(PATTERN.source) 二次构造并拼接

为什么不能只靠正则字符串内容做安全判定

单纯扫描 /.*?/i 或 /[a-z]+/ 这类模式毫无意义。真正的问题往往藏在上下文里:

  • new RegExp(userInput + '$'):AST 中 userInput 是一个 Identifier,它的来源可能来自 URLSearchParams 或 localStorage,必须沿 ReferencePath 向上查到声明处或调用入口
  • const r = /\w+/; location.href = `/?q=${r}`:这里 r 本身安全,但字符串化后参与 URL 拼接,触发 XSS,需检测 BinaryExpression 右侧是否为 TemplateLiteral 且含 location、document 等全局对象
  • eval(`/${unsafe}/g`):AST 中 eval 是 CallExpression,其第一个 argument 是 TemplateLiteral,内部插槽含 Identifier,此时必须标记整个表达式为高危,而非仅修改 unsafe 变量名

重写策略必须区分构造方式与执行环境

不同正则使用场景,修复手段完全不同,硬统一替换会引入新 bug:

  • 对纯字面量 /\d{3}-\d{2}-\d{4}/,可安全替换成预编译的 const SSN_REGEX = new RegExp('\\d{3}-\\d{2}-\\d{4}', 'g'),并加 /* @__PURE__ */ 注释避免 tree-shaking 误删
  • 对动态构造 new RegExp(prefix + '\d+'),不能直接改字符串,而应插入校验:替换为 new RegExp(escapeRegExp(prefix) + '\\d+', 'g'),其中 escapeRegExp 需提前注入或要求项目已存在
  • 对用于 replace 的正则(如 str.replace(//g, '<')),若原模式无捕获组,可转成字符串方法调用:str.split(',避免正则引擎开销与回溯风险
  • 所有重写必须保留原始 flags(g、i、m 等),且生成新节点时用 t.newExpression(t.identifier('RegExp'), [stringLiteralNode, flagLiteralNode]),不能漏掉 flags 参数导致行为变更

容易被忽略的边界:跨文件引用与模块导出

一个正则定义在 utils/regex.js 中导出,被十个文件 import 使用,只改定义文件远远不够:

  • 若该正则被 export const EMAIL = /\S+@\S+\.\S+/ 导出,则重写时必须同步更新所有 import { EMAIL } 处的调用上下文——尤其是它是否出现在 new Function(...EMAIL...) 中
  • ESM 动态 import() 加载的模块内正则无法被单文件 AST 分析覆盖,需配合打包器插件(如 esbuild.onLoad)做全图扫描
  • CommonJS 的 module.exports = { pattern: /.../ } 会被 Babel 转成 exports.pattern = /.../,此时 pattern 是属性访问,需识别 MemberExpression 的 object.name === 'exports' 才能准确定位
  • 没处理 require.resolve 或 import.meta.url 构造的路径拼接正则,会导致混淆后路径失效,这类必须人工标注 /* @no-rewrite-regex */ 注释跳过
PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

2023.06.20

4076

8

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

2023.07.05

2621

4

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

7142

9

java正则表达式匹配字符串
java正则表达式匹配字符串

在Java中,我们可以使用正则表达式来匹配字符串。本专题为大家带来java正则表达式匹配字符串的相关内容,帮助大家解决问题。

2023.08.11

792

5

正则表达式空格
正则表达式空格

正则表达式空格可以用“\s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。本专题为大家提供正则表达式相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.31

500

5

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.13

653

12

正则表达式空格如何表示
正则表达式空格如何表示

正则表达式空格可以用“\s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。想了解更多正则表达式空格怎么表示的内容,可以访问下面的文章。

2023.11.17

386

3

正则表达式中如何匹配数字
正则表达式中如何匹配数字

正则表达式中可以通过匹配单个数字、匹配多个数字、匹配固定长度的数字、匹配整数和小数、匹配负数和匹配科学计数法表示的数字的方法匹配数字。更多关于正则表达式的相关知识详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.12.06

719

7

php正则表达式有哪些
php正则表达式有哪些

php正则表达式有"/pattern/"、"^"、"$"、"."、"[]"、"[^]"、"[a-z]"、"[A-Z]"、"[0-9]"、"\d"、"\D"、"\w"、"\W"、&a

2024.02.23

312

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.4万人学习