fix(loader-client): /env exposes server-only NANOFORGE_SERVER_* variables to the browser
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 2/5
- 预计耗时
- 1-3 小时
- 新手友好度
- 77/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- bun, typescript
调研方向
从 apps/client/src/env.ts 及其 getGameEnv 函数开始,然后检查对应的 apps/server/src/env.ts 和现有单元测试。添加测试,验证客户端环境输出不包含 NANOFORGE_SERVER_* 值,且服务器输出不包含 NANOFORGE_CLIENT_* 值。完成标准是两个加载器都不公开另一侧带前缀的变量。
由索引模型根据 Issue 内容生成。
描述
Which app is this bug report for?
client
Issue description
Security. /env can return server-only environment variables to any browser that loads the game.
The CLI splits .env into client and server values (NANOFORGE_CLIENT_* / NANOFORGE_SERVER_*), but its runner starts the client loader with { ...process.env, ...clientEnv } (cli runner.ts#L79). So a NANOFORGE_SERVER_* variable exported in the shell or set by CI reaches the client process.
The client loader's getGameEnv keeps every NANOFORGE_* key and /env returns them all, prefix stripped. The server binds to all interfaces, so the value can be read from the local network, not only from localhost.
Reproduced on the local build with a dummy value:
$ NANOFORGE_SERVER_DB_PASSWORD=dummy bun apps/client/dist/server.js -p 39171 -d <empty dir>
$ curl localhost:39171/env
{"SERVER_DB_PASSWORD":"dummy","tlsEnabled":false}
The same happens the other way: the server loader (env.ts) receives NANOFORGE_CLIENT_*.
Expected: /env never returns NANOFORGE_SERVER_* values.
Suggested fix: in apps/client/src/env.ts, drop keys starting with NANOFORGE_SERVER_ (and in apps/server/src/env.ts, drop NANOFORGE_CLIENT_), with a unit test. A follow-up in the CLI can stop the runner from forwarding those prefixes from process.env.
Related to #87 (optional auth on the loader routes): auth would not fix this, since server-only values should never be sent to the client at all.
Found during a read-only audit of main @ 044c766 (2026-11-11).
Code sample
const PREFIX = "NANOFORGE_";
export const getGameEnv = () => {
return Object.fromEntries(
Object.entries(process.env)
.filter(([key]) => key.startsWith(PREFIX)) // NANOFORGE_SERVER_* passes too
.map(([key, value]) => [key.replace(PREFIX, ""), value]),
);
};
Versions
- @nanoforge-dev/loader-client / @nanoforge-dev/loader-server / @nanoforge-dev/loader-website 1.7.0 (
main@ 044c766) - Bun 1.3.14
- Linux x86_64
Issue priority
High (immediate attention needed)
I have tested this issue on a development release
044c766
- 主要语言
- TypeScript
- 星标
- 1
- 派生
- 0
- 平均合并
- 17 小时 25 分钟
- 30 天内合并 PR
- 11
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
NanoForge-dev/Loader 的其他 Issue
-
app:client app:website enhancement refactor
难度 2/5 1-3 小时 新手友好度 72/100
NanoForge-dev/Loader#145 ·
维护者通常 1 天内回复
-
chore(loader-client,loader-server): package.json entry points name files the build does not produce未关闭app:client app:server bug chore good first issue
难度 2/5 1-3 小时 新手友好度 78/100
NanoForge-dev/Loader#144 ·
维护者通常 1 天内回复
-
app:website bug good first issue
难度 2/5 1-3 小时 新手友好度 85/100
NanoForge-dev/Loader#141 ·
维护者通常 1 天内回复
-
app:website bug good first issue
难度 2/5 1-3 小时 新手友好度 82/100
NanoForge-dev/Loader#140 ·
维护者通常 1 天内回复
-
app:server bug
难度 2/5 1-3 小时 新手友好度 85/100
NanoForge-dev/Loader#138 ·
维护者通常 1 天内回复
查看 NanoForge-dev/Loader 的全部 Issue
相似的 Issue
-
Mend: dependency security vulnerability
难度 1/5 1-3 小时 新手友好度 65/100
fdm-monster/fdm-monster#5563 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
be-BOP-io-SA/be-BOP#2849 ·
-
难度 2/5 1-3 小时 新手友好度 79/100
维护者通常 1 天内回复
-
1️⃣ phase/under-investigation flaky/confirmed flaky/needs-decision type/bug
难度 2/5 1-3 小时 新手友好度 65/100
growilabs/growi#12246 · 3 条评论 ·
维护者通常 1 天内回复
-
🐛 The Rulekeeper - An index run that gives up on the lock ends Succeeded可能已有人在做 @github-actions 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 72/100
SSWConsulting/SSW.Rules#2809 · 1 条评论 ·
维护者通常 1 天内回复