Skip to content

Prompt-saved secrets are written 0o644 by the configs TextFiles store (gap left by #21) #33

Description

@thorwhalen

Found during the 2026-09-26 cloud sweep. #21 routed ConfigStore.persist, FileStore, ensure_seeded and the directory helpers through secure_open/secure_makedirs, but the store behind the headline flow was not covered. That store backs config_getter, simple_config_getter and get_configs_local_store: a dol TextFiles, one file per key. It still writes with a plain open, so value files get the umask default.

Reproduction (Linux, config2py 0.1.54)

A folder created by an older config2py, or by the user, is 0o755. _default_folder_setup only tightens folders it creates itself.

cd "$(mktemp -d)" && mkdir -p .config/config2py/configs && chmod 755 .config .config/config2py .config/config2py/configs
HOME=$PWD python -c "
import os
from config2py import config_getter
config_getter.configs['OPENAI_API_KEY'] = 'sk-demo'
p = os.path.expanduser('~/.config/config2py/configs')
print('dir', oct(os.stat(p).st_mode & 0o777), 'file', oct(os.stat(p + '/OPENAI_API_KEY').st_mode & 0o777))
"
# dir 0o755 file 0o644   <- the saved key is readable by every local user

A fresh install is protected by its 0o700 folder, but the file itself is still 0o644. The same holds for any folder path passed to simple_config_getter.

Why not fixed in the sweep

The sweep's code scope was #13 and #16. Also, get_configs_local_store returns a plain dol.TextFiles, and swapping in a subclass changes the public return type for about 30 dependents.

Proposed fix

  1. Add a SecureTextFiles(TextFiles) in config2py/tools.py whose __setitem__ writes through secure_open. Return it from get_configs_local_store for the folder and app-name cases. Keep it an isinstance of TextFiles.
  2. In get_configs_folder_for_app, re-tighten an existing config2py-managed folder (one that has the .config2py marker) with secure_makedirs.
  3. POSIX-only tests in config2py/tests/test_secure_io.py: a pre-existing 0o755 folder plus config_getter.configs[k] = v gives a 0o600 file and a 0o700 folder.
  4. Run the dependents gate.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions