Skip to content

Latest commit

 

History

History
229 lines (168 loc) · 16 KB

File metadata and controls

229 lines (168 loc) · 16 KB

代码安全审查记录

审查目标

对 GradNote-v1 项目进行全面的代码安全审查,识别潜在的安全漏洞和风险,特别是关注以下领域:

  • 敏感信息泄露:硬编码的 API 密钥、密码、数据库凭证、私钥等。
  • 身份认证与授权:检查 API 端点是否存在越权访问风险。
  • 输入验证:防止注入攻击,如 SQL 注入、命令注入等。
  • 依赖项安全:检查 requirements.txt 中是否存在已知漏洞的库。
  • 配置安全:审查 Dockerfile 和其他配置文件,防止不安全的配置。
  • 隐私数据暴露:确保 API 响应中不包含不必要的敏感用户数据。
  • 域名/IP泄露:检查代码和文档中是否硬编码了内部或测试环境的域名/IP地址。

审查计划 (To-Do List)

  • 1. 自动化扫描与初步分析
    • 1.1. 使用 search_file_content 搜索整个项目,查找常见的敏感信息关键字,例如: secret, password, token, api_key, access_key, private_key, key =, passwd
    • 1.2. 搜索可能硬编码的域名或IP地址 (例如 http://, https://, aliyuncs.com, 192.168., 127.0.0.1)。
  • 2. 配置文件审查
    • 2.1. 审查 backend/app/core/config.py,检查敏感配置的加载方式,确认是否从环境变量读取而非硬编码。
    • 2.2. 审查 backend/.env.example,确保示例文件中不包含任何真实凭证。
    • 2.3. 审查 backend/Dockerfile,检查是否存在构建时泄露密钥、使用不安全的基镜像或不当的权限配置。
  • 3. 身份认证与授权审查
    • 3.1. 审查 backend/app/core/security.py,分析密码哈希、令牌生成与验证的安全性。
    • 3.2. 审查 backend/app/api/deps.py,理解用户身份验证和依赖注入的逻辑。
    • 3.3. 逐一审查 backend/app/api/routes/ 中的所有API端点,确保需要保护的路由都正确应用了身份验证和授权依赖。
  • 4. 数据与隐私审查
    • 4.1. 审查 backend/app/api/schemas/ 中的数据模型,特别是 user.py,检查API响应是否可能泄露如密码哈希等敏感字段。
    • 4.2. 审查 backend/services/backend/db/ 中的数据库操作,初步判断是否存在SQL注入风险(例如,拼接原始SQL字符串)。
  • 5. 依赖项审查
    • 5.1. 审查 backend/requirements.txt,列出所有依赖项及其版本,为后续漏洞扫描做准备。
  • 6. 文档审查
    • 6.1. 审查项目根目录及 docs/ 目录下的所有 .md 文件,防止在文档中泄露敏感信息。

审查发现 (Review Findings)

1. 自动化扫描与初步分析 (已完成)

发现 (Findings):

  1. 默认密钥和凭证:

    • backend/app/core/config.py: SECRET_KEYPOSTGRES_PASSWORD 存在硬编码的默认值 (your-secret-key-for-development, 123456)。虽然环境变量会覆盖它们,但这是一种不安全的实践,开发环境的密钥不应如此简单。
    • backend/db/init_db.py: FIRST_SUPERUSER_PASSWORD 硬编码为 "admin"。这会创建一个默认的、密码可预测的超级用户。
  2. API密钥管理:

    • backend/app/llm_services/*/*.py: 多个服务(image_processing, knowledge_mark, solving 等)直接通过 os.getenv("OPENAI_API_KEY") 获取密钥。虽然这是标准做法,但代码中没有对密钥为空或无效的情况做充分的错误处理,可能导致应用在未正确配置时出现意外行为。
  3. 本地主机地址硬编码:

    • backend/app/core/config.py: BACKEND_CORS_ORIGINS 中硬编码了 "http://localhost:3000""http://localhost:8000"。这在开发中是常见的,但在生产环境中需要替换为实际的域名。
    • 多个文档 (README.md, docs/*.md) 和代码示例中包含了 http://localhost:8000 的地址,这对于文档是可接受的,但需要确保生产部署时不会意外使用这些地址。
  4. 文档中的敏感信息示例:

    • backend/.env.example 和多个 .md 文档中包含了如 your_generated_secret_key_here, your_password, your_api_key 等占位符。这是预期的行为,但需要确保占位符没有被意外替换为真实凭证并提交到版本库。

建议 (Recommendations):

  • 移除默认凭证: 从 config.pyinit_db.py 中移除所有硬编码的默认密码和密钥。强制要求通过环境变量提供这些值,并在启动时检查是否存在,如果不存在则抛出明确的配置错误。
  • 加强密钥处理: 在所有使用 os.getenv 的地方,增加对返回值为 None 的检查,并提供清晰的日志或异常处理。
  • CORS配置: 生产环境的 BACKEND_CORS_ORIGINS 应完全由环境变量控制,不应包含任何本地主机地址。
  • 凭证管理: 强调在任何情况下都不能将包含真实凭证的 .env 文件或任何其他配置文件提交到版本控制系统。

2. 配置文件审查 (已完成)

发现 (Findings):

  1. config.py 中的硬编码回退值:

    • assemble_db_connection 函数中,当环境变量不完整时,会回退到一个硬编码的数据库连接字符串 "postgresql://postgres:123456@localhost:5432/GradNote"。这可能导致在配置错误时,应用意外连接到本地开发数据库,存在数据混淆或泄露风险。
  2. Dockerfile 安全性:

    • 基镜像: 使用 python:3.13-slim 是一个好的选择,减少了镜像体积和潜在的攻击面。
    • 用户权限: 容器内的所有操作(包括应用运行)都以 root 用户身份执行。这是一个安全风险。最佳实践是创建一个非 root 用户来运行应用程序。
    • 依赖项安装: pip install 命令缺少 --no-cache-dir 之外的最佳实践,例如验证哈希以确保依赖项的完整性。
    • 文件复制: COPY . /app/ 指令会复制构建上下文中的所有文件。虽然项目有 .gitignore,但缺少 .dockerignore 文件可能会导致不必要的文件(如 .git 目录、本地配置文件、测试报告等)被复制到镜像中,增加镜像大小和潜在的攻击面。
  3. .env.example 文件:

    • 该文件正确地使用了占位符,没有发现硬编码的真实凭证。符合安全实践。

建议 (Recommendations):

  • 移除硬编码数据库URI: 修改 assemble_db_connection 函数,在配置不完整时应直接抛出启动异常,而不是回退到硬编码的URI。
  • 在Dockerfile中创建非root用户: 在 Dockerfile 中添加步骤来创建一个专用的、无特权的用户和组,并使用 USER 指令切换到该用户来运行应用。
  • 创建 .dockerignore 文件: 在 backend 目录下创建一个 .dockerignore 文件,至少应包含 .git, __pycache__, *.pyc, .env 等条目,以防止不必要的文件被包含在Docker镜像中。

3. 身份认证与授权审查 (已完成)

发现 (Findings):

  1. 密码哈希: security.py 使用 passlibbcrypt 方案来哈希密码。这是当前推荐的、安全的密码存储方法。
  2. JWT令牌: security.pydeps.py 中正确实现了JWT的生成和解码。令牌包含 exp (过期时间) 和 sub (用户ID) 声明,算法为 HS256。密钥从配置中安全地读取。
  3. 依赖注入与路由保护:
    • 项目有效地利用了 FastAPI 的依赖注入系统 (Depends) 来保护路由。deps.py 中的 get_current_active_user 是所有需要认证的端点的保护屏障。
    • routes 目录下的所有文件进行的审查表明,除了公开的注册和登录端点外,所有其他API端点都正确地依赖于 get_current_active_userget_current_user
  4. 水平越权保护: 在处理用户特定资源(如错题)时,代码正确地实施了水平越权保护。例如,在 questions.py 中,所有数据库查询都包含了 WrongQuestion.user_id == current_user.id 的过滤条件,确保用户只能访问自己的数据。

结论: 身份认证和授权机制设计良好,实施正确。未发现明显的认证绕过或越权漏洞。这是一个积极的发现。


4. 数据与隐私审查 (已完成)

发现 (Findings):

  1. 数据模型 (Schemas) 安全性:

    • schemas/user.py: User 响应模型没有包含 password 字段,这遵循了最佳实践,有效防止了密码哈希的泄露。
    • 其他数据模型也只暴露了必要的字段,未发现敏感信息泄露风险。
  2. 数据库操作安全性:

    • ORM使用: 项目绝大部分数据库操作都通过 SQLAlchemy ORM 完成,这是一种安全的方式,可以有效防止SQL注入。
    • 潜在的SQL注入风险: 在 db/reset_sequence.py 文件中,reset_sequence 函数使用了 f-string 来动态构造SQL语句:connection.execute(text(f"SELECT MAX(id) FROM {table_name}"))connection.execute(text(f"ALTER SEQUENCE {seq_name} RESTART WITH {next_val}"))。虽然当前调用该函数的地方 (reset_all_sequences) 使用的是硬编码的表名列表,但函数本身是不安全的。如果未来在其他地方用用户可控的输入调用此函数,将导致SQL注入漏洞。

建议 (Recommendations):

  • 修复潜在的SQL注入: 即使目前没有直接的利用路径,也应修复 reset_sequence 函数。可以通过白名单验证 table_name 参数,确保它只包含预期的、安全的表名,然后再将其拼接到SQL字符串中。

5. 依赖项审查 (已完成)

发现 (Findings):

  1. 未固定版本依赖: requirements.txt 文件中存在多个未固定版本的依赖项,包括:

    • psycopg2
    • langgraph
    • pytest
    • httpx
    • jinja2 这种做法存在风险,因为在重新构建环境时可能会自动安装这些库的最新版本,这可能引入未经测试的重大更改或新的安全漏洞。
  2. 依赖项列表:

    fastapi==0.115.12
    uvicorn==0.34.1
    SQLAlchemy==2.0.40
    pydantic==2.11.3
    pydantic_settings==2.8.1
    python-jose==3.4.0
    passlib==1.7.4
    python-multipart==0.0.6
    psycopg2
    langchain==0.3.23
    langchain-openai==0.3.12
    langchain_core==0.3.51
    langgraph
    langfuse==2.60.2
    python-dotenv==1.1.0
    pytest
    pytest-asyncio==0.23.2
    httpx
    redis==5.0.1
    jinja2
    aiofiles==24.1.0
    

建议 (Recommendations):

  • 固定所有依赖版本: 为了构建的可复现性和安全性,应将 requirements.txt 中的所有依赖项都固定到具体的版本号。例如,将 psycopg2 改为 psycopg2-binary==2.9.9
  • 定期扫描依赖项: 建议集成自动化工具(如 safetySnyk)到CI/CD流程中,以定期扫描项目依赖项是否存在已知的安全漏洞。

6. 文档审查 (已完成)

发现 (Findings):

  1. 文档内容: 项目的文档(包括根目录和 docs/ 下的 .md 文件)内容详尽,结构清晰,对项目架构、API、数据库设计和部署流程进行了全面的说明。
  2. 敏感信息: 文档中正确地使用了占位符(如 your_password, your_api_key)来表示敏感信息,未发现硬编码的真实凭证、密钥或生产环境域名。
  3. 一致性: 文档内容与代码实现基本保持一致,准确反映了项目的当前状态。

结论: 文档管理规范,未在文档中发现敏感信息泄露风险。这是一个积极的发现。


7. 补充审查发现 (Supplemental Review Findings)

在对 main.pyllm_services 目录进行补充审查后,发现以下新的问题:

  1. 不安全的CORS策略 (高危风险):

    • backend/app/main.py: 应用的CORS中间件配置为 allow_origins=["*"]。这是一个严重的安全漏洞,它允许任何域名的网页向您的API发送请求,可能导致跨站请求伪造 (CSRF) 和其他跨站攻击。虽然有注释说明生产环境应修改,但将其作为默认配置是极其危险的。
  2. 静态文件服务的潜在风险 (中等风险):

    • backend/app/main.py: 应用通过 app.mount("/uploads", StaticFiles(directory=UPLOAD_DIR)) 将上传目录直接暴露为静态文件服务。如果攻击者能够上传一个包含恶意脚本的HTML文件 (例如 malicious.html),他们就可以通过访问 http://your-domain.com/uploads/malicious.html 在您的域下执行任意JavaScript,从而窃取用户Token或执行其他恶意操作 (存储型XSS)。虽然上传路由检查了 content_type,但这并非完全可靠的防护。
  3. 生产环境中不安全的启动流程 (中等风险):

    • backend/app/main.py: 应用在启动时会自动执行 create_tables(), init_db(), reset_all_sequences() 等操作。这在开发中很方便,但在生产环境中是危险的,可能会在每次服务重启时意外重置数据库、清空数据或造成不可预料的状态。

最终审查总结 (Final Review Summary)

本次对 GradNote-v1 项目的代码安全审查已经完成。总体来看,该项目具备了良好的安全基础,特别是在身份认证、授权和防止数据泄露方面表现出色。然而,审查也发现了一些严重的安全风险,主要集中在网络配置和开发实践上。

主要风险与建议 (按优先级排序)

  • 高优先级风险:

    1. 不安全的CORS策略: 在 main.py 中,allow_origins 被设置为 ["*"]。这是最紧急需要修复的问题。
      • 建议: 立即修改CORS配置,将其设置为一个严格的前端域名白名单,并通过环境变量进行管理。
    2. 硬编码凭证: 在 config.pyinit_db.py 中存在默认的开发密钥和密码。
      • 建议: 立即移除所有硬编码的凭证,强制通过环境变量配置,并在应用启动时进行检查。
    3. 硬编码数据库回退URI: config.py 在配置不完整时会回退到本地数据库。
      • 建议: 移除该回退逻辑,在配置不完整时应直接抛出异常并终止启动。
    4. 潜在的SQL注入: db/reset_sequence.py 中存在使用f-string构造SQL语句的情况。
      • 建议: 对传入的表名进行严格的白名单验证,防止SQL注入。
  • 中优先级风险:

    1. 静态文件服务的XSS风险: uploads 目录被直接提供静态服务。
      • 建议: 实施更严格的文件上传策略。例如:1) 不允许上传HTML/JS等可执行文件类型。2) 对所有上传文件进行内容层面的类型校验(而不仅仅是依赖Content-Type头)。3) 将用户上传内容托管在完全独立的域名下。
    2. 生产环境中不安全的启动流程: 应用启动时会自动初始化数据库。
      • 建议: 将数据库迁移和初始化操作从应用启动流程中分离,使用独立的迁移脚本(如Alembic)进行管理。
    3. Docker容器权限: Dockerfile 中使用 root 用户运行应用。
      • 建议: 创建一个非特权用户来运行应用,遵循最小权限原则。
    4. 未固定依赖版本: requirements.txt 中存在未固定版本的依赖。
      • 建议: 将所有依赖项固定到具体版本,以确保构建的可复现性和安全性。
  • 低优先级风险:

    1. 缺少 .dockerignore: Dockerfile 的构建上下文中可能包含不必要的文件。
      • 建议: 创建 .dockerignore 文件以减小镜像体积并排除敏感文件。
    2. API密钥处理: 代码中获取环境变量后缺少对 None 值的检查。
      • 建议: 增加对密钥是否成功加载的判断和错误处理。

总体结论

GradNote-v1 是一个功能完善、结构清晰的项目。但当前存在的高危配置问题(特别是CORS策略)使其不适合直接部署到生产环境。通过解决上述报告中提出的问题,特别是高优先级的风险点,可以显著提升其安全性和健robustness,为项目的安全部署做好充分准备。