把所有诊断都变成红灯门禁很快就会失去可信度。开发者不知道这次是会产生运行错误还是只少了一个空格管理员却开始习惯性地替大家点跳过。问题不在于规则够不够“智能”而在于每条规则有没有清楚的任务它识别什么证据在哪里为什么需要阻断又会漏掉什么。规则性质与阻断级别是两条轴ESLint 的规则元信息把性质分为 problem、suggestion、layout。严重程度则在配置中指定为 off、warn、error。不要把 meta.type 写成 problem就以为它会自动阻断 CI也不要认为 layout 类型不能配置成 error。性质与团队决策分别存放才便于复查。Custom Rules性质讨论的问题本文建议的处置problem代码中存在明确问题或约定禁止的能力有足够证据时阻断suggestion有更好的写法但是否适用有上下文提醒并说明理由layout空白、分号等表现形式优先交给格式化工具最后一列是工程选择不是 ESLint 官方对所有团队的要求。代码生成文件、兼容层、历史迁移文件都可能需要不同配置。写一条窄规则别宣称“消灭所有注入”下面是可独立保存运行的规则实验。它禁止直接写出eval(...)不会把注释里的单词当调用。为了让范围容易看清测试故意保留一个漏检反例。// 依赖 eslint10.0.0保存为 lint-case.mjs import assert from node:assert/strict; import { Linter } from eslint; const noDirectEval { meta: { type: problem, schema: [], messages: { forbidden: 此模块禁止直接调用 eval。 } }, create(context) { return { CallExpression(node) { if (node.callee.type Identifier node.callee.name eval) { context.report({ node, messageId: forbidden }); } } }; } }; const config [{ languageOptions: { ecmaVersion: 2022, sourceType: module }, plugins: { local: { rules: { no-direct-eval: noDirectEval } } }, rules: { local/no-direct-eval: error } }]; const linter new Linter(); const diagnose code linter.verify(code, config); assert.equal(diagnose(eval(1 1)).length, 1); assert.equal(diagnose(const text eval(x);).length, 0); // 当前规则只匹配直接调用。这个结果暴露范围不代表代码安全。 assert.equal(diagnose((0, eval)(1 1)).length, 0); const warning [{ ...config[0], rules: { local/no-direct-eval: warn } }]; assert.equal(linter.verify(eval(1), warning)[0].severity, 1); console.log(narrow rule checks passed);把测试里的第三个结果藏起来再写“AST百分百拦住动态执行”就是在拿读者的信任换标题。AST 给的是结构化语法证据完整的数据流、别名、跨模块行为还要靠其他分析。同理找到了addEventListener却没找到removeEventListener也不能立即断言泄漏。监听可能使用 AbortSignal 清理可能由封装层管理也可能刻意跟随页面生命周期。规则必须说明自己覆盖了哪些清理模式以及哪些情况只能给建议。阻断规则需要反例而不只是一个红灯样例一条规则至少要准备三组输入第一组是应当阻断的代码能定位到具体语法节点。第二组是相似但合法的写法防止字符串、注释和不同作用域被误伤。第三组是已知超出能力范围的写法明确留在边界说明中。修复建议也有级别。删除一个尾随空格与改写一段异步控制流不能共享同一种“自动修复”权限。涉及生命周期或业务分支时生成一个待审差异通常比直接修改更合适。这个例子没有实现类型分析没有处理 TypeScript、Vue SFC 或所有动态执行方式。引入这些语法后应使用相应解析器和真实工程样本重新测试不能把一份 JavaScript 规则直接挂到所有文件上。CI 才是团队共同遵守的检查点本地诊断可以缩短反馈时间服务端仍要保留必需检查。保护分支的检查名称、管理员是否可绕过、谁能修改规则都属于门禁有效性的一部分。GitHub 文档还提示工作流里重复的 job 名称会造成状态检查歧义。保护分支说明不要用“有一个脚本”代替这些配置证据。也别把一次规则通过解释成整个系统没有安全问题。规则示例的完整行为验证依赖 ESLint 10。没有执行依赖测试的环境只能核对代码语法和预期样例不能写成运行通过生产误报率、漏报率与性能开销也都没有在本文测量。文档未标首发日按现行接口说明使用。