fix: exclude prose colons from drainage URL boundaries
CSS quality / css-quality (push) Has been cancelled
CSS quality / css-quality (push) Has been cancelled
This commit is contained in:
@@ -30,6 +30,28 @@ const material = (id: string, url: string, channels: string[], auditStatus = 'ap
|
|||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
describe('drainage authorization', () => {
|
describe('drainage authorization', () => {
|
||||||
|
it.each(['详情:https://qa0915.example.com', '详情:https://qa0915.example.com'])(
|
||||||
|
'keeps prose separators outside explicit URLs: %s',
|
||||||
|
(content) => {
|
||||||
|
const text = 'https://qa0915.example.com';
|
||||||
|
const start = content.indexOf(text);
|
||||||
|
const targets = drainageTargets(content, [
|
||||||
|
{
|
||||||
|
ruleId: 'url',
|
||||||
|
ruleCode: 'URL',
|
||||||
|
ruleName: 'URL',
|
||||||
|
category: 'url',
|
||||||
|
text,
|
||||||
|
normalizedText: text,
|
||||||
|
start,
|
||||||
|
end: start + text.length,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(targets).toHaveLength(1);
|
||||||
|
expect(targets[0].text).toBe(text);
|
||||||
|
expect(materialMatches(targets[0], text)).toBe(true);
|
||||||
|
},
|
||||||
|
);
|
||||||
test.each([
|
test.each([
|
||||||
'lisglo.cn',
|
'lisglo.cn',
|
||||||
'sms.lisglo.cn',
|
'sms.lisglo.cn',
|
||||||
|
|||||||
@@ -81,7 +81,11 @@ export function drainageTargets(content: string, matches: DrainageDetectionMatch
|
|||||||
if (start < 0 || end <= 0) throw new ServiceUnavailableException('引流识别位置无效');
|
if (start < 0 || end <= 0) throw new ServiceUnavailableException('引流识别位置无效');
|
||||||
// Extend the entire URL token, including suffix labels, userInfo and query.
|
// Extend the entire URL token, including suffix labels, userInfo and query.
|
||||||
const token = /[a-z0-9:/?&=.%_+@#~!$*()[\]-]/i;
|
const token = /[a-z0-9:/?&=.%_+@#~!$*()[\]-]/i;
|
||||||
while (start > 0 && token.test(normalized.text[start - 1])) start--;
|
while (start > 0 && token.test(normalized.text[start - 1])) {
|
||||||
|
// A prose colon before an explicit scheme is a separator, including normalized Chinese colons.
|
||||||
|
if (normalized.text[start - 1] === ':' && /^https?:\/\//i.test(normalized.text.slice(start, end))) break;
|
||||||
|
start--;
|
||||||
|
}
|
||||||
while (end < normalized.text.length && token.test(normalized.text[end])) end++;
|
while (end < normalized.text.length && token.test(normalized.text[end])) end++;
|
||||||
const text = normalized.text.slice(start, end).replace(/[.,;!]+$/, '');
|
const text = normalized.text.slice(start, end).replace(/[.,;!]+$/, '');
|
||||||
const value = drainageHost(text);
|
const value = drainageHost(text);
|
||||||
|
|||||||
@@ -193,3 +193,8 @@ Gateway 每个分片等待可用连接后通过仅本机直连的 POST /api/gate
|
|||||||
### 11.1 实际数据库约束补核
|
### 11.1 实际数据库约束补核
|
||||||
|
|
||||||
真实隔离库复现原ChannelSignatureReportTask_drainage_target_key是签名+引流+通道部分唯一索引(Prisma模型未声明此部分约束)。必须新增20260914093000_drainage_carrier_reports,在同事务建立carrier非空四维唯一索引及carrier为空历史三维唯一索引,再移除旧三维索引;不改旧数据/状态。新索引同样防止状态保存与导出并发产生重复任务。迁移仅在独立验收库执行,发布后方能启用新代码;不能回退旧程序继续发送并把三网任务当通道级读取。应用回退需暂停发送并评估三网事实,不能删除新任务或直接重建旧唯一索引。
|
真实隔离库复现原ChannelSignatureReportTask_drainage_target_key是签名+引流+通道部分唯一索引(Prisma模型未声明此部分约束)。必须新增20260914093000_drainage_carrier_reports,在同事务建立carrier非空四维唯一索引及carrier为空历史三维唯一索引,再移除旧三维索引;不改旧数据/状态。新索引同样防止状态保存与导出并发产生重复任务。迁移仅在独立验收库执行,发布后方能启用新代码;不能回退旧程序继续发送并把三网任务当通道级读取。应用回退需暂停发送并评估三网事实,不能删除新任务或直接重建旧唯一索引。
|
||||||
|
|
||||||
|
|
||||||
|
### 2026-09-15 URL 前置文字分隔符补充
|
||||||
|
|
||||||
|
显式 http(s) URL 前紧邻的中英文冒号属于正文分隔符,不得进入引流域名解析。URL 内的协议、userinfo、完整域名后缀及 query 仍须整体校验,不能通过缩短匹配令恶意域名借用已报备资料。真实误拦截与回归记录见 HTTP-0915-B03。
|
||||||
|
|||||||
@@ -5550,3 +5550,9 @@ CLIENT-0914-01~07 的模板样式/顺序、文档归属与检索、中文状
|
|||||||
- HTTP-0915-B01:上行mobile=abc/1/空/超长,accessNumber=非数字/空/22位返回400;合法11位手机号和1–21位接入号精确匹配。
|
- HTTP-0915-B01:上行mobile=abc/1/空/超长,accessNumber=非数字/空/22位返回400;合法11位手机号和1–21位接入号精确匹配。
|
||||||
- HTTP-0915-B02:仅HTTP开通、CMPP关闭时合法请求正常送达;HTTP总开关或sendEnabled关闭仍拒绝,客户端/CMPP原关闭检查保留;外部sourceType不能模拟内部HTTP上下文。
|
- HTTP-0915-B02:仅HTTP开通、CMPP关闭时合法请求正常送达;HTTP总开关或sendEnabled关闭仍拒绝,客户端/CMPP原关闭检查保留;外部sourceType不能模拟内部HTTP上下文。
|
||||||
- HTTP-0915-E2E:四公开接口鉴权/nonce/过期/签名篡改/参数类型及边界/幂等/重复/隔离/分页;专用模拟通道正常与失败回执、黑名单/号码频次/模板/签名/引流/敏感词拦截,核对真实PG、Redis、Gateway、Webhook签名/成功/重试/终止及扣退费;测试后排空并停用本轮对象。每项执行结论写进度和证据矩阵,不把旧版本通过当新版本通过。
|
- HTTP-0915-E2E:四公开接口鉴权/nonce/过期/签名篡改/参数类型及边界/幂等/重复/隔离/分页;专用模拟通道正常与失败回执、黑名单/号码频次/模板/签名/引流/敏感词拦截,核对真实PG、Redis、Gateway、Webhook签名/成功/重试/终止及扣退费;测试后排空并停用本轮对象。每项执行结论写进度和证据矩阵,不把旧版本通过当新版本通过。
|
||||||
|
|
||||||
|
|
||||||
|
### HTTP-0915-B03:引流 URL 前置分隔符
|
||||||
|
|
||||||
|
- 已审核签名、模板、引流资料及当前运营商通道报备通过时,正文中的“详情:https://qa0915.example.com”和英文冒号版本应提取完整 URL,正常路由;冒号不计入 URL。
|
||||||
|
- 未登记、未审核、当前运营商报备失败仍应分别拒绝,零供应商 Submit;恶意后缀、userinfo 和 query 不得借用其他域名报备。
|
||||||
|
|||||||
@@ -5042,3 +5042,12 @@ CUA本轮可用,实际后端文档三尺寸1600×1000/1366×768/390×844无页
|
|||||||
用户明确授权仅专用企业、应用、模拟通道及号码发送/回执/Webhook和必要测试配置。已新建HTTP隔离0915企业、2应用、3条远端loopback模拟通道、测试余额及对应流水;原客户/通道无修改。模拟器仅接受指定测试账号与号码、最多40个Submit,不连接运营商。当前准备上线新代码后完成真实链路复验及测试收尾。证据.local-data/http-complete-20260915。
|
用户明确授权仅专用企业、应用、模拟通道及号码发送/回执/Webhook和必要测试配置。已新建HTTP隔离0915企业、2应用、3条远端loopback模拟通道、测试余额及对应流水;原客户/通道无修改。模拟器仅接受指定测试账号与号码、最多40个Submit,不连接运营商。当前准备上线新代码后完成真实链路复验及测试收尾。证据.local-data/http-complete-20260915。
|
||||||
|
|
||||||
用户要求安全复用sudo密码:已存当前Windows用户DPAPI加密文件(仓库外),不写明文;本机受保护未跟踪release.py仅新增test专用--sudo-credential及测试,47项工具测试含5项平台跳过。发现PowerShell7模块路径影响PowerShell5解密,调用时移除继承PSModulePath后真实只读SSH通过。工具变更后新计划绑定新摘要,不复用旧preflight。工具仍未提交,不能以应用SHA冒充工具版本。后续发布/推送及完成证据另行追加;预生产不在范围。
|
用户要求安全复用sudo密码:已存当前Windows用户DPAPI加密文件(仓库外),不写明文;本机受保护未跟踪release.py仅新增test专用--sudo-credential及测试,47项工具测试含5项平台跳过。发现PowerShell7模块路径影响PowerShell5解密,调用时移除继承PSModulePath后真实只读SSH通过。工具变更后新计划绑定新摘要,不复用旧preflight。工具仍未提交,不能以应用SHA冒充工具版本。后续发布/推送及完成证据另行追加;预生产不在范围。
|
||||||
|
|
||||||
|
|
||||||
|
### 2026-09-15 HTTP 全链路复测:引流 URL 冒号边界误拦截(进行中)
|
||||||
|
|
||||||
|
- 测试环境 c781313 的 78 项异常参数、新签名及旧协议拒绝用例全部通过。已获得实际模拟 Submit、DELIVRD/UNDELIV、黑名单与频次拦截、退款、上行及 Webhook 503 后自动重试成功证据。
|
||||||
|
- 真实发现 HTTP-0915-B03:正文“调测内容:https://qa0915.example.com”的识别结果是完整 URL,但 drainageTargets 向左扩展时把归一化后的中文冒号加入 URL,抛出 DRAINAGE_INVALID,已批准引流资料仍不能发送。此问题属于 URL 边界误判,不能把误拦截算作报备校验通过。
|
||||||
|
- 修复目标:显式 http(s) URL 前的文字冒号不属于 URL;继续扩展恶意域名后缀、userinfo 和 query,保留已有安全校验。最终复测与发布状态后续追加。
|
||||||
|
|
||||||
|
- 定向回归:修复前 2 失败/20 通过,修复后 22/22 通过;候选全量门禁及部署后真实 URL 验收待执行。
|
||||||
|
|||||||
Reference in New Issue
Block a user