Summary
In qwen serve (ACP host) sessions, the built-in text-write tools (write_file, edit, notebook_edit) create new files with mode 0600 unconditionally. The daemon process umask is ignored, and no settings key, flag, or environment variable exists to change the new-file mode. Agent-created files silently diverge from the rest of the system's file conventions (e.g. group-readable 0664), and users have no way to opt out except after-the-fact workarounds.
Environment
- Qwen Code
0.21.12 (@qwen-code/qwen-code), Node v22.22.2, Linux
qwen serve daemon launched via systemd; the unit's drop-in explicitly sets UMask=0002
- ACP session hosted by the serve daemon; the agent's shell umask is also
0002
Reproduction
- Start a
qwen serve-hosted session (any workspace).
- Have the agent create a new file with the
write_file tool.
stat -c '%a' <file> → 600.
touch <file> in the same directory via the shell → 664.
- No configuration option exists: the full settings reference has no file-mode/umask key in
general.*, advanced.*, or anywhere else, and the qwen-serve flags/env reference does not expose one.
Root cause (identified in installed 0.21.12)
The serve host writer's writeTextFile (package chunk chunks/chunk-6P5EXEBL.js, method at line 3581) writes via temp file + rename with:
await fs.writeFile(tmp, params.content, {
encoding: "utf8",
flag: "wx",
mode: preserveMode?.mode ?? 384, // line 3618 — 384 = 0o600, hard-coded
});
- Existing files: mode/uid/gid are preserved (the documented "mode preservation" behavior — fine).
- New files: the fallback is the hard-coded
384 (0o600). The process umask is never consulted (Node's fs.writeFile default of 0o666 & ~umask would have yielded 0664 here). No config, env var, or flag is read.
Documentation gap
docs/qwen-serve.md ("Default deployment threat model") lists "0600 new-file mode" as a property of the host writer, presented as a fixed invariant rather than a configurable one.
- The design doc referenced there (
../design/daemon-external-tool-text-writes.md) is not shipped with the npm package — the link is dangling.
- Neither the settings reference nor the qwen-serve flag/env-var reference provides any way to configure it.
Expected behavior
A setting must exist that allows file writes to follow system processes and controls. The hard-coded 0600 default for new files is a security stance the vendor imposes on user files; users must be able to disable that default so new files follow the standard system permission handling (process umask) like any other process on the machine. The default may remain 0600, but it must be overridable. Mode preservation for existing files should remain unchanged.
Suggested fix
Add a setting that allows the user to disable the default, so the vendor's security stance can be overridden:
{ "general": { "newFileMode": "system" } }
"0600" (default, current behavior): new files are created owner-only.
"system": new files are created with the standard 0o666 & ~umask handling, i.e. they follow system processes and controls instead of the hard-coded mode.
An equivalent qwen serve --new-file-mode flag or env var would also satisfy this. Whatever form is chosen, it must be documented in the settings reference.
Impact
- Team/group workflows: agent-created files are owner-only even when the repository or team convention is group-readable; every user must work around it (post-write hooks, manual chmod, or patching the installed package locally — which is wiped on every upgrade).
- A vendor hard-coded permission policy applied to user files with no escape hatch overrides user/system file conventions by default. A fail-closed default is defensible; what is missing is the user's ability to turn it off.
Summary
In
qwen serve(ACP host) sessions, the built-in text-write tools (write_file,edit,notebook_edit) create new files with mode0600unconditionally. The daemon process umask is ignored, and no settings key, flag, or environment variable exists to change the new-file mode. Agent-created files silently diverge from the rest of the system's file conventions (e.g. group-readable0664), and users have no way to opt out except after-the-fact workarounds.Environment
0.21.12(@qwen-code/qwen-code), Nodev22.22.2, Linuxqwen servedaemon launched via systemd; the unit's drop-in explicitly setsUMask=00020002Reproduction
qwen serve-hosted session (any workspace).write_filetool.stat -c '%a' <file>→600.touch <file>in the same directory via the shell →664.general.*,advanced.*, or anywhere else, and the qwen-serve flags/env reference does not expose one.Root cause (identified in installed 0.21.12)
The serve host writer's
writeTextFile(package chunkchunks/chunk-6P5EXEBL.js, method at line 3581) writes via temp file + rename with:384(0o600). The process umask is never consulted (Node'sfs.writeFiledefault of0o666 & ~umaskwould have yielded0664here). No config, env var, or flag is read.Documentation gap
docs/qwen-serve.md("Default deployment threat model") lists "0600 new-file mode" as a property of the host writer, presented as a fixed invariant rather than a configurable one.../design/daemon-external-tool-text-writes.md) is not shipped with the npm package — the link is dangling.Expected behavior
A setting must exist that allows file writes to follow system processes and controls. The hard-coded
0600default for new files is a security stance the vendor imposes on user files; users must be able to disable that default so new files follow the standard system permission handling (process umask) like any other process on the machine. The default may remain0600, but it must be overridable. Mode preservation for existing files should remain unchanged.Suggested fix
Add a setting that allows the user to disable the default, so the vendor's security stance can be overridden:
{ "general": { "newFileMode": "system" } }"0600"(default, current behavior): new files are created owner-only."system": new files are created with the standard0o666 & ~umaskhandling, i.e. they follow system processes and controls instead of the hard-coded mode.An equivalent
qwen serve --new-file-modeflag or env var would also satisfy this. Whatever form is chosen, it must be documented in the settings reference.Impact