Skip to content

fix: enforce owner-only permissions on credential files#6242

Merged
theCyberTech merged 7 commits into
mainfrom
fix/credential-file-permissions
Jun 25, 2026
Merged

fix: enforce owner-only permissions on credential files#6242
theCyberTech merged 7 commits into
mainfrom
fix/credential-file-permissions

Conversation

@theCyberTech

@theCyberTech theCyberTech commented Jun 19, 2026

Copy link
Copy Markdown
Member

Summary

Two credential-at-rest files were left world-readable on multi-user hosts. Both stem from mkdir/open using default (umask-dependent) permissions instead of restricting to the owner. The token_manager.py module already writes its secrets atomically at 0o600; this brings the rest of the credential surface in line.

Findings

  1. TokenManager._get_secure_storage_path() — docstring promises a 0o700 credential directory, but mkdir(parents=True, exist_ok=True) created it at the default 0o755. The dir holds the Fernet secret.key and encrypted tokens.enc, so other local users could traverse/list it.
  2. Settings.dump() — persists tool_repository_password (plaintext) to ~/.config/crewai/settings.json via open("w"), producing a world-readable 0o644 file; the config dir was also 0o755.

Fixes

  • TokenManager: chmod(0o700) the credential dir after mkdir (robust against umask and pre-existing dirs).
  • Settings: write settings.json atomically (mkstempjson.dumpchmod 0o600os.replace) and chmod(0o700) the dedicated config dir. The /tmp and cwd fallback parents are deliberately not chmod'd — the 0o600 file mode protects the credential there without tightening a shared directory.

Threat model

Local information disclosure. Low impact on a single-user dev laptop; real exposure on shared/multi-user hosts and via the /tmp/cwd config fallbacks. Clearly a framework defect rather than operator error — the user never introduces the world-readability, and the inconsistency with token_manager's existing 0o600 writes is the tell.

Out of scope (follow-up)

The /tmp and cwd fallbacks in get_writable_config_path() remain. They're far less dangerous now (files are 0o600), but silently writing credentials to a predictable /tmp path or cwd is worth revisiting separately.

Tests

New regression tests assert 0o600 files and 0o700 dirs, and that shared fallback dirs are not globally tightened. All fail on the pre-fix code and pass after. Full settings/token suite (39 tests) green; ruff + mypy clean.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Hardened local settings persistence with owner-only permissions for the config directory (0o700) and settings file (0o600), using atomic write behavior for safer updates.
    • Strengthened secure credential storage by enforcing restrictive directory permissions (0o700) after creation, with best-effort permission correction.
  • Tests
    • Added POSIX-focused, platform-aware regression coverage for settings and credential directory/file permissions (skipped on Windows).

Credentials stored at rest were left world-readable on multi-user hosts:

- TokenManager._get_secure_storage_path() documented its credential dir as
  mode 0o700 but created it via mkdir() with default perms (0o755), leaving
  the Fernet secret.key and encrypted tokens.enc in a traversable dir.
- Settings.dump() persisted tool_repository_password (plaintext) to
  settings.json via open("w"), producing a 0o644 file, and created the
  config dir at 0o755 — despite the sibling token_manager already writing
  secrets atomically at 0o600.

Fixes:
- TokenManager: chmod the credential dir to 0o700 after mkdir (robust against
  umask and pre-existing dirs).
- Settings: write settings.json atomically at 0o600 (mkstemp + chmod +
  os.replace) and chmod the dedicated config dir to 0o700. The /tmp and cwd
  fallback parents are deliberately not chmod'd; the 0o600 file mode protects
  the credential there.

Adds regression tests asserting 0o600 files and 0o700 dirs, and that shared
fallback dirs are not globally tightened.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 19, 2026 06:24

@corridor-security corridor-security Bot 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.

Summary: This PR tightens credential-at-rest permissions by enforcing owner-only modes on settings files and credential directories and using atomic JSON writes.

Risk: Low risk. No exploitable security vulnerabilities were identified in the added code; the changes reduce local disclosure risk without introducing a new public attack surface or weakening authentication or authorization controls.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

settings.py adds helpers for owner-only config directory permissions and atomic secure JSON writes, and wires them into config path resolution, settings initialization, and dump persistence. token_manager.py now chmods the credential directory to 0o700. New POSIX-only tests cover both permission behaviors.

Changes

POSIX Permission Enforcement for Config and Credential Files

Layer / File(s) Summary
settings.py permission helpers and call sites
lib/crewai-core/src/crewai_core/settings.py
Adds os import, _ensure_dir_mode for 0o700 directory restriction, and _write_secure_json for atomic 0o600 JSON writes. get_writable_config_path(), Settings.__init__(), and Settings.dump() now call these helpers.
TokenManager credential directory chmod
lib/crewai-core/src/crewai_core/token_manager.py
Adds storage_path.chmod(0o700) with OSError suppression in _get_secure_storage_path().
POSIX permission regression tests
lib/cli/tests/test_config.py, lib/cli/tests/test_token_manager.py
Adds tests for settings.json file mode, config directory mode, temp-dir handling, and secure credential directory permissions, all skipped on Windows.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main security change: enforcing owner-only permissions for credential storage.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/credential-file-permissions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread lib/crewai-core/src/crewai_core/settings.py Fixed
Comment thread lib/crewai-core/src/crewai_core/token_manager.py Fixed

Copilot AI 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.

Pull request overview

This PR hardens credential-at-rest handling by enforcing owner-only permissions for the token credential directory and the persisted settings file, aligning behavior with the existing secure-write approach used elsewhere in the codebase.

Changes:

  • Enforce 0o700 on the TokenManager credential directory after creation (umask- and pre-existing-dir-safe).
  • Write settings.json atomically and enforce 0o600 for the file and 0o700 for the dedicated config directory (while avoiding chmod on shared fallback dirs).
  • Add regression tests asserting the restrictive modes and ensuring shared fallback directories aren’t chmod’d.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
lib/crewai-core/src/crewai_core/token_manager.py Tightens credential directory permissions to match documented 0o700.
lib/crewai-core/src/crewai_core/settings.py Adds secure directory-mode enforcement and atomic 0o600 settings writes.
lib/cli/tests/test_token_manager.py Adds permission regression tests for TokenManager storage directory.
lib/cli/tests/test_config.py Adds permission regression tests for settings file/dir and shared fallback behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/crewai-core/src/crewai_core/settings.py
Comment thread lib/cli/tests/test_config.py
Comment thread lib/cli/tests/test_token_manager.py
theCyberTech and others added 4 commits June 19, 2026 14:42
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Comment thread lib/crewai-core/src/crewai_core/settings.py Fixed
@theCyberTech theCyberTech force-pushed the fix/credential-file-permissions branch from 8a05735 to 035a90d Compare June 25, 2026 02:07
@theCyberTech theCyberTech merged commit 654abcb into main Jun 25, 2026
53 checks passed
@theCyberTech theCyberTech deleted the fix/credential-file-permissions branch June 25, 2026 17:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants