Skip to content

fix(envs): 修复配置中带 # 井号的内容(如剧名)被误截断失效 - #443

Merged
huangxd- merged 2 commits into
huangxd-:mainfrom
wan0ge:fix/env-hash-raw-read
Aug 15, 2026
Merged

fix(envs): 修复配置中带 # 井号的内容(如剧名)被误截断失效#443
huangxd- merged 2 commits into
huangxd-:mainfrom
wan0ge:fix/env-hash-raw-read

Conversation

@wan0ge

@wan0ge wan0ge commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

不一定是最佳方案

Summary

为文本类自定义环境变量引入原始读取能力,绕过 dotenv 将值中 # 视为注释的截断行为,并加固加密变量守卫,覆盖四个维度:

  1. 文本类自定义变量原始读取:新增 RAW_ENV_KEYS 白名单(14 个纯文本类变量:各类 filter / mapping / blocklist / url 等)、parseRawEnvText(保留行内 #、剥外层双引号)、getRawEnv(系统环境变量 > .env 原始值 > 默认值),使值中的 # 等 dotenv 视为注释的字符不再被截断。
  2. 加密变量守卫Envs.gettype === 'string' && !encrypt && RAW_ENV_KEYS.has(key) 时路由到 getRawEnv;加密变量(encrypt = true)绝不走此路径,防止绕过加密返回明文。
  3. Node 运行时注入:server.js 注入 Envs.systemEnvBackup(启动前系统环境变量快照)与 Envs.rawEnvValues.env 原始解析结果);非 Node(测试/Workers)无二者时 getRawEnv 退化为普通取值,保证测试隔离与平台兼容。
  4. 清理冗余记录:移除 resolveCustomMergeRules 内冗余的 accessedEnvVars.setCUSTOM_MERGE_RULESget()getRawEnv.finalize 已记录)。

改动明细

1. 文本类变量原始读取绕过 dotenv 截断

上游原版行为Envs.get 解析自定义变量时依赖 dotenv 已加载的 this.env,dotenv 将值中首个 # 视为注释起始,导致含 # 的文本(如 COLOR_POOL='#FF0000,#00FF00'、带 # 的 URL、含 # 的合并映射规则)被截断丢失。

改动后行为:新增 RAW_ENV_KEYS 白名单与 getRawEnvget() 在字符串且未加密且键在白名单时改走 getRawEnvgetRawEnv 优先系统环境变量(最高优先级,与既有 systemEnvBackup 体系一致),否则读 .env 原始解析值(parseRawEnvText 保留行内 #、仅剥外层双引号),未配置回退 process.env 或默认值。

实际观察

注释态测试验证 parseRawEnvText 保留行内 # 与剥引号;CUSTOM_MERGE_RULES/COLOR_POOL/DANMU_PUSH_URL#get 完整保留。

2. 加密变量守卫

上游原版行为:无针对 RAW 路径的加密隔离;若误将带令牌/密码的变量纳入 RAW 白名单,会绕过加密以明文返回。

改动后行为get() 守卫要求 !encryptRAW_ENV_KEYS 14 项经人工甄别均为非凭据类文本(端点 URL 不含密钥),注释明确禁止纳入带令牌/密码变量。

实际观察

注释态测试验证 encrypt = trueDANMU_PUSH_URL 走加密路径返回默认值而非原始含 # 值,守卫生效。

3. Node 运行时注入与平台兼容

上游原版行为Envs 无系统环境变量快照与 .env 原始解析入口,无法在 getRawEnv 层面绕过 dotenv。

改动后行为:server.js 在既有的 systemEnvBackup 旁注入 Envs.systemEnvBackup,并在 loadEnv()try/catch 解析 .env 原始内容写入 Envs.rawEnvValues(解析失败不影响启动)。getRawEnv 在非 Node(无 systemEnvBackup)时退化为 this.env > process.env > default

实际观察

Node 启动时注入生效;测试/Workers 无注入时退化为普通取值,不影响既有测试与平台运行。

4. 移除冗余 accessedEnvVars.set

上游原版行为resolveCustomMergeRules 末尾 this.accessedEnvVars.set('CUSTOM_MERGE_RULES', raw),但 CUSTOM_MERGE_RULES 已在 RAW_ENV_KEYS 内,经 get()getRawEnv.finalize 同时写入 originalEnvVarsaccessedEnvVars,该显式 set 冗余。

改动后行为:移除该冗余 set,统一由 finalize 记录。

实际观察

getRawEnv 测试覆盖 CUSTOM_MERGE_RULESget 既返回原始值又完成记录,无功能回退。


实际案例

CUSTOM_MERGE_RULES 含 # 井号键被 dotenv 截断失效

某用户使用 CUSTOM_MERGE_RULES 配置跨源合并规则,其中剧名携带 # 井号(舞台剧/演唱会副标题常见):

CUSTOM_MERGE_RULES=少女☆歌剧Revue Starlight -The LIVE- #1 revival(2019)【动漫】@bilibili × 少女☆歌剧 Revue Starlight(2018)【TV动画】@dandan

上游原版经 dotenv 加载后,值中首个 # 被视为注释起始,变量实际被截断为 少女☆歌剧Revue Starlight -The LIVE- #1 revival(2019)... 及后续整条规则丢失),导致该合并规则残缺或完全失效,用户无法将带 # 副标题的条目正确合并。本分支将 CUSTOM_MERGE_RULES 纳入 RAW_ENV_KEYS,经 getRawEnvparseRawEnvText 保留行内 #、仅剥外层双引号)读取,上述完整规则被原样保留,× 分隔的两条合并关系正常生效。


影响范围

场景 行为变化
# 的文本类自定义变量(COLOR_POOL / 带 # URL / 合并映射规则等) 完整保留,不再被 dotenv 截断
加密变量(encrypt = true 不走 RAW 路径,明文不外泄
RAW 白名单变量 仍走原 dotenv 解析,无变化
测试 / Workers(无 systemEnvBackup getRawEnv 退化为普通取值,平台兼容
.env 原始解析失败 不影响启动,相关变量回退普通取值

涉及文件

文件 改动
danmu_api/configs/envs.js 新增 RAW_ENV_KEYS / systemEnvBackup / rawEnvValues / parseRawEnvText / getRawEnvget 路由守卫;移除冗余 accessedEnvVars.set
danmu_api/server.js 注入 Envs.systemEnvBackuploadEnv 内解析 .env 原始内容写入 Envs.rawEnvValues
danmu_api/worker.test.js 注释态新增 envs RAW_ENV_KEYS 保留 # / 加密守卫 测试

问题:dotenv.config() 将未加引号的行内 # 视为注释起始,导致自定义文本类变量中合法包含的 # 被截断、规则失效;即便用户通过前端写入双引号可规避,直接编辑 .env 不加引号时仍会触发。

方案:在 Envs.get 中对未加密的文本类自定义变量(RAW_ENV_KEYS)统一路由到 getRawEnv,直接解析 .env 原始文本(仅跳过整行 # 注释、剥离外层双引号),从而保留 # 等字符。优先级保持系统环境变量 > .env 原始值 > 默认值,与既有 systemEnvBackup 机制一致;非 Node 运行时(测试 / Workers)无原始 .env 时退化为普通取值语义,不影响测试隔离与平台兼容。前端设置页读取的 originalEnvVars 同样由 get/getRawEnv 写入,显示侧一并修复。同步移除 resolveCustomMergeRules 中已冗余的 accessedEnvVars.set 调用。

覆盖范围:RAW_ENV_KEYS 含合并映射表、标题/自动匹配映射表、弹幕偏移、屏蔽词、各标题/剧集噪音过滤器、IP 黑名单、AI 匹配提示,以及非加密的 COLOR_POOL / DANMU_PUSH_URL / OTHER_SERVER / VOD_SERVERS(URL / 颜色类)。

加密守卫:get() 路由条件加 !encrypt,防止加密变量(PROXY_URL / CUSTOM_SOURCE_API_URL / UPSTASH_REDIS_REST_URL / LOCAL_REDIS_URL 等带令牌 URL)被绕过加密返回明文;此类加密变量刻意不入 RAW_ENV_KEYS(其 # 风险极低且经安全写入路径)。

测试:worker.test.js 增加对应注释测试桩(按项目约定注释待启用);独立的 raw-env-read.test.mjs 仅本地验证、不入库。
@vercel

vercel Bot commented Aug 13, 2026

Copy link
Copy Markdown

@wan0ge is attempting to deploy a commit to the huangxd's projects Team on Vercel.

A member of the Team first needs to authorize it.

@huangxd-
huangxd- merged commit 7e5c807 into huangxd-:main Aug 15, 2026
0 of 2 checks passed
xingye84 added a commit to xingye84/danmu_api that referenced this pull request Aug 15, 2026
* commit '1bdb2a879e698ee6b0f90a9b5b7513ef5aba2862':
  fix: 修复 widget 构建中 http/https 模块兼容性及环境检测逻辑
  docs: remove recommended label for Netlify deployment
  fix(bangumi-data): 修复 Bangumi Data 开启可能不触发立即下载,并调整云部署数据丢失时下载时机 (huangxd-#444)
  fix: 自定义文本类环境变量读取绕过 dotenv 注释截断以保留 # (huangxd-#443)
  feat: 清理缓存支持按项勾选清理 (huangxd-#441)
  fix(ui): UI 细节与响应式优化 (huangxd-#440)
  feat: 弹弹play源支持经 NipaPlay 302关联链接获取弹幕,并支持 NIPAPLAY_REPLACE_DANDAN 替代原生弹幕开关 (huangxd-#439)
  fix: 修复多 p 视频按总时长计算分段数导致越界请求 304 空响应 (huangxd-#438)
  fix(mango): 综艺纯第N期条目取消后缀过滤,直接作为正片收录 (huangxd-#437)
  fix(match): 修复偏好偏移计算目标集数为0时数组越界引发TypeError及400异常 (huangxd-#436)
  feat: 支持 IPv4/IPv6 双栈监听并优化服务器启动与清理逻辑 (huangxd-#445)

# Conflicts:
#	danmu_api/worker.test.js
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants