跳转至

灵扬 LingYang — 上帝视角审计报告

审计范围:全项目代码、数据、发布内容、架构设计
审计时间:2026-04-06
审计基线:commit c6cd3c7 + 未提交的 src/ 变更


一、总览

维度 评分 趋势
安全 2/106/10 🟡→🟢 修复后
代码质量 5/107/10 🟡→🟢 修复后
业务逻辑 4/106/10 🟡 仍有改进空间
架构 4/10 🟡 早期阶段
合规规范 3/107/10 🔴→🟢 修复后
内容真实性 7/10 🟢 旧文件已标记

核心结论:P0 和 P1 问题已修复。剩余 P2(配置系统、CLI 入口、测试)为中期改进项。唯一需手动操作:npm token 轮换。


二、安全问题(P0)

2.1 npm 认证令牌暴露

文件~/.npmrc
内容//registry.npmjs.org/:_authToken=npm_gW...pq(已脱敏)

风险:令牌以明文存储。虽然 .npmrc 不在 git 仓库中,但: - 该令牌对 npm registry 有发布权限(ling-term-mcp@1.0.0 就是用它发的) - 任何以 ai 用户身份运行的进程都能读取 - 如果项目被克隆到其他机器,令牌不会随之复制,但 .npmrc 的存在可能被遗忘

建议:令牌应轮换(revoke + regenerate),并考虑使用环境变量 NPM_TOKEN 替代文件存储。

2.2 数据库无访问控制 ✅ 已修复

文件~/.lingyang/contacts.db~/.lingyang/metrics.db
原权限644 (ai:ai) — 所有用户可读
修复后权限600 (ai:ai) — 仅 owner 可读写

风险(原状态): - 联系人数据库包含对外联络策略(优先级、状态、备注) - 任何本地进程/用户都能直接 sqlite3 ~/.lingyang/contacts.db 读取全部数据 - 无加密、无密码保护

修复方式:手动 chmod 600 + _get_db() 中自动执行 os.chmod()

2.3 GitHub API 无 Token — 信息泄露反向风险

文件src/metrics.py:82-95
现状:无认证调用 GitHub API,速率限制 60 次/小时。

风险:不是泄露风险,而是可靠性风险——6 个仓库 × 每小时 1 次采集 = 占用 10% 配额。超过配额后静默失败(返回 None),无重试机制,数据缺失无声无息。

2.4 import_targets_md() 解析器制造脏数据 ✅ 已修复

文件src/contacts_tracker.py:278-312(修复后)

原问题:解析器将 Markdown 表格的列标题("网址"、"版块"、"策略")和操作建议("邀请相关领域大V讨论")当作联系人导入。

已确认影响:38 条导入中 17 条是垃圾数据(已在会话中清理)。

修复方式:添加 _TABLE_HEADERS 黑名单、空名称/超长名称检查、短中文名称过滤。


三、代码质量问题

3.1 数据库连接管理:每次操作开关

文件contacts_tracker.py 全局、metrics.py 全局

模式:每个函数 conn = _get_db() → 操作 → conn.close()

问题: - 无连接池,频繁开关有性能开销(当前规模可忽略) - ~~_get_db() 每次都执行 CREATE TABLE IF NOT EXISTSPRAGMA journal_mode=WAL——浪费~~ ✅ 已修复:使用 _db_initialized 模块级标志,CREATE TABLE 仅首次执行 - ~~update() 函数存在 TOCTOU 竞态~~ ✅ 已修复:改为单连接内读+写(L163-220)

def update(contact_id, ...):
    conn = _get_db()           # 连接 1
    contact = get(contact_id)  # get() 内部又开一个连接 2,读完后关掉连接 2
    if not contact:
        conn.close()           # 关掉连接 1
        return None
    # 此时另一个进程可能已删除该联系人
    conn.execute(f"UPDATE ...")  # 在连接 1 上操作——如果数据已变,结果不可预测

3.2 SQL 拼接

文件contacts_tracker.py:142contacts_tracker.py:215

# contacts_tracker.py:142
rows = conn.execute(f"SELECT * FROM contacts{where} ORDER BY priority, updated_at DESC", params).fetchall()

# contacts_tracker.py:215  
conn.execute(f"UPDATE contacts SET {', '.join(sets)} WHERE id = ?", params)

风险等级:🟡 低。wheresets 由代码内部控制,不接受外部输入。但 f-string SQL 是反模式,容易被后续开发者误用。

3.3 无错误处理

文件:两文件全部函数

表现: - fetch_repo() 吞掉所有异常:except (HTTPError, URLError, TimeoutError): return None - _get_db() 不处理 sqlite3.OperationalError(磁盘满、权限不足等) - ~~add() 不校验参数(空名称、超长字符串)~~ ✅ 已修复:空名称检查 + 200 字符截断(L100-102) - ~~update() 不校验 status 是否在枚举范围内~~ ✅ 已修复:VALID_STATUSES 枚举校验(L173-175)

3.4 无类型校验的 dataclass 滥用

文件contacts_tracker.py:85-86

def _row_to_contact(row: sqlite3.Row) -> Contact:
    return Contact(**dict(row))

问题:如果数据库 schema 和 dataclass 定义不同步(加字段、改类型),这里会静默失败或抛出不可预测的异常。没有版本迁移机制。

3.5 无测试

文件:不存在测试文件

整个项目零测试。对于一个"对外宣传"工具,可能影响不大。但如果解析器和 API 采集出问题(已经出过了),没有回归保护。


四、业务逻辑缺陷

4.1 联系人状态机无约束

文件contacts_tracker.py:163-220(修复后)

status 字段没有状态机——可以从任意状态跳到任意状态(repliedpending 是合法的)。notes 字段只追加不编辑(f"{existing}\n{now}: {notes}"),只能越来越长。
注意:update() 现在校验 status 必须在 VALID_STATUSES 枚举内(L173-175),但状态转换顺序无约束。

4.2 指标采集只写不删

文件metrics.py:114-151

每次 collect_metrics() 都是 INSERT,从不清理旧数据。metrics_history() 默认 LIMIT 30,但数据库会无限增长。对于 6 个仓库、每天采集 1 次,一年约 2,190 行——不严重但不够干净。
注意:已添加 cleanup_old_metrics() 函数(L241-262)可在手动调用时清理,但未自动触发。

4.3 format_report()format_growth() 硬编码中文

文件metrics.py:206-238

输出字符串硬编码中文标题("灵字辈 GitHub 指标"、"合计")。与"去灵字辈化"原则矛盾——如果这些函数被外部调用,输出会暴露灵字辈品牌。

4.4 REPOS 字典与实际项目不对应

文件metrics.py:20-27

REPOS = {
    "LingFlow": "guangda88/LingFlow",
    "LingClaude": "guangda88/LingClaude",
    "LingYi": "guangda88/LingYi",
    "LingMessage": "guangda88/LingMessage",
    "LingMinOpt": "guangda88/LingMinOpt",
    "Ling-term-mcp": "guangda88/Ling-term-mcp",  # ← 注意这个名字
}
  • Ling-term-mcp 与 npm 包名 ling-term-mcp 大小写不一致
  • 缺少 LingYan(灵研)、ZhiBridge(智桥)、LingTongAsk(灵通问道)等项目
  • LingYang 自身也未包含

4.5 发布内容中仍存在审计报告标记的问题

文件releases/hn_launch_post.mdreleases/reddit_launch_post.mdreleases/researcher_email_template.md

这些文件尚未经过本轮审计修复,仍包含 docs/AUDIT_REPORT_20260405.md 中标记的多个问题:

问题 文件 状态
"Show HN" 标题过于 clickbait hn_launch_post.md ❌ 未修
"world's first" 隐含断言 hn_launch_post.md ❌ 未修
GitHub 链接可能 404 reddit_launch_post.md ❌ 未验证
过度拟人化("genuinely"、"re-enacted") hn_launch_post.md ❌ 未修
研究者邮件模板过于营销化 researcher_email_template.md ❌ 未修
指向不存在的 GitHub 路径 researcher_email_template.md L28-29 ❌ 未验证

五、架构风险

5.1 单文件数据库无并发保护

两个 SQLite 数据库(contacts.dbmetrics.db)虽然用了 WAL 模式,但: - 无文件锁检查 - 如果两个进程同时运行 collect_metrics(),可能写入重复数据 - 如果两个进程同时 import_targets_md(),会重复导入(find() 查重不原子)

5.2 配置硬编码

表现: - DB 路径硬编码 Path.home() / ".lingyang" - GitHub API 地址硬编码 - REPOS 列表硬编码 - 无 .env / config.yaml / 环境变量支持

影响:不可配置 = 不可测试 = 不可移植。

5.3 stdlib-only 的双刃剑

决策:项目坚持不用第三方依赖(stdlib-only)。

好处:零安装、简单。
代价: - urllib.requestrequests/httpx 难用 10 倍,且无连接池 - 无日志框架(用 print) - 无 CLI 框架(无入口命令) - 如果项目增长,这个约束会成为瓶颈

5.4 无入口点

项目没有 __main__.py、没有 CLI 命令、没有 if __name__ == "__main__"。所有功能只能通过 python3 -c "from src.xxx import ..." 调用。这不是一个可用的工具,而是一个库——但也没有 setup.py / pyproject.toml,所以也不是一个正经的库。


六、合规与规范

6.1 Git 中不应存在的内容

检查结果contacts/ 目录在 .gitignore 中(正确),contacts/targets.md 未被 git 追踪(正确)。但:

  • ~~src/__pycache__/ 在 git 追踪中~~ ✅ 实际未被追踪(git ls-files 返回空),.gitignore 已有规则
  • .editorconfig、无 linter 配置、无 CI

6.2 许可证 ✅ 已修复

项目 README 提到 MIT 许可证。 - ~~根目录无 LICENSE 文件~~ ✅ 已添加 LICENSE(MIT) - 源文件头部无许可证声明(可选改进) - src/__init__.py 有 docstring 但无版权信息(可选改进)

6.3 发布内容的法律风险

文件releases/researcher_email_template.md

邮件模板将 AI 系统的输出描述为"observations"和"research-relevant aspects",暗示学术研究发现。如果发送给真实研究者: - 未披露这些"观察"来自 AI 生成的内容 - 可能构成学术不端(misrepresentation) - "We operate a network..." 暗示有一个研究团队,实际是个人项目


七、修复优先级

P0 — 立即修复(安全 + 数据完整性)

# 问题 工作量 影响 状态
1 轮换 npm token 5min 防止供应链攻击 ⏳ 需手动:npmjs.com → Access Tokens → Regenerate
2 DB 文件权限改为 600 1min 防止本地信息泄露 ✅ 已修复 — chmod 600 + _get_db() 自动修复
3 修复 import_targets_md() 解析器 30min 防止再次导入垃圾数据 ✅ 已修复 — 过滤表头、短名称、空名称
4 修复 update() 的 TOCTOU 竞态 15min 数据一致性 ✅ 已修复 — 单连接读+写,移除 get() 调用

P1 — 近期修复(代码质量 + 可靠性)

# 问题 工作量 影响 状态
5 移除 __pycache__ from git 2min 仓库清洁 ✅ 不需要 — pycache/ 尚未被 git 追踪
6 添加 .gitignore 规则 __pycache__/ 1min 防止再次提交 ✅ 已存在 — .gitignore 已包含规则
7 为旧发布文件添加"未审核"警告 5min 防止误发 ✅ 已修复 — 3个文件添加 UNREVIEWED HTML 注释
8 fetch_repo() 添加 GitHub Token 支持 15min 可靠性 ✅ 已修复 — 支持 GITHUB_TOKEN 环境变量
9 _get_db() 移除重复的 CREATE TABLE 5min 性能 ✅ 已修复 — 模块级 _db_initialized 标志
10 添加 LICENSE 文件 2min 合规 ✅ 已修复 — MIT License

P2 — 中期改进(架构)

# 问题 工作量 影响 状态
11 提取配置到 .envconfig.json 1h 可维护性 ⏳ 待做
12 添加 CLI 入口点 2h 可用性 ⏳ 待做
13 添加基本测试 3h 回归保护 ⏳ 待做

八、一句话总结

P0/P1 已修复,项目从"不能公开"升级到"可用但需打磨"。 下一步:轮换 npm token(手动),然后决定 P2 架构改进的优先级。


审计人:灵扬 LingYang (Crush GLM-5.1)
审计基线:commit c6cd3c7
修复时间:2026-04-06(同日修复 P0 #2-4, P1 #5-10)