敏感信息泄露往往发生在接口返回结构未经脱敏处理时,例如把用户密码、身份证号、内部错误栈或云存储密钥原样吐给调用方。使用Node.js编写自动化测试脚本,可以在每次构建后主动请求一批关键API,检查响应体中是否夹带不应外泄的字段,从而把人工评审容易遗漏的隐患提前暴露出来。

请求构造与上下文模拟
自动化测试的第一步是尽可能真实地还原客户端调用。很多泄露只在携带特定身份令牌或命中某种查询参数时才出现,因此脚本需要支持读取环境配置、注入鉴权头以及批量替换路径参数。我们可以把待测试的接口清单写成一个JSON文件,由Node.js读取后依次发出请求,这样后续新增用例只需改配置而不动代码。
在Node.js中推荐使用内置的fetch或者轻量的axios库来发请求。需要注意,部分接口依赖登录态,脚本应先调用认证接口拿到token再塞进后续请求头。下面示例展示如何从配置文件加载目标并带上Bearer令牌访问:
const fs = require('fs');
async function callApi(item, token) {
const res = await fetch(item.url, {
method: item.method || 'GET',
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/json'
},
body: item.body ? JSON.stringify(item.body) : undefined
});
const text = await res.text();
return { status: res.status, text };
}
const list = JSON.parse(fs.readFileSync('./api-list.json', 'utf8'));
// 假设已通过登录接口获取token
const token = 'test-token-abc';
list.forEach(async (it) => {
const r = await callApi(it, token);
console.log(it.url, r.status, r.text.length);
});
上述方式把请求逻辑和用例数据分离,便于在CI中复用。如果系统有签名校验,还可以在脚本里实现HMAC计算函数,确保发出的请求能通过网关校验,否则测试会因为403而扫不到真实业务逻辑里的泄露点。
响应扫描与泄露特征匹配
拿到响应文本后,核心动作是判断其中是否包含敏感信息。简单做法是用正则表达式匹配常见模式,例如身份证号、手机号、邮箱、JWT格式串以及含有password或secret键名的JSON片段。但正则容易误报,比如手机号可能本就是公开客服电话,所以应结合接口用途设置白名单或忽略字段。
更稳妥的方案是先把响应解析为JSON,递归遍历键值对,当键名命中敏感词库且值非空时记录告警;对于非JSON响应,再退回正则扫描。下面的代码演示了递归检查对象属性的思路:
const SENSITIVE_KEYS = ['password', 'secret', 'idcard', 'token', 'privatekey'];
function scanObject(obj, path) {
let hits = [];
if (Array.isArray(obj)) {
obj.forEach((v, i) => hits = hits.concat(scanObject(v, path + '[' + i + ']')));
} else if (obj && typeof obj === 'object') {
for (const k of Object.keys(obj)) {
const lower = k.toLowerCase();
if (SENSITIVE_KEYS.some(s => lower.includes(s)) && obj[k]) {
hits.push(path + '.' + k + ' = ' + JSON.stringify(obj[k]).slice(0, 50));
}
hits = hits.concat(scanObject(obj[k], path + '.' + k));
}
}
return hits;
}
function checkResponse(text) {
try {
const data = JSON.parse(text);
return scanObject(data, 'root');
} catch (e) {
// 非JSON,使用正则兜底
const re = /b1[3-9]d{9}b/g;
return text.match(re) || [];
}
}
实践中建议把正则与结构扫描结合:结构扫描负责抓出明确不应返回的字段,正则负责兜底识别文本中散落的凭证。同时应为每个接口设定期望状态码与脱敏规则,避免把正常返回误判为泄露。扫描结果统一收集到数组,后面生成报告时按严重程度排序。
报告输出与流水线集成
发现疑似泄露后,必须给出可读且可追踪的报告,否则开发难以定位。可以让脚本把结果写成Markdown或JUnit XML,在CI平台直接展示。对于命中项,应附带请求URL、匹配字段和截断后的值,但注意报告本身不要完整写出敏感值,防止二次泄露。
将扫描脚本接入流水线时,推荐用npm脚本封装,并在合并请求阶段阻断包含高危泄露的提交。下面示例展示如何把结果汇总并打印摘要:
function buildReport(allHits) {
if (allHits.length === 0) {
return '安全扫描通过:未检测到敏感信息泄露';
}
let lines = ['发现 ' + allHits.length + ' 处疑似泄露:'];
allHits.forEach(h => lines.push('- ' + h));
return lines.join('n');
}
// 假设results是之前收集到的命中数组
const results = [];
console.log(buildReport(results));
</script>
在团队落地时,还应控制扫描频率与并发数,避免对测试环境造成压力。可以把脚本安排在夜间或预发环境定时跑,并把历史报告存档,方便对比每次迭代是否引入了新的泄露点。当规则库随业务演进不断更新,这套Node.js工具就能持续守护接口安全。