如何修复SonarQube报告的Java邮箱校验正则拒绝服务漏洞?
邮箱正则灾难性回溯问题修复方案
问题根因
你提供的原始正则存在两处可触发灾难性回溯的结构:(\\.[_A-Za-z0-9-]+)*和(\\.[A-Za-z0-9]+)*。这类重复分组嵌套重复匹配的结构,遇到恶意构造的超长不合法邮箱字符串时,正则引擎会反复尝试不同的匹配路径,CPU占用会短时间拉满,最终触发拒绝服务风险,这也是SonarQube报错的核心原因。
修复方案
方案1:改动最小,用占有量词消除回溯(推荐)
Java正则的占有量词匹配到内容后不会释放进行回溯,直接从根源消除回溯路径,只需要修改正则符号即可,原有校验规则完全不变:
import java.util.regex.Pattern; public class EmailValidator { // 正则预编译为静态常量,避免每次调用重复编译损耗性能 private static final Pattern VALID_EMAIL_PATTERN = Pattern.compile( "^[_A-Za-z0-9-+]++(\\.[_A-Za-z0-9-]++)*+@" + "[A-Za-z0-9-]++(\\.[A-Za-z0-9]++)*+(\\.[A-Za-z]{2,})$" ); public static boolean validEmailAddress(String email) { // 增加空校验避免空指针异常 if (email == null || email.isBlank()) { return false; } return VALID_EMAIL_PATTERN.matcher(email).matches(); } }
改动说明:
- 所有普通匹配量词
+替换为占有量词++,*替换为占有量词*+,匹配失败直接返回,不会产生回溯 - 移除了正则中多余的
+转义符(Java字符串中+不需要转义,只有正则语法中+属于特殊符号,无需额外加转义符) - 方法名调整为符合Java编码规范的小驼峰格式
- 增加入参空校验,避免空指针异常
方案2:不用手写正则,直接用成熟的校验实现
邮箱格式规范非常复杂,手写正则很容易出现覆盖不全或者安全问题,优先用业界成熟的校验库实现,底层已经处理了所有回溯风险。
如果是Spring生态项目,可以直接用Hibernate Validator内置的邮箱校验器:
import org.hibernate.validator.internal.constraintvalidators.bv.EmailValidator; public static boolean validEmailAddress(String email) { if (email == null || email.isBlank()) { return false; } return new EmailValidator().isValid(email, null); }
内容的提问来源于stack exchange,提问作者tea code
相关产品推荐
相关产品推荐

