JOTO
联系我们
← AI 智库
Dify

升级 Dify v1.16.1 后,我先把 Agent 的默认密码换了

2026 年 8 月 11 日

Dify v1.16.1 引入多项安全增强:沙箱网络隔离、Squid 代理 ACL 白名单控制出站、内部服务间 Bearer Token 认证、Jinja2 模板沙箱化。但两个关键环境变量 DIFY_AGENT_API_TOKEN 和 AGENT_BACKEND_API_TOKEN 默认值仍为明文公开的 'dify-agent-run-token-for-dev-only',生产环境若未手动修改将导致 agent_backend 接口被绕过权限直接调用。

上周我在本地把 Dify 从 v1.15.x 升到 v1.16.1。之前一直拖着没升,怕迁移出问题。看了下 release note,7 月 28 号发的,四个 additive 迁移,不停机,心里踏实了点。docker compose pull && docker compose up -d,跑完,日志干净,迁移顺利。

顺手点了个 Agent 工作流跑测试。LLM 正常回了,工具调了,沙箱代码也执行了,一切正常。

然后我习惯性扫了一眼 .env。

DIFY_AGENT_API_TOKEN=dify-agent-run-token-for-dev-only

升级 Dify v1.16.1 后,我先把 Agent 的默认密码换了

默认值。没改。

愣了两秒。这串字符明晃晃写在 Dify 的 GitHub 仓库、docker-compose 模板和官方文档里。全世界搜得到。要是生产环境——任何能摸到容器网络的人,同机器上别的容器也好、被攻破的边缘服务也好、内网里横向移动的攻击者也好——拿到这串字符就能直接调 agent_backend,绕过 API 层所有业务逻辑和权限控制。

你的 Agent 后门钥匙,挂在门把手上。

我为什么会去翻 .env?v1.16.1 的 release note 专门提到了两个新环境变量,我想看下默认值长什么样。一翻,好家伙,跟 GitHub 仓库里的一模一样。Dify 不是藏着掖着,它明明白白告诉你这是开发用的默认值。但多少人升级后会去翻 .env?大部分人 docker compose up -d 跑完看到服务起来了就走了。

这个值为什么危险

v1.16.1 改了什么?核心就俩字:安全。

升级 Dify v1.16.1 后,我先把 Agent 的默认密码换了 配图 2

沙箱网络之前跟 API、worker、数据库挤同一个默认网络。沙箱里跑的代码——用户上传的工具脚本、LLM 动态生成的工作流代码——理论上能发 HTTP 请求访问这些内部服务。经典 SSRF:沙箱本该只能出去访问外部 API,结果内网全暴露了。

举个具体场景。同一台机器上跑了 Dify 和一个不太安全的 Web 服务。那个服务被打穿了,攻击者拿到容器网络访问权。v1.16.0 及以前,他可以从那个容器直接访问 Dify 的 API、worker 甚至数据库——没有任何隔离。v1.16.1 之后,他最多碰到沙箱网络里的东西,核心业务碰不到。就算网络层面漏了,没有 Bearer Token 也调不动。

现在 local_sandbox 被挪到两个专用网络,agent_sandbox_networklocal_sandbox_proxy_network,跟主业务网络隔开了。沙箱想出去,得过 agent_ssrf_proxy——一个 Squid 正向代理。代理用 ACL 卡死白名单:只允许访问 API 的 /files/ 端点和 agent_backend 的 /agent-stub/ 路径,其他一律 deny。

内部服务通信也改了。API、worker、agent_backend 互调全走 Bearer Token 认证。两个环境变量:DIFY_AGENT_API_TOKENAGENT_BACKEND_API_TOKEN。不带 token 调内部接口,直接 401。Jinja2 模板渲染也换成了 SandboxedEnvironment,堵工作流代码节点的模板注入——之前恶意 Jinja2 语法能调 Python 内建函数读文件、执行命令,现在属性和方法访问被严格限制了。

改动方向都对。该堵的洞堵了。

但两个 token 的默认值都是 dify-agent-run-token-for-dev-only。开发环境图方便,行。生产环境忘了改呢?Dify 不会拦你——不检测、不警告、不阻止你带着默认值跑起来。它就这么静悄悄起来了,带着一把全世界都知道的钥匙。

升级 Dify v1.16.1 后,我先把 Agent 的默认密码换了 配图 3

动手改

先把 token 换了。Python 标准库生成,不需要装额外依赖:

python -c 'import secrets; print(secrets.token_urlsafe(32))'

跑两遍,拿到两个不同字符串。每个大概 43 个字符长,URL-safe,没有特殊字符,直接塞进 .env 不会有转义问题。别手写几个随机字符凑数——人写的"随机"一点都不随机。secrets.token_urlsafe 用的是系统级 CSPRNG,密码学安全的。

分别给 DIFY_AGENT_API_TOKENAGENT_BACKEND_API_TOKEN 设上。文档说两边值要一致——指的是同一个 token 在 api、worker、agent_backend 三个服务里保持一致,不是说两个不同 token 要设成同一个值。我选了两个不同的随机串,万一一个泄露不至于全军覆没。

还有一个容易漏的:这两个变量得同时传给 api、worker、agent_backend 三个服务。Dify 默认 compose 文件已经配好了,但如果自定义过服务定义,翻一下这三个服务的 environment 段,确认两个变量都在。漏了一个的话服务间认证对不上,Agent 跑起来直接报 401,排查起来挺烦的。

然后是 docker-compose。这步容易忽略。网络拓扑变了,光改 .env 不够。拉最新 compose 文件,有几件事得确认。

local_sandbox 不在默认网络了。如果之前自定义过 compose——改过端口映射、挂过额外卷、加过自定义服务——别直接拿新文件覆盖,手动把网络配置合并进去。

agent_ssrf_proxy 是新增服务。Squid 的配置文件在 ssrf_proxy/squid.conf,建议看一眼 ACL 规则。默认白名单是 API 的 /files/ 和 agent_backend 的 /agent-stub/。如果在 agent_backend 上挂了自定义 stub 路径,或者有别的需要沙箱访问的内部端点,得手动加到 ACL 里。Squid 的 ACL 语法不复杂,但改完得重启 agent_ssrf_proxy 容器才生效。

确认完,拉镜像重启:

docker compose pull
docker compose up -d

验证

重启完别急着走。验一下,确认改的东西真生效了。

先验 Squid ACL。从沙箱容器内,通过代理 curl 一个不在白名单上的地址:

docker exec -it <sandbox_container> \
  curl -x http://agent_ssrf_proxy:3128 http://api:5001/health

返回 403 或连接被重置,ACL 拦住了,对了。再试白名单内的 /files/ 路径,应该能通。

再验 Bearer Token。直接 curl agent_backend,故意不带 token:

curl http://localhost:5002/agent-stub/

返回 401,认证生效。带上正确 token 再试,应该 200。

还可以验网络隔离。docker network inspect agent_sandbox_network 看看沙箱容器是不是真跟 API、worker 不在同一个网络里。docker exec 进沙箱容器 ping 一下 API 容器,ping 不通就对了。

有个坑。我那天验的时候,第一次 curl 沙箱代理返回的不是 403 而是 connection refused。排查了十分钟,发现是因为之前自定义过 compose 的服务名,沙箱的 HTTP_PROXY 环境变量还指向旧的服务名。改成 agent_ssrf_proxy 之后就好了。如果也自定义过 compose,这个坑大概率会遇到。先检查沙箱容器的 HTTP_PROXY 有没有正确指向代理服务,再往下验。

那天验完快一点了。关电脑前又扫了眼 .env,确认两个 token 都不是默认值。踏实。

升级前后

v1.16.0 及以前v1.16.1
沙箱网络与所有服务同网络隔离到 agent_sandbox_network + local_sandbox_proxy_network
出站控制无限制Squid 代理 + ACL 白名单(/files//agent-stub/
内部认证Bearer Token
模板渲染标准 Jinja2SandboxedEnvironment

几句实在话

Dify 这次干得漂亮。安全从"顺带修 bug"变成了基础设施级别的变更——网络隔离、代理 ACL、Bearer 认证、模板沙箱化,该有的都有了。SandboxedEnvironment 那个改动尤其值得说一句,工作流代码节点的模板注入之前确实是个洞,堵得好。

但默认 token 这个事,说句不好听的。

dify-agent-run-token-for-dev-only,明文写在文档和 compose 模板里,GitHub 上一搜就有。给个默认值图开发方便,理解。但生产部署的时候 Dify 不强制你改——不检测、不警告、不阻止你带着默认值跑。有些项目怎么做的?首次启动自动生成随机 token 写回配置文件,或者检测到默认值直接拒绝启动、强制你改。Dify 没做这层。安全工具递到手上了,用不用靠自觉。

不是要求 Dify 做保姆。但一个带 Agent 沙箱的生产级平台,默认 token 公开这件事,至少在启动日志里打个 WARNING 行不行?成本几乎为零,效果立竿见影。安全圈有句话叫"default deny"——默认拒绝。Dify 的做法反过来了,默认放行,默认给一把公开的钥匙,改不改你自己看着办。开箱即用和安全默认之间,总得有人做选择。Dify 选了前者,后者的责任就落到了部署者头上。

这个锅用户自己背。

别把 Agent 当可信程序。沙箱里跑的代码——我自己写的工具也好、LLM 动态生成的工作流也好——本质都不可信。LLM 生成代码的时候可不会替你考虑安全。隔离网络、限制出站、加认证,三样缺一不可。Dify v1.16.1 把工具给了,改不改是我的事。

说到底这不是 Dify 一家的问题。任何提供代码沙箱能力的平台——Dify、Coze 还是别的什么——都面对同一个问题:沙箱里跑的代码不可信。隔离、限流、认证,三板斧少一斧都不行。Dify 这次把安全从"修 bug"提到了"基础设施变更"的级别,态度要肯定。但"给你工具不管你用不用"这个姿势,我觉得可以做得更好。

对了,这版还顺手把首页"继续工作"接口延迟降了约 69%。跟安全无关,但点开首页确实快了不少,体感明显。

下一步打算把 Squid 的 ACL 日志接到 Loki 里,沙箱有异常出站请求能第一时间看到。下周末的事了。

参考资料

  • • Dify v1.16.1 Release Notes: https://github.com/langgenius/dify/releases/tag/v1.16.1
  • • Dify Docker Compose 配置: https://github.com/langgenius/dify/blob/main/docker/docker-compose.yaml
  • • Python secrets 文档: https://docs.python.org/3/library/secrets.html
  • • Squid ACL 配置: http://www.squid-cache.org/Doc/config/acl/
  • • Jinja2 SandboxedEnvironment: https://jinja.palletsprojects.com/en/3.1.x/api/#jinja2.SandboxedEnvironment

JOTO 企业落地观察

  • 企业部署 Agent 类系统时,v1.16.1 的网络隔离与 Bearer Token 认证机制显著提升了纵深防御能力,但默认凭证未强制校验的设计,将安全责任完全前置至部署环节。这意味着企业必须在 CI/CD 流程中嵌入配置审计步骤,否则极易因疏忽引入高危暴露面。
  • 这类系统的取舍在于:开箱即用的便利性与安全默认的严谨性难以兼得。Dify 将沙箱网络、代理 ACL、Token 认证等能力全部开放,但未设置启动时的默认值校验或告警,要求团队具备明确的安全配置 SOP,否则自动化部署可能固化风险。
  • 对 AI 安全治理而言,v1.16.1 的改进表明:仅靠运行时防护(如沙箱)不够,必须叠加通信层认证与网络层隔离。企业需将环境变量管理纳入密钥治理体系,禁止明文配置,并通过配置扫描工具主动识别类似 'dify-agent-run-token-for-dev-only' 的硬编码凭证。
  • RAG 知识工程虽未直接涉及,但 Agent 沙箱的安全加固间接保障了知识调用链路的完整性。若沙箱被突破并反向探测 RAG 后端服务,可能导致提示词泄露或向量库越权访问。因此,企业需确保 RAG 组件与 Agent 沙箱处于同等隔离等级的网络域中。

立即咨询 JOTO

JOTO 提供覆盖企业智能体规划与搭建、AI 平台私有化部署、RAG 知识工程、AI 安全治理、FDE 驻场共创及持续运营优化的全周期 AI 落地服务,帮助企业把验证中的 AI 能力转化为安全、可控、可持续迭代的生产力。 联系 JOTO 获取 AI 落地咨询

想把这些做法用到你的业务里?

留下你的场景和痛点,我们帮你判断从哪一步开始。

联系我们
联系我们

开启企业级 AI 落地

留下你的行业、部门和当前痛点,我们会在 1 个工作日内与你联系,帮你判断适合先做什么、需要准备哪些数据、适合什么平台。

微信咨询
扫码添加,一对一沟通
JOTO 微信咨询二维码
发送邮件
jotoai@jototech.cn

填写需求单

收到你的信息后,我们将在 1 个工作日内与你取得联系。