Skip to content

fix(credential_store): stop persisting encryption key file when keyring is available#345

Merged
jpoehnelt merged 1 commit intomainfrom
fix/encryption-key-file-leak
Mar 9, 2026
Merged

fix(credential_store): stop persisting encryption key file when keyring is available#345
jpoehnelt merged 1 commit intomainfrom
fix/encryption-key-file-leak

Conversation

@jpoehnelt
Copy link
Member

Summary

get_or_create_key() unconditionally wrote the encryption key to ~/.config/gws/.encryption_key on first run, even when the OS keyring was available. This left key material on disk as a plain file (permissions 0600), making credentials fully portable by copying the config directory.

Changes

  • Extract save_key_file() helper — deduplicates file-writing logic with secure permissions
  • Keyring success path: delete stale .encryption_key if it exists (migrates existing installs on upgrade)
  • NoEntry + existing file: migrate file-based key into keyring, then delete the file
  • NoEntry + new key: try keyring first; only write .encryption_key as fallback if keyring store fails

Migration

Existing users with a stale .encryption_key file will have it automatically removed on their next CLI invocation, as long as their OS keyring is working. No manual steps required.

Testing

All 499 tests pass. The 8 credential_store tests specifically validate encrypt/decrypt round-trips and key determinism.

Fixes #344

@changeset-bot
Copy link

changeset-bot bot commented Mar 9, 2026

🦋 Changeset detected

Latest commit: bf7e2e6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@googleworkspace/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the security posture of credential storage by preventing the unnecessary persistence of encryption keys to local files when a more secure OS keyring is present. It introduces a robust migration path for existing installations, automatically moving previously file-stored keys to the keyring and cleaning up the old files. The changes streamline key management, making the system more secure by default and reducing the attack surface for sensitive data.

Highlights

  • Enhanced Security: Stopped persisting encryption keys to a local file (.encryption_key) when an OS keyring is available, reducing exposure of sensitive data.
  • Key Migration: Implemented automatic migration of existing file-based encryption keys into the OS keyring, deleting the old file upon successful migration.
  • Code Refactoring: Extracted file-writing logic into a dedicated save_key_file helper function to ensure consistent and secure permissions (0600 for file, 0700 for directory).
  • Keyring Priority: Modified key generation and storage to prioritize the OS keyring, only falling back to file storage if the keyring is unavailable or fails.
Changelog
  • .changeset/fix-encryption-key-file-leak.md
    • Added a new changeset entry describing the fix for encryption key file leakage.
  • src/credential_store.rs
    • Extracted a new private helper function save_key_file to encapsulate secure file writing logic for encryption keys.
    • Modified get_or_create_key to remove the .encryption_key file if a key is successfully retrieved from the keyring, ensuring migration for existing installations.
    • Updated the logic for handling NoEntry cases: if an existing key file is found, it attempts to migrate it to the keyring and then deletes the file.
    • Changed the new key generation flow to first attempt storing the key in the keyring, only falling back to file storage if the keyring operation fails.
    • Replaced duplicated file-writing code with calls to the new save_key_file helper function.
Activity
  • All 499 tests passed, including 8 specific credential_store tests validating encrypt/decrypt round-trips and key determinism.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Generative AI Prohibited Use Policy, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@googleworkspace-bot googleworkspace-bot added the cla: yes This human has signed the Contributor License Agreement. label Mar 9, 2026
Copy link
Contributor

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

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 improves security by prioritizing the OS keyring for storing the encryption key and only using a file as a fallback. The changes also include logic to migrate existing file-based keys to the keyring. This is a great improvement. However, I've found a critical issue where I/O errors during the key file saving process are ignored, which could lead to data loss if the key is not persisted correctly. My review includes suggestions to fix this by propagating errors.

Note: Security Review is unavailable for this PR.

@github-actions github-actions bot added gemini: reviewed Gemini Code Assist has reviewed the latest changes and removed gemini: reviewed Gemini Code Assist has reviewed the latest changes labels Mar 9, 2026
@jpoehnelt
Copy link
Member Author

Addressed the review feedback from @gemini-code-assist: save_key_file now returns std::io::Result<()> and both call sites propagate errors via ?. This prevents silent data loss if the fallback key file can't be written.

@gemini-code-assist
Copy link
Contributor

Thank you for addressing the feedback, @jpoehnelt! I've reviewed the changes and confirmed that save_key_file now correctly returns std::io::Result<()> and errors are propagated using the ? operator at both call sites. This significantly improves the robustness of the fallback key file writing by preventing silent data loss. Excellent work!

@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

/gemini review

1 similar comment
@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

/gemini review

@jpoehnelt jpoehnelt force-pushed the fix/encryption-key-file-leak branch from 0db5a76 to 59eee6f Compare March 9, 2026 21:00
@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

/gemini review

@jpoehnelt jpoehnelt force-pushed the fix/encryption-key-file-leak branch from 59eee6f to e094e69 Compare March 9, 2026 21:33
@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

/gemini review

@jpoehnelt jpoehnelt force-pushed the fix/encryption-key-file-leak branch from e094e69 to 8c4930d Compare March 9, 2026 21:35
@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

/gemini review

…ng is available

Previously, get_or_create_key() unconditionally wrote the encryption key
to ~/.config/gws/.encryption_key on first run, even when the OS keyring
was available. This left the key material on disk as a plain file,
making credentials portable by copying the config directory.

Changes:
- Extract save_key_file() helper to deduplicate file-writing logic
- On keyring read success: delete stale .encryption_key (migration)
- On NoEntry + existing file: migrate key into keyring, then delete file
- On NoEntry + new key: try keyring first, only write file as fallback

Fixes #344
@jpoehnelt jpoehnelt force-pushed the fix/encryption-key-file-leak branch from 8c4930d to bf7e2e6 Compare March 9, 2026 21:42
@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

/gemini review

@jpoehnelt jpoehnelt merged commit 5872dbe into main Mar 9, 2026
28 checks passed
@jpoehnelt jpoehnelt deleted the fix/encryption-key-file-leak branch March 9, 2026 21:51
@codecov
Copy link

codecov bot commented Mar 9, 2026

Codecov Report

❌ Patch coverage is 8.33333% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.74%. Comparing base (2b4bcbb) to head (bf7e2e6).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
src/credential_store.rs 8.33% 22 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #345      +/-   ##
==========================================
- Coverage   61.78%   61.74%   -0.05%     
==========================================
  Files          38       38              
  Lines       14607    14603       -4     
==========================================
- Hits         9025     9016       -9     
- Misses       5582     5587       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: auth cla: yes This human has signed the Contributor License Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

credential_store: .encryption_key file persists on disk even when OS keyring succeeds

3 participants