Skip to content

Default .env to 0600 but allow overriding the mode#258

Open
jackson-asmith wants to merge 1 commit into
jamesyc:mainfrom
jackson-asmith:harden/env-file-mode
Open

Default .env to 0600 but allow overriding the mode#258
jackson-asmith wants to merge 1 commit into
jamesyc:mainfrom
jackson-asmith:harden/env-file-mode

Conversation

@jackson-asmith

Copy link
Copy Markdown

What

Writes .env with owner-only (0600) permissions by default, but lets power users override the mode via a TCAPSULE_ENV_FILE_MODE env var (octal, e.g. 640).

Why

This reworks the closed #252. Your feedback there was that unconditionally forcing 0600 breaks legitimate workflows — a Docker container or multi-user host where another user needs access to .env. This keeps 0600 for the vast majority of cases (the file holds TC_PASSWORD) while giving power users a clean way to choose a different mode, instead of forcing it or leaving it to chance.

Changes

  • env_file_target_mode(env) reads TCAPSULE_ENV_FILE_MODE as an octal mode; unset/invalid/out-of-range falls back to 0600.
  • write_env_file applies that mode to the temp file before the atomic rename (so os.replace delivers it, with no post-rename chmod).
  • README note on the default and the override.

Tests

  • env_file_target_mode: default, 640/0640 overrides, invalid and out-of-range fallback.
  • write_env_file yields 0600 by default and 0640 when the override is set.

I dropped the doctor "loose permissions" warning from the original #252 — with the mode now intentionally configurable, a warning would just nag the power users this is meant to serve.

🤖 Generated with Claude Code

Reworks the closed jamesyc#252 per maintainer feedback: instead of unconditionally
forcing 0600 (which breaks Docker/multi-user setups that need group access
to .env), default to 0600 and let power users pick a different mode via the
TCAPSULE_ENV_FILE_MODE env var (octal, e.g. 640). Invalid or out-of-range
values fall back to 0600.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the ability to configure the file permissions of the generated .env file using the TCAPSULE_ENV_FILE_MODE environment variable, defaulting to 0o600. It includes corresponding documentation updates and unit tests. The review feedback correctly identifies that parsing octal values with int(raw, 8) will fail and fallback to the default if standard Python octal prefixes like 0o are used. It is recommended to strip these prefixes before parsing and add a test case to verify this behavior.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +658 to +662
raw = environ.get(ENV_FILE_MODE_ENV, "").strip()
if not raw:
return DEFAULT_ENV_FILE_MODE
try:
mode = int(raw, 8)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The int(raw, 8) call will raise a ValueError if the user specifies the octal mode with a standard Python octal prefix like 0o or 0O (e.g., 0o640). This causes it to silently fall back to the default 0o600 mode, which defeats the user's override. Stripping the 0o or 0O prefix if present makes the override more robust and user-friendly.

Suggested change
raw = environ.get(ENV_FILE_MODE_ENV, "").strip()
if not raw:
return DEFAULT_ENV_FILE_MODE
try:
mode = int(raw, 8)
raw = environ.get(ENV_FILE_MODE_ENV, "").strip()
if not raw:
return DEFAULT_ENV_FILE_MODE
if raw.lower().startswith("0o"):
raw = raw[2:]
try:
mode = int(raw, 8)

Comment thread tests/test_config.py
Comment on lines +214 to +215
self.assertEqual(env_file_target_mode({"TCAPSULE_ENV_FILE_MODE": "640"}), 0o640)
self.assertEqual(env_file_target_mode({"TCAPSULE_ENV_FILE_MODE": "0640"}), 0o640)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Add a test case to verify that env_file_target_mode correctly handles the standard Python octal prefix 0o (e.g., 0o640).

Suggested change
self.assertEqual(env_file_target_mode({"TCAPSULE_ENV_FILE_MODE": "640"}), 0o640)
self.assertEqual(env_file_target_mode({"TCAPSULE_ENV_FILE_MODE": "0640"}), 0o640)
self.assertEqual(env_file_target_mode({"TCAPSULE_ENV_FILE_MODE": "640"}), 0o640)
self.assertEqual(env_file_target_mode({"TCAPSULE_ENV_FILE_MODE": "0640"}), 0o640)
self.assertEqual(env_file_target_mode({"TCAPSULE_ENV_FILE_MODE": "0o640"}), 0o640)

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.

1 participant