回跳地址通过了前缀检查:用 URL 解析结果校验来源
登录后跳回 return_to 指定地址。用字符串前缀检查 https://app.example.com 时,域名后缀和 URL 用户信息都可能改变浏览器实际访问的主机。先按 URL 标准解析,再比较解析后的 origin,并把审核过的序列化结果交给重定向。
1. 用反例测试允许列表
保存为 origin_lab.mjs,运行 node origin_lab.mjs。所有输入仅用于解析。
import assert from 'node:assert/strict';
const app = new URL('https://app.example.com/');
function validatedTarget(input) {
let url;
try {
url = new URL(input, app);
} catch {
return null;
}
if (url.protocol !== 'https:' || url.origin !== app.origin ||
url.username || url.password) {
return null;
}
return url.href;
}
const cases = [
['/orders', 'https://app.example.com/orders'],
['https://APP.example.com:443/orders', 'https://app.example.com/orders'],
['https://app.example.com.evil.example/orders', null],
['https://app.example.com@evil.example/orders', null],
['//evil.example/orders', null],
['https://app.example.com:8443/orders', null],
['javascript:alert(1)', null],
['blob:https://app.example.com/id', null],
];
for (const [value, expected] of cases) {
const target = validatedTarget(value);
assert.equal(target, expected);
console.log(value, '=>', target ?? 'rejected');
}
assert.equal(cases[2][0].startsWith(app.origin), true);
assert.equal(cases[3][0].startsWith(app.origin), true);
本机实测输出如下。
/orders => https://app.example.com/orders
https://APP.example.com:443/orders => https://app.example.com/orders
https://app.example.com.evil.example/orders => rejected
https://app.example.com@evil.example/orders => rejected
//evil.example/orders => rejected
https://app.example.com:8443/orders => rejected
javascript:alert(1) => rejected
blob:https://app.example.com/id => rejected
2. 区分来源限制和页面限制
origin 包含协议、主机和端口,默认端口经过规范化。只比较 hostname 会同时放过使用其他协议或非默认端口的目标。本例额外限制协议,避免 origin 继承自内部 URL 的 blob 地址通过。用户信息段也被明确拒绝。
如果登录回跳只能去少数业务页面,可以直接接受一个路由名,从服务端固定表生成目标地址。必须支持 URL 时,在解析后比较 origin,再校验允许的路径。只校验来源仍会允许同源站点上的其他路径,包括可继续重定向的入口。
小结
校验与实际重定向共用一次 URL 解析。测试域名后缀、用户信息、协议相对地址与非默认端口,保存通过检查的序列化 URL。
数据来源与检索时间
检索时间 2026-11-13。
| 来源 | URL | 对应内容 |
|---|---|---|
| WHATWG URL | https://url.spec.whatwg.org/#url-parsing | URL 解析与规范化 |
| WHATWG URL | https://url.spec.whatwg.org/#origin | origin 的计算和 blob 行为 |
核验说明
- Node.js v24.19.0 验证 URL 解析和校验结果,未访问示例地址。