CityVistion 项目全面审核报告

审核时间:2026-06-21  |  服务器:47.95.213.144  |  域名:cityvistion.cn
总体结论:有隐患,存在 1 个 P0 生产事故级问题。
核心服务全部 active,但 www.cityvistion.cn 全站静态资源 403,且存在多个安全/配置隐患需立即处理。

P0 严重问题

2

P1 高危问题

7

P2 中危问题

12

核心服务状态

全部 active

一、P0 严重问题(立即修复)

P0 1. www.cityvistion.cn 全站静态资源 403 Forbidden

位置/etc/nginx/sites-enabled/cityvistion-migration
根因/www/wwwroot/cityvistion.cn 是符号链接指向 /root/cityvistion.cn/root 目录权限为 drwx------,nginx worker(www-data)无法进入
影响首页、控制台、管理后台、登录页、JS/CSS/图片、CesiumJS vendor 全部无法加载
修复推荐将 /www/wwwroot/cityvistion.cn 改为独立实体目录(复制内容过来),或调整 Nginx location /static/ 指向并对 www-data 开放读取权限

P0 2. Open-Meteo 地理编码成功时抛出 NameError

位置/root/cityvistion.cn/app/public.py:558
根因print() 中使用了未定义变量 namecountry_code
影响城市生成时 OSM 地理编码本可成功,但因异常回退到 Nominatim/Overpass,失败时返回 502
修复改为 best.get("name")best.get("country_code")

二、P1 高危问题(今日内修复)

#问题位置影响修复建议
P1 3 /opt/cityvistion/.env 全局可读(644) /opt/cityvistion/.env 任何本地用户可读取 OSS AK/SK、JWT Secret、API Key、Redis 密码 chmod 600 并轮换其中所有密钥
P1 4 cityvistion / cgajs-api 服务以 root 运行 /etc/systemd/system/cityvistion.service
/etc/systemd/system/cgajs-api.service
一旦被漏洞利用,直接获得 root 权限 创建专用系统用户,systemd 中设置 User= / Group=
P1 5 Redis 监听 0.0.0.0,且 UFW 允许旧服务器访问 /etc/redis/redis.conf、UFW Redis 密码直接暴露在网络层,存在爆破/漏洞利用风险 Redis 改为 bind 127.0.0.1 ::1;删除旧 UFW 规则
P1 6 Runtime /api/v1/cv/jobs/{job_id} 未授权访问 /opt/cityvistion/app/main.py:95 知道 job_id 即可获取任务结果,绕过 API Key 校验 增加 Depends(verify_api_key)
P1 7 Embedding /embed 接口未认证且对公网开放 /opt/cityvistion/app/embedding_service.py:38
Nginx runtime 配置
任何人可无限制调用本地 bge-m3 模型,造成 DoS 增加 API Key 校验,或 Nginx 层限制仅 127.0.0.1 访问
P1 8 cgajs-api CORS 仍允许旧域名 /www/wwwroot/cgajs-api/main.py:87-108 旧域名若被第三方注册或原服务器被入侵,可利用 CORS 发起跨域攻击 移除 cgajs.cityvistion.cnrulepackage.cityvistion.cn,仅保留 *.cityvistion.cn
P1 9 cgajs-api 认证 Cookie 未设置 HttpOnly /www/wwwroot/cgajs-api/main.py:618-633 XSS 可导致 cgajs_token 被盗 httponly=True

三、P2 中危问题(本周内修复)

#问题位置影响修复建议
10log_usage 参数顺序错误/root/cityvistion.cn/app/public.py:63使用统计与计费报表数据错误改为 log_usage(..., action, db, cost=cost)
11订阅过期直接抛 Exception,导致 500/root/cityvistion.cn/app/quota.py:40用户订阅过期后调用接口返回 500改为返回 403 或清晰提示
12cv_preview / cv_export 先扣配额再执行/root/cityvistion.cn/app/main.py下游失败时配额已消耗先检查可用性再扣配额;失败回滚 Redis
13多处硬编码弱默认密钥/密码/opt/cityvistion/app/config.py
/root/cityvistion.cn/app/config.py
环境变量未加载时使用弱凭据默认值改为空字符串,缺失则拒绝启动
14密码重置 Token 可能在前端显示/root/cityvistion.cn/app/main.py:464
/root/cityvistion.cn/static/auth.html:139
debug 误开启时可在页面明文看到 reset_token前端删除展示逻辑;后端不向前端返回 Token
15留言板存在存储型 XSS 风险/root/cityvistion.cn/app/messages.py可导致存储型 XSS后端做 HTML 转义,前端使用 textContent
16文件上传无大小/内容校验/root/cityvistion.cn/app/files.py:148-200存在 DoS 与恶意文件上传风险增加大小限制、MIME 白名单、文件头 magic 校验
17/api/v1/auth/* 限流豁免,存在爆破风险/root/cityvistion.cn/app/main.py:141登录/注册/重置密码无 IP/账号级限流对认证端点单独设置更严格限流
18certbot 钩子硬编码阿里云 AK/SK/etc/letsencrypt/hooks/add_txt.py
/etc/letsencrypt/hooks/del_txt.py
泄露后可用于操作 DNS 记录迁移到环境变量文件或改用 RAM 角色
19Nginx 缺少基础安全响应头/etc/nginx/sites-enabled/cityvistion-migration增加点击劫持、MIME 嗅探、XSS 风险添加 X-Frame-Options、HSTS 等
20cgajs-api 备份文件世界可读/www/wwwroot/cgajs-api/*.bak.*历史版本可能含旧密钥/逻辑删除或移至非 web 目录并限制权限
21旧域名大量残留在前端与 CGA 文件中IDE、Marketplace、CGA 纹理 URL用户可能跳转到旧域名,资源 404 或证书错误/root/TASKS.md P2/P3 批量清理

四、P3 建议项(后续优化)

运维与可观测性

架构与代码

五、运行状态快照

项目状态
核心服务全部 active
磁盘40G 已用 21G(55%)
内存7.1G,可用约 4.1G
SSL 证书cityvistion_wildcard,有效期至 2026-09-19
数据库cityvistion 12MB,cgajs 24MB,连接正常
Nginx 配置语法nginx -t 通过
监控栈Prometheus、Grafana、Loki、Promtail、Node Exporter 均 active
值得肯定的方面: 支付回调签名校验完整、服务间 HMAC-SHA256 鉴权合理、JWT 黑名单机制正确、PostgreSQL 未暴露公网、SSL 通配符证书已覆盖所有子域、敏感配置文件(/etc/cityvistion//etc/cgajs/)权限合规。

六、原技术路线图

updata.html 中的 CGA.js / NL2CGA 技术路线图已归档到: https://cgajs.cityvistion.cn/updata-roadmap.html