Skip to content

Commit b0a1e1e

Browse files
hanxigithub-advanced-security[bot]Formatter [BOT]
authored
Potential fix for code scanning alert no. 66: Full server-side request forgery (#630)
* Potential fix for code scanning alert no. 66: Full server-side request forgery Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Auto-format code 🧹🌟🤖 --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Formatter [BOT] <runner@runnervmh13bl.i3bvc2db5o2uln5sftk5ylwv3b.ex.internal.cloudapp.net>
1 parent 8f919ea commit b0a1e1e

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

xiaomusic/xiaomusic.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
import asyncio
33
import base64
44
import copy
5+
import ipaddress
56
import json
67
import logging
78
import math
89
import os
910
import random
1011
import re
12+
import socket
1113
import time
1214
import urllib.parse
1315
from collections import OrderedDict
@@ -1305,11 +1307,57 @@ async def get_real_url_of_openapi(url: str, timeout: int = 10) -> dict:
13051307

13061308
import aiohttp
13071309

1310+
# 内部辅助函数:检查主机解析到的IP是否安全,防止访问内网/本地地址
1311+
def _is_safe_hostname(parsed) -> bool:
1312+
hostname = parsed.hostname
1313+
if not hostname:
1314+
return False
1315+
try:
1316+
# 解析主机名对应的所有地址
1317+
addrinfo_list = socket.getaddrinfo(hostname, None)
1318+
except Exception:
1319+
return False
1320+
for family, _, _, _, sockaddr in addrinfo_list:
1321+
ip_str = (
1322+
sockaddr[0] if family in (socket.AF_INET, socket.AF_INET6) else None
1323+
)
1324+
if not ip_str:
1325+
continue
1326+
try:
1327+
ip_obj = ipaddress.ip_address(ip_str)
1328+
except ValueError:
1329+
return False
1330+
# 拒绝内网、回环、链路本地、多播和保留地址
1331+
if (
1332+
ip_obj.is_private
1333+
or ip_obj.is_loopback
1334+
or ip_obj.is_link_local
1335+
or ip_obj.is_multicast
1336+
or ip_obj.is_reserved
1337+
):
1338+
return False
1339+
return True
1340+
13081341
try:
13091342
# 验证URL格式
13101343
parsed_url = urlparse(url)
13111344
if not parsed_url.scheme or not parsed_url.netloc:
13121345
return {"success": False, "url": url, "error": "Invalid URL format"}
1346+
# 仅允许 http/https
1347+
if parsed_url.scheme not in ("http", "https"):
1348+
return {
1349+
"success": False,
1350+
"url": url,
1351+
"error": "Unsupported URL scheme",
1352+
}
1353+
# 检查主机是否安全,防止SSRF到内网
1354+
if not _is_safe_hostname(parsed_url):
1355+
return {
1356+
"success": False,
1357+
"url": url,
1358+
"error": "Unsafe target host",
1359+
}
1360+
13131361
# 创建aiohttp客户端会话
13141362
async with aiohttp.ClientSession() as session:
13151363
# 发送HEAD请求跟随重定向

0 commit comments

Comments
 (0)