mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 01:51:24 +00:00
fix(security): restrict canvas IP-based auth to private networks (#14661)
Merged via /review-pr -> /prepare-pr -> /merge-pr.
Prepared head SHA: 9e4e1aca4a
Co-authored-by: sumleo <29517764+sumleo@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Reviewed-by: @steipete
This commit is contained in:
@@ -44,6 +44,50 @@ export function isLoopbackAddress(ip: string | undefined): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the IP belongs to a private or loopback network range.
|
||||
* Private ranges: RFC1918, link-local, ULA IPv6, and CGNAT (100.64/10), plus loopback.
|
||||
*/
|
||||
export function isPrivateOrLoopbackAddress(ip: string | undefined): boolean {
|
||||
if (!ip) {
|
||||
return false;
|
||||
}
|
||||
if (isLoopbackAddress(ip)) {
|
||||
return true;
|
||||
}
|
||||
const normalized = normalizeIPv4MappedAddress(ip.trim().toLowerCase());
|
||||
const family = net.isIP(normalized);
|
||||
if (!family) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (family === 4) {
|
||||
const octets = normalized.split(".").map((value) => Number.parseInt(value, 10));
|
||||
if (octets.length !== 4 || octets.some((value) => Number.isNaN(value))) {
|
||||
return false;
|
||||
}
|
||||
const [o1, o2] = octets;
|
||||
// RFC1918 IPv4 private ranges.
|
||||
if (o1 === 10 || (o1 === 172 && o2 >= 16 && o2 <= 31) || (o1 === 192 && o2 === 168)) {
|
||||
return true;
|
||||
}
|
||||
// IPv4 link-local and CGNAT (commonly used by Tailnet-like networks).
|
||||
if ((o1 === 169 && o2 === 254) || (o1 === 100 && o2 >= 64 && o2 <= 127)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// IPv6 unique-local and link-local ranges.
|
||||
if (normalized.startsWith("fc") || normalized.startsWith("fd")) {
|
||||
return true;
|
||||
}
|
||||
if (/^fe[89ab]/.test(normalized)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function normalizeIPv4MappedAddress(ip: string): string {
|
||||
if (ip.startsWith("::ffff:")) {
|
||||
return ip.slice("::ffff:".length);
|
||||
|
||||
Reference in New Issue
Block a user