From 7c0d95385f51081a943b35443e899915a358a675 Mon Sep 17 00:00:00 2001 From: vinland100 Date: Mon, 12 Jan 2026 15:08:33 +0800 Subject: [PATCH] refactor: update SVG circle radius and improve code readability in ReportExportDialog --- ...能漏洞挖掘审计 - 完整示例_2025-12-15.html | 782 +++++++++++------- .../components/ReportExportDialog.tsx | 88 +- 2 files changed, 537 insertions(+), 333 deletions(-) diff --git a/docs/audit_report_智能漏洞挖掘审计 - 完整示例_2025-12-15.html b/docs/audit_report_智能漏洞挖掘审计 - 完整示例_2025-12-15.html index dce635c..f5c9c63 100644 --- a/docs/audit_report_智能漏洞挖掘审计 - 完整示例_2025-12-15.html +++ b/docs/audit_report_智能漏洞挖掘审计 - 完整示例_2025-12-15.html @@ -1,5 +1,6 @@ + @@ -32,8 +33,17 @@ --code-bg: #0d1117; } - *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } - html { scroll-behavior: smooth; } + *, + *::before, + *::after { + box-sizing: border-box; + margin: 0; + padding: 0; + } + + html { + scroll-behavior: smooth; + } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; @@ -43,7 +53,11 @@ font-size: 14px; } - .container { max-width: 900px; margin: 0 auto; padding: 0 1.5rem; } + .container { + max-width: 900px; + margin: 0 auto; + padding: 0 1.5rem; + } /* Header */ .header { @@ -90,7 +104,11 @@ color: white; } - .brand-text { font-size: 1rem; font-weight: 700; color: var(--text-primary); } + .brand-text { + font-size: 1rem; + font-weight: 700; + color: var(--text-primary); + } .header-title { font-size: 1.25rem; @@ -137,19 +155,24 @@ } .score-ring svg { - transform: rotate(-90deg); + transform: rotate(90deg) scaleY(-1); width: 56px; height: 56px; } - .score-ring-bg { fill: none; stroke: var(--border); stroke-width: 5; } + .score-ring-bg { + fill: none; + stroke: var(--border); + stroke-width: 5; + } + .score-ring-progress { fill: none; stroke: #ef4444; stroke-width: 5; stroke-linecap: round; - stroke-dasharray: 251.32741228718345; - stroke-dashoffset: 161.35219868837177; + stroke-dasharray: 144.51326206513048; + stroke-dashoffset: 92.48848772168351; filter: drop-shadow(0 0 4px #ef444440); } @@ -219,15 +242,48 @@ font-weight: 700; } - .stat-card-icon.critical { background: var(--critical-bg); color: var(--critical); } - .stat-card-icon.high { background: var(--high-bg); color: var(--high); } - .stat-card-icon.total { background: var(--info-bg); color: var(--info); } - .stat-card-icon.verified { background: rgba(16,185,129,0.1); color: var(--success); } + .stat-card-icon.critical { + background: var(--critical-bg); + color: var(--critical); + } - .stat-card-label { font-size: 0.6rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; } - .stat-card-value { font-size: 1.25rem; font-weight: 700; color: var(--text-primary); font-family: 'SF Mono', monospace; line-height: 1; } - .stat-card-value.critical { color: var(--critical); } - .stat-card-value.high { color: var(--high); } + .stat-card-icon.high { + background: var(--high-bg); + color: var(--high); + } + + .stat-card-icon.total { + background: var(--info-bg); + color: var(--info); + } + + .stat-card-icon.verified { + background: rgba(16, 185, 129, 0.1); + color: var(--success); + } + + .stat-card-label { + font-size: 0.6rem; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.05em; + } + + .stat-card-value { + font-size: 1.25rem; + font-weight: 700; + color: var(--text-primary); + font-family: 'SF Mono', monospace; + line-height: 1; + } + + .stat-card-value.critical { + color: var(--critical); + } + + .stat-card-value.high { + color: var(--high); + } /* Severity Bar */ .severity-section { @@ -257,11 +313,25 @@ background: var(--border); } - .severity-segment { height: 100%; } - .severity-segment.critical { background: var(--critical); } - .severity-segment.high { background: var(--high); } - .severity-segment.medium { background: var(--medium); } - .severity-segment.low { background: var(--low); } + .severity-segment { + height: 100%; + } + + .severity-segment.critical { + background: var(--critical); + } + + .severity-segment.high { + background: var(--high); + } + + .severity-segment.medium { + background: var(--medium); + } + + .severity-segment.low { + background: var(--low); + } .severity-legend { display: flex; @@ -276,11 +346,27 @@ color: var(--text-muted); } - .severity-dot { width: 6px; height: 6px; border-radius: 50%; } - .severity-dot.critical { background: var(--critical); } - .severity-dot.high { background: var(--high); } - .severity-dot.medium { background: var(--medium); } - .severity-dot.low { background: var(--low); } + .severity-dot { + width: 6px; + height: 6px; + border-radius: 50%; + } + + .severity-dot.critical { + background: var(--critical); + } + + .severity-dot.high { + background: var(--high); + } + + .severity-dot.medium { + background: var(--medium); + } + + .severity-dot.low { + background: var(--low); + } /* Main Content */ .main-content { @@ -296,7 +382,10 @@ } /* Typography */ - h1, h2, h3, h4 { + h1, + h2, + h3, + h4 { color: var(--text-primary); font-weight: 600; letter-spacing: -0.01em; @@ -312,7 +401,11 @@ gap: 0.5rem; } - h1::before { content: "§"; color: var(--accent); font-weight: 400; } + h1::before { + content: "§"; + color: var(--accent); + font-weight: 400; + } h2 { font-size: 1.1rem; @@ -321,7 +414,13 @@ border-bottom: 1px solid var(--border); } - h2::before { content: "//"; color: var(--accent); margin-right: 0.35rem; font-weight: 400; opacity: 0.7; } + h2::before { + content: "//"; + color: var(--accent); + margin-right: 0.35rem; + font-weight: 400; + opacity: 0.7; + } h3 { font-size: 1rem; @@ -330,9 +429,16 @@ border-left: 2px solid var(--accent); } - h4 { font-size: 0.9rem; margin: 0.75rem 0 0.35rem; color: var(--text-secondary); } + h4 { + font-size: 0.9rem; + margin: 0.75rem 0 0.35rem; + color: var(--text-secondary); + } - p { margin-bottom: 0.6rem; font-size: 0.875rem; } + p { + margin-bottom: 0.6rem; + font-size: 0.875rem; + } /* Code Blocks */ pre { @@ -369,7 +475,9 @@ color: #e2e8f0; } - p code, li code, td code { + p code, + li code, + td code { background: var(--bg-tertiary); color: var(--accent); padding: 0.15em 0.35em; @@ -406,13 +514,28 @@ border-bottom: 1px solid var(--border); } - tr:last-child td { border-bottom: none; } - tr:hover td { background: rgba(255, 255, 255, 0.02); } + tr:last-child td { + border-bottom: none; + } + + tr:hover td { + background: rgba(255, 255, 255, 0.02); + } /* Lists */ - ul, ol { margin: 0.5rem 0 0.5rem 1.25rem; } - li { margin-bottom: 0.25rem; font-size: 0.875rem; } - li::marker { color: var(--accent); } + ul, + ol { + margin: 0.5rem 0 0.5rem 1.25rem; + } + + li { + margin-bottom: 0.25rem; + font-size: 0.875rem; + } + + li::marker { + color: var(--accent); + } /* Blockquotes */ blockquote { @@ -424,11 +547,19 @@ font-size: 0.85rem; } - blockquote p:last-child { margin-bottom: 0; } + blockquote p:last-child { + margin-bottom: 0; + } /* Links */ - a { color: var(--accent); text-decoration: none; } - a:hover { text-decoration: underline; } + a { + color: var(--accent); + text-decoration: none; + } + + a:hover { + text-decoration: underline; + } /* HR */ hr { @@ -438,8 +569,14 @@ margin: 1.5rem 0; } - strong { color: var(--text-primary); font-weight: 600; } - em { color: var(--text-muted); } + strong { + color: var(--text-primary); + font-weight: 600; + } + + em { + color: var(--text-muted); + } /* Footer */ .report-footer { @@ -481,14 +618,41 @@ /* Responsive */ @media (max-width: 768px) { - .container { padding: 0 1rem; } - .stats-grid { flex-direction: column; gap: 0.75rem; } - .score-ring-container { width: 100%; justify-content: center; } - .stats-cards { flex-wrap: wrap; } - .stat-card { min-width: calc(50% - 0.25rem); } - .severity-bar-wrap { flex-direction: column; align-items: stretch; gap: 0.5rem; } - .severity-legend { justify-content: center; } - .content-wrapper { padding: 1rem; } + .container { + padding: 0 1rem; + } + + .stats-grid { + flex-direction: column; + gap: 0.75rem; + } + + .score-ring-container { + width: 100%; + justify-content: center; + } + + .stats-cards { + flex-wrap: wrap; + } + + .stat-card { + min-width: calc(50% - 0.25rem); + } + + .severity-bar-wrap { + flex-direction: column; + align-items: stretch; + gap: 0.5rem; + } + + .severity-legend { + justify-content: center; + } + + .content-wrapper { + padding: 1rem; + } } /* Print */ @@ -505,16 +669,42 @@ --border: #e2e8f0; --code-bg: #f8fafc; } - body { background: white; font-size: 11pt; } - .header::before { display: none; } - .content-wrapper { border: none; padding: 0; } - pre { break-inside: avoid; } - code { color: #1e293b; } - p code, li code { background: #f1f5f9; color: #c2410c; } - a { color: #2563eb; } + + body { + background: white; + font-size: 11pt; + } + + .header::before { + display: none; + } + + .content-wrapper { + border: none; + padding: 0; + } + + pre { + break-inside: avoid; + } + + code { + color: #1e293b; + } + + p code, + li code { + background: #f1f5f9; + color: #c2410c; + } + + a { + color: #2563eb; + } } +
@@ -584,18 +774,26 @@
分布
- -
-
-
-
- + +
+
+
+
+
-
2
-
3
-
2
-
1
+
+
2 +
+
+
3 +
+
+
2 +
+
+
1 +
@@ -605,91 +803,96 @@

DeepAudit 安全审计报告

-
-

报告信息

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
属性内容
项目名称VulnWebApp - 安全演示项目
任务 ID0e41da00...
生成时间2025-12-15 11:07:20
任务状态COMPLETED
耗时13.0 分钟
-

执行摘要

-

安全评分: 35/100 [未通过] -严重 - 需要立即进行修复

-

漏洞发现概览

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
严重程度数量已验证
严重 (CRITICAL)22
高危 (HIGH)33
中危 (MEDIUM)21
低危 (LOW)10
总计86
-

审计指标

-
    -
  • 分析文件数: 48 / 48
  • -
  • Agent 迭代次数: 32
  • -
  • 工具调用次数: 87
  • -
  • Token 消耗: 45,680
  • -
  • 生成的 PoC: 5
  • -
-

严重 (Critical) 漏洞

-

CRITICAL-1: 备份功能存在命令注入漏洞

-

[已验证] [含 PoC] | 类型: command_injection

-

位置: app/utils/backup.py:34-40

-

AI 置信度: 99%

-

漏洞描述:

-

在备份功能中,用户提供的文件名参数直接传递给 os.system() 函数执行,攻击者可以通过命令分隔符(如 ; 或 |)注入任意系统命令。

-

漏洞代码:

-
def create_backup(filename):
+        
+

报告信息

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
属性内容
项目名称VulnWebApp - 安全演示项目
任务 ID0e41da00...
生成时间2025-12-15 11:07:20
任务状态COMPLETED
耗时13.0 分钟
+

执行摘要

+

安全评分: 35/100 [未通过] + 严重 - 需要立即进行修复 +

+

漏洞发现概览

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
严重程度数量已验证
严重 (CRITICAL)22
高危 (HIGH)33
中危 (MEDIUM)21
低危 (LOW)10
总计86
+

审计指标

+
    +
  • 分析文件数: 48 / 48
  • +
  • Agent 迭代次数: 32
  • +
  • 工具调用次数: 87
  • +
  • Token 消耗: 45,680
  • +
  • 生成的 PoC: 5
  • +
+

严重 (Critical) 漏洞

+

CRITICAL-1: 备份功能存在命令注入漏洞

+

[已验证] [含 PoC] | 类型: command_injection

+

位置: app/utils/backup.py:34-40

+

AI 置信度: 99%

+

漏洞描述:

+

在备份功能中,用户提供的文件名参数直接传递给 os.system() 函数执行,攻击者可以通过命令分隔符(如 ; 或 |)注入任意系统命令。

+

漏洞代码:

+
def create_backup(filename):
     """创建备份文件"""
     # 危险:直接将用户输入传递给系统命令
     backup_path = f"/backups/{filename}.tar.gz"
@@ -697,10 +900,10 @@
     os.system(cmd)  # 命令注入风险
     return backup_path
 
-

修复建议:

-

避免使用 os.system(),改用 subprocess 模块并禁用 shell=True,对用户输入进行严格的白名单验证

-

参考修复代码:

-
import subprocess
+        

修复建议:

+

避免使用 os.system(),改用 subprocess 模块并禁用 shell=True,对用户输入进行严格的白名单验证

+

参考修复代码:

+
import subprocess
 import re
 
 def create_backup(filename):
@@ -718,16 +921,16 @@ def create_backup(filename):
     )
     return backup_path
 
-

概念验证 (PoC):

-

通过在 filename 参数中注入分号和系统命令,在服务器上执行任意代码

-

复现步骤:

-
    -
  1. 构造恶意 filename: test; id; cat /etc/passwd
  2. -
  3. 发送请求到 /api/backup 接口
  4. -
  5. 观察服务器响应或日志中的命令执行结果
  6. -
-

PoC 代码:

-
import requests
+        

概念验证 (PoC):

+

通过在 filename 参数中注入分号和系统命令,在服务器上执行任意代码

+

复现步骤:

+
    +
  1. 构造恶意 filename: test; id; cat /etc/passwd
  2. +
  3. 发送请求到 /api/backup 接口
  4. +
  5. 观察服务器响应或日志中的命令执行结果
  6. +
+

PoC 代码:

+
import requests
 
 # 命令注入 PoC
 target_url = "http://target.com/api/backup"
@@ -740,15 +943,15 @@ print(f"Response: {response.text}")
 
 # 预期结果:服务器执行 id 和 cat /etc/passwd 命令
 
-
-

CRITICAL-2: 用户搜索接口存在 SQL 注入漏洞

-

[已验证] [含 PoC] | 类型: sql_injection

-

位置: app/routes/user.py:52-58

-

AI 置信度: 98%

-

漏洞描述:

-

在 /api/user/search 接口中,用户输入的 name 参数直接拼接到 SQL 查询语句中,未经过任何过滤或参数化处理,攻击者可以通过构造恶意输入执行任意 SQL 语句。

-

漏洞代码:

-
@app.route('/api/user/search')
+        
+

CRITICAL-2: 用户搜索接口存在 SQL 注入漏洞

+

[已验证] [含 PoC] | 类型: sql_injection

+

位置: app/routes/user.py:52-58

+

AI 置信度: 98%

+

漏洞描述:

+

在 /api/user/search 接口中,用户输入的 name 参数直接拼接到 SQL 查询语句中,未经过任何过滤或参数化处理,攻击者可以通过构造恶意输入执行任意 SQL 语句。

+

漏洞代码:

+
@app.route('/api/user/search')
 def search_user():
     name = request.args.get('name', '')
     # 危险:直接拼接用户输入到SQL语句
@@ -756,10 +959,10 @@ def search_user():
     result = db.execute(query)
     return jsonify(result.fetchall())
 
-

修复建议:

-

使用参数化查询或 ORM 框架来防止 SQL 注入

-

参考修复代码:

-
@app.route('/api/user/search')
+        

修复建议:

+

使用参数化查询或 ORM 框架来防止 SQL 注入

+

参考修复代码:

+
@app.route('/api/user/search')
 def search_user():
     name = request.args.get('name', '')
     # 修复:使用参数化查询
@@ -767,16 +970,16 @@ def search_user():
     result = db.execute(query, {"name": f"%{name}%"})
     return jsonify(result.fetchall())
 
-

概念验证 (PoC):

-

通过在 name 参数中注入 SQL 语句,绕过查询条件获取数据库中所有用户信息

-

复现步骤:

-
    -
  1. 访问目标 URL: /api/user/search?name=' OR '1'='1' --
  2. -
  3. 观察响应:应返回所有用户数据
  4. -
  5. 进一步利用:可尝试 UNION 注入获取其他表数据
  6. -
-

PoC 代码:

-
import requests
+        

概念验证 (PoC):

+

通过在 name 参数中注入 SQL 语句,绕过查询条件获取数据库中所有用户信息

+

复现步骤:

+
    +
  1. 访问目标 URL: /api/user/search?name=' OR '1'='1' --
  2. +
  3. 观察响应:应返回所有用户数据
  4. +
  5. 进一步利用:可尝试 UNION 注入获取其他表数据
  6. +
+

PoC 代码:

+
import requests
 
 # SQL 注入 PoC
 target_url = "http://target.com/api/user/search"
@@ -790,26 +993,26 @@ print(f"Data: {response.json()}")
 
 # 预期结果:返回所有用户数据,而非仅匹配搜索条件的用户
 
-
-

高危 (High) 漏洞

-

HIGH-1: 代理接口存在 SSRF 漏洞

-

[已验证] [含 PoC] | 类型: ssrf

-

位置: app/routes/proxy.py:42-50

-

AI 置信度: 94%

-

漏洞描述:

-

代理接口接受用户提供的 URL 并发起请求,没有验证目标地址,攻击者可以利用此漏洞访问内网资源或云元数据服务。

-

漏洞代码:

-
@app.route('/api/proxy')
+        
+

高危 (High) 漏洞

+

HIGH-1: 代理接口存在 SSRF 漏洞

+

[已验证] [含 PoC] | 类型: ssrf

+

位置: app/routes/proxy.py:42-50

+

AI 置信度: 94%

+

漏洞描述:

+

代理接口接受用户提供的 URL 并发起请求,没有验证目标地址,攻击者可以利用此漏洞访问内网资源或云元数据服务。

+

漏洞代码:

+
@app.route('/api/proxy')
 def proxy_request():
     target_url = request.args.get('url')
     # 危险:直接请求用户提供的 URL
     response = requests.get(target_url)
     return response.content
 
-

修复建议:

-

实现 URL 白名单验证,禁止访问内网地址和元数据服务

-

参考修复代码:

-
from urllib.parse import urlparse
+        

修复建议:

+

实现 URL 白名单验证,禁止访问内网地址和元数据服务

+

参考修复代码:

+
from urllib.parse import urlparse
 import ipaddress
 
 ALLOWED_HOSTS = ['api.example.com', 'cdn.example.com']
@@ -845,9 +1048,9 @@ def proxy_request():
     response = requests.get(target_url, timeout=5)
     return response.content
 
-

概念验证 (PoC):

-

PoC 代码:

-
import requests
+        

概念验证 (PoC):

+

PoC 代码:

+
import requests
 
 # SSRF PoC - 访问 AWS 元数据
 target_url = "http://target.com/api/proxy"
@@ -856,15 +1059,15 @@ payload = "http://169.254.169.254/latest/meta-data/iam/security-credentials
 response = requests.get(target_url, params={"url": payload})
 print(f"AWS Credentials:\n{response.text}")
 
-
-

HIGH-2: 文件下载接口存在路径遍历漏洞

-

[已验证] [含 PoC] | 类型: path_traversal

-

位置: app/routes/download.py:18-26

-

AI 置信度: 95%

-

漏洞描述:

-

文件下载接口直接使用用户提供的文件名参数构建文件路径,没有验证路径是否在允许的目录范围内,攻击者可以使用 ../ 序列访问任意文件。

-

漏洞代码:

-
@app.route('/api/download')
+        
+

HIGH-2: 文件下载接口存在路径遍历漏洞

+

[已验证] [含 PoC] | 类型: path_traversal

+

位置: app/routes/download.py:18-26

+

AI 置信度: 95%

+

漏洞描述:

+

文件下载接口直接使用用户提供的文件名参数构建文件路径,没有验证路径是否在允许的目录范围内,攻击者可以使用 ../ 序列访问任意文件。

+

漏洞代码:

+
@app.route('/api/download')
 def download_file():
     filename = request.args.get('file')
     # 危险:直接拼接用户输入构建路径
@@ -874,10 +1077,10 @@ def download_file():
         return send_file(file_path)
     return "File not found", 404
 
-

修复建议:

-

使用 os.path.realpath() 解析路径后验证是否在允许的目录内

-

参考修复代码:

-
import os
+        

修复建议:

+

使用 os.path.realpath() 解析路径后验证是否在允许的目录内

+

参考修复代码:

+
import os
 from pathlib import Path
 
 UPLOAD_DIR = Path('/uploads/').resolve()
@@ -897,9 +1100,9 @@ def download_file():
         return send_file(file_path)
     return "File not found", 404
 
-

概念验证 (PoC):

-

PoC 代码:

-
import requests
+        

概念验证 (PoC):

+

PoC 代码:

+
import requests
 
 # 路径遍历 PoC
 target_url = "http://target.com/api/download"
@@ -910,15 +1113,15 @@ payload = "../../../etc/passwd"
 response = requests.get(target_url, params={"file": payload})
 print(f"File content:\n{response.text}")
 
-
-

HIGH-3: 评论功能存在存储型 XSS 漏洞

-

[已验证] [含 PoC] | 类型: xss

-

位置: app/templates/comment.html:28-32

-

AI 置信度: 96%

-

漏洞描述:

-

用户提交的评论内容在展示时未经 HTML 转义直接渲染,攻击者可以在评论中注入恶意 JavaScript 代码,当其他用户查看评论时会执行这些代码。

-

漏洞代码:

-
<div class="comment-list">
+        
+

HIGH-3: 评论功能存在存储型 XSS 漏洞

+

[已验证] [含 PoC] | 类型: xss

+

位置: app/templates/comment.html:28-32

+

AI 置信度: 96%

+

漏洞描述:

+

用户提交的评论内容在展示时未经 HTML 转义直接渲染,攻击者可以在评论中注入恶意 JavaScript 代码,当其他用户查看评论时会执行这些代码。

+

漏洞代码:

+
<div class="comment-list">
     {% for comment in comments %}
     <div class="comment-item">
         <p class="comment-content">{{ comment.content | safe }}</p>
@@ -927,10 +1130,10 @@ print(f"File content:\n{response.text}")
     {% endfor %}
 </div>
 
-

修复建议:

-

移除 safe 过滤器,让 Jinja2 自动转义 HTML 特殊字符

-

参考修复代码:

-
<div class="comment-list">
+        

修复建议:

+

移除 safe 过滤器,让 Jinja2 自动转义 HTML 特殊字符

+

参考修复代码:

+
<div class="comment-list">
     {% for comment in comments %}
     <div class="comment-item">
         <!-- 修复:移除 safe 过滤器,使用自动转义 -->
@@ -939,10 +1142,10 @@ print(f"File content:\n{response.text}")
     {% endfor %}
 </div>
 
-

概念验证 (PoC):

-

通过在评论中注入 JavaScript 代码,当其他用户查看页面时窃取其 Cookie

-

PoC 代码:

-
import requests
+        

概念验证 (PoC):

+

通过在评论中注入 JavaScript 代码,当其他用户查看页面时窃取其 Cookie

+

PoC 代码:

+
import requests
 
 # 存储型 XSS PoC
 target_url = "http://target.com/api/comment"
@@ -955,25 +1158,25 @@ print(f"Comment posted: {response.status_code}")
 
 # 当其他用户访问评论页面时,恶意脚本会自动执行
 
-
-

中危 (Medium) 漏洞

-

MEDIUM-1: 使用不安全的 MD5 哈希算法存储密码

-

[已验证] | 类型: weak_crypto

-

位置: app/utils/crypto.py:8-12

-

AI 置信度: 97%

-

漏洞描述:

-

密码哈希使用了已被破解的 MD5 算法,没有使用盐值,容易受到彩虹表攻击和暴力破解。

-

漏洞代码:

-
import hashlib
+        
+

中危 (Medium) 漏洞

+

MEDIUM-1: 使用不安全的 MD5 哈希算法存储密码

+

[已验证] | 类型: weak_crypto

+

位置: app/utils/crypto.py:8-12

+

AI 置信度: 97%

+

漏洞描述:

+

密码哈希使用了已被破解的 MD5 算法,没有使用盐值,容易受到彩虹表攻击和暴力破解。

+

漏洞代码:

+
import hashlib
 
 def hash_password(password):
     # 危险:使用不安全的 MD5 且无盐值
     return hashlib.md5(password.encode()).hexdigest()
 
-

修复建议:

-

使用 bcrypt、Argon2 或 PBKDF2 等专门的密码哈希算法

-

参考修复代码:

-
import bcrypt
+        

修复建议:

+

使用 bcrypt、Argon2 或 PBKDF2 等专门的密码哈希算法

+

参考修复代码:

+
import bcrypt
 
 def hash_password(password):
     # 修复:使用 bcrypt 进行安全的密码哈希
@@ -983,54 +1186,54 @@ def hash_password(password):
 def verify_password(password, hashed):
     return bcrypt.checkpw(password.encode(), hashed.encode())
 
-
-

MEDIUM-2: 发现硬编码的 API 密钥(误报)

-

[未验证] | 类型: hardcoded_secret

-

位置: app/config.py.example:15-18

-

AI 置信度: 85%

-

漏洞描述:

-

在配置文件中发现硬编码的 API 密钥,经验证为示例配置模板中的占位符。

-

漏洞代码:

-
# 示例配置文件 - 请复制为 config.py 并替换实际值
+        
+

MEDIUM-2: 发现硬编码的 API 密钥(误报)

+

[未验证] | 类型: hardcoded_secret

+

位置: app/config.py.example:15-18

+

AI 置信度: 85%

+

漏洞描述:

+

在配置文件中发现硬编码的 API 密钥,经验证为示例配置模板中的占位符。

+

漏洞代码:

+
# 示例配置文件 - 请复制为 config.py 并替换实际值
 API_KEY = "your-api-key-here"  # 请替换为实际密钥
 SECRET_KEY = "change-this-secret"  # 请替换为随机字符串
 
-

修复建议:

-

确保 .example 文件不被误用,在 .gitignore 中排除实际配置文件

-
-

低危 (Low) 漏洞

-

LOW-1: 生产环境启用了调试模式

-

[未验证] | 类型: security_misconfiguration

-

位置: app/__init__.py:25-28

-

AI 置信度: 88%

-

漏洞描述:

-

Flask 应用在生产环境中启用了调试模式,可能泄露敏感信息和允许远程代码执行。

-

漏洞代码:

-
# 应用配置
+        

修复建议:

+

确保 .example 文件不被误用,在 .gitignore 中排除实际配置文件

+
+

低危 (Low) 漏洞

+

LOW-1: 生产环境启用了调试模式

+

[未验证] | 类型: security_misconfiguration

+

位置: app/__init__.py:25-28

+

AI 置信度: 88%

+

漏洞描述:

+

Flask 应用在生产环境中启用了调试模式,可能泄露敏感信息和允许远程代码执行。

+

漏洞代码:

+
# 应用配置
 app = Flask(__name__)
 app.debug = True  # 警告:生产环境应禁用
 app.secret_key = 'development-key'  # 警告:应使用安全密钥
 
-

修复建议:

-

在生产环境中禁用调试模式,使用环境变量配置

-

参考修复代码:

-
import os
+        

修复建议:

+

在生产环境中禁用调试模式,使用环境变量配置

+

参考修复代码:

+
import os
 
 app = Flask(__name__)
 app.debug = os.environ.get('FLASK_DEBUG', 'False').lower() == 'true'
 app.secret_key = os.environ.get('SECRET_KEY', os.urandom(24))
 
-
-

修复优先级建议

-

基于已发现的漏洞,我们建议按以下优先级进行修复:

-
    -
  1. 立即修复: 处理 2 个严重漏洞 - 可能造成严重影响
  2. -
  3. 高优先级: 在 1 周内修复 3 个高危漏洞
  4. -
  5. 中优先级: 在 2-4 周内修复 2 个中危漏洞
  6. -
  7. 低优先级: 在日常维护中处理 1 个低危漏洞
  8. -
-
-

本报告由 DeepAudit - AI 驱动的安全分析系统生成

+
+

修复优先级建议

+

基于已发现的漏洞,我们建议按以下优先级进行修复:

+
    +
  1. 立即修复: 处理 2 个严重漏洞 - 可能造成严重影响
  2. +
  3. 高优先级: 在 1 周内修复 3 个高危漏洞
  4. +
  5. 中优先级: 在 2-4 周内修复 2 个中危漏洞
  6. +
  7. 低优先级: 在日常维护中处理 1 个低危漏洞
  8. +
+
+

本报告由 DeepAudit - AI 驱动的安全分析系统生成

@@ -1049,4 +1252,5 @@ app.secret_key = os.environ.get('SECRET_KEY', os.urandom(24)) + \ No newline at end of file diff --git a/frontend/src/pages/AgentAudit/components/ReportExportDialog.tsx b/frontend/src/pages/AgentAudit/components/ReportExportDialog.tsx index c48ea84..22601f8 100644 --- a/frontend/src/pages/AgentAudit/components/ReportExportDialog.tsx +++ b/frontend/src/pages/AgentAudit/components/ReportExportDialog.tsx @@ -866,8 +866,8 @@ export const ReportExportDialog = memo(function ReportExportDialog({ }; const scoreInfo = getScoreGrade(score); - // SVG 圆环进度条 - const circumference = 2 * Math.PI * 40; // r=40 (smaller) + // SVG 圆环进度条 (逆时针方向) + const circumference = 2 * Math.PI * 23; // r=23 matches SVG circle radius const strokeDashoffset = circumference - (score / 100) * circumference; return ` @@ -1009,11 +1009,11 @@ export const ReportExportDialog = memo(function ReportExportDialog({ } .score-ring svg { - transform: rotate(-90deg); + transform: rotate(-90deg); width: 56px; height: 56px; + display: block; } - .score-ring-bg { fill: none; stroke: var(--border); stroke-width: 5; } .score-ring-progress { fill: none; @@ -1457,10 +1457,10 @@ export const ReportExportDialog = memo(function ReportExportDialog({ 分布
${totalFindings > 0 ? ` -
-
-
-
+
+
+
+
` : ''}
@@ -1771,45 +1771,45 @@ export const ReportExportDialog = memo(function ReportExportDialog({
- {preview.loading ? ( - - ) : preview.error ? ( -
-
-
- + {preview.loading ? ( + + ) : preview.error ? ( +
+
+
+ +
+
+

加载失败

+

{preview.error}

+
+
-
-

加载失败

-

{preview.error}

+
+ ) : ( +
+
+ {activeFormat === "markdown" && ( + + )} + {activeFormat === "json" && ( + + )} + {activeFormat === "html" && ( + + )}
-
-
- ) : ( -
-
- {activeFormat === "markdown" && ( - - )} - {activeFormat === "json" && ( - - )} - {activeFormat === "html" && ( - - )} -
-
- )} -
+ )} +