Skip to content

fix(config): keep config init captures private when overwriting - #127

Merged
entelecheia merged 1 commit into
mainfrom
fix/119-config-init-destination
Nov 10, 2026
Merged

entelecheia merged 1 commit into
mainfrom
fix/119-config-init-destination

Conversation

@entelecheia

Copy link
Copy Markdown
Member

Closes #119

rootfiles config init --file FILE --overwrite used os.WriteFile, which applies the 0600 mode only when it creates the file. An existing 0644 destination stayed 0644, even when a --from-system capture held the tunnel token.

Policy, now enforced and documented in docs/specs/config.md and docs/commands.md:

  • The written file always ends 0600 and owned by the caller, whether new or overwritten.
  • Data goes to a temp file in the destination directory, which is synced and then renamed over the destination. A failed write leaves the previous file unchanged and removes the temp file.
  • A symlink or special-file destination is refused, so the command never writes through a link. So is a destination owned by another non-root user. Each refusal names the cause and the next step.
  • Content is never printed when --file is given; only the path is reported.

Tests (host-free, temp directories only) cover:

  • an existing 0644 destination becomes 0600 after --overwrite, and no content is printed;
  • a new capture holding a synthetic token is 0600 with no temp file left behind;
  • a symlink destination is refused and its target is unchanged;
  • a write into a read-only directory fails and keeps the previous file.

config init is an operator-side command that apply, check and fleet rollouts never run, so servers see no change on upgrade.

🤖 Generated with Claude Code

config init --file wrote with os.WriteFile, which sets the mode only on
create, so an overwritten 0644 file stayed world-readable even when a
--from-system capture held the tunnel token. Write a 0600 temp file in the
destination directory, sync it and rename it over the destination. A failed
write keeps the previous file, and a symlink, special file or file owned by
another non-root user is refused.
Copilot AI balanced review requested due to automatic review settings November 10, 2026 00:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-10T00:20:36.033900Z d4cade0 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@entelecheia
entelecheia merged commit 306a770 into main Nov 10, 2026
57 checks passed
@entelecheia
entelecheia deleted the fix/119-config-init-destination branch November 10, 2026 00:27
entelecheia added a commit that referenced this pull request Nov 10, 2026
Review follow-up to #127: the stat, write and rename failures in
writePrivateConfig named the cause but not what to do next.
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.

security: harden existing destinations for config init captures

2 participants