Skip to content

CLI stops steering the OpenAI key into .agentic.yml (#59) - #66

Open
minerva-sky wants to merge 2 commits into
codenamev:mainfrom
minerva-sky:security/no-token-in-agentic-yml
Open

minerva-sky wants to merge 2 commits into
codenamev:mainfrom
minerva-sky:security/no-token-in-agentic-yml

Conversation

@minerva-sky

Copy link
Copy Markdown
Collaborator

Closes #59.

The missing-token error (check_api_token!) and two README sections told users to run agentic config set api_token=.... That writes plain-text YAML to $PWD/.agentic.yml with umask permissions, the file is not gitignored (this repo's own .gitignore ignores .env but not .agentic.yml), and nothing in lib/ ever reads api_token back: LegacyConfiguration takes the token from OPENAI_ACCESS_TOKEN / AGENTIC_API_TOKEN only, and active_config is consumed by config list and config get alone. So the advice stored a secret one git add . from a public repo, and the user got the same error box on the next run.

What changes

  • The error box names the paths that work: the two env vars, Agentic.configure { |c| c.access_token = ... }, or AGENTIC_API_BASE_URL for a local endpoint that needs no token. The .agentic.yml and config set api_token= lines are gone.
  • README drops the api_token example from the command list and from the configuration section, and says why the key stays out of .agentic.yml.
  • config set refuses credentials. Keys containing token, key, secret, passw, or credential in any spelling (api_token, apiKey, api-key, apikey, accessToken), and values shaped like an OpenAI key (sk-...) under any key name. It prints why and exits 1 before any read or write. The substring match is deliberate: a false positive such as max_token costs a rename and the message says so, a false negative costs a secret.

Nothing else about .agentic.yml changes: existing files still load, config get still reads whatever is in them, and model remains the example key. Making the home-directory file actually carry a token (0600 write plus a reader) is the product call the issue leaves for a separate ask.

Tests

spec/agentic/cli/config_commands_spec.rb: eleven credential-shaped KEY=VALUE forms all exit non-zero with save_config never called; model=gpt-4o-mini still writes. spec/agentic/cli_spec.rb: the error text names OPENAI_ACCESS_TOKEN and Agentic.configure and no longer mentions .agentic.yml. The existing placeholder key test_key is renamed test_option because it trips the guard. Full suite on the first commit: 1394 examples, 1 failure (the event_dispatcher_integration_spec.rb:291 timing flake that #36 addresses); CLI specs re-run green on the final commit, StandardRB clean.

Side finding, not changed here: lib/agentic/cli/config.rb defines a second CLI::Config class with the same commands that nothing references (cli.rb wires ConfigCommands). It still has the unguarded set. Dead code; worth its own removal.

Panel

  • DHH — cleared. One regex constant and one guard in the existing Thor command; nits (private_constant, Thor::Error over exit 1) noted, the guard copies the invalid-format branch's existing exit 1 for consistency.
  • Obie Fernandez — objected, then cleared on revision. Objection (3/3): the first cut matched whole snake_case segments only, so apiKey, api-key, apikey, accessToken walked through, and values were never checked. Fixed: substring key match plus the sk- value check. Re-run 3/3 cleared; residual gaps (other vendors' token shapes under innocuous keys, URL userinfo) are out of scope for closing the paths the CLI itself advertised.
  • Vladimir Dementyev — cleared. Guard runs before any I/O, specs are in-memory, instance_double pins the configuration seam.
  • The gem consumer — cleared 2/3. Dissent: config set api_token= exiting 1 is a CLI behaviour change without a warn-first release. Rebuttal: the old call never did anything but leak, a warn-first release would keep writing plain-text secrets, the gem is pre-1.0, and the CHANGELOG carries it under Security.

🤖 Generated with Claude Code

minerva-sky and others added 2 commits October 15, 2026 01:52
The missing-token error and the README told users to run
`agentic config set api_token=...`. That writes plain-text YAML to
$PWD/.agentic.yml, which is not gitignored, and nothing in lib/ ever
reads api_token back: LegacyConfiguration takes the token from
OPENAI_ACCESS_TOKEN / AGENTIC_API_TOKEN only. The advice stored a secret
one `git add .` from a public repo and did not even work.

- check_api_token! now names the paths that work: the env vars,
  Agentic.configure, or a local endpoint via AGENTIC_API_BASE_URL.
- README drops the api_token example and says why the key stays out of
  .agentic.yml.
- `config set` refuses credential-shaped keys (token, key, secret,
  password as whole name segments; "tokenizer" still passes) and exits
  non-zero without writing.
- Specs: refusal writes nothing, non-secret keys still work, the error
  text no longer mentions .agentic.yml. The existing placeholder key
  `test_key` is renamed `test_option` because it trips the guard.

Closes codenamev#59

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Whole-segment matching let apiKey, api-key, apikey and accessToken
through. The key check is a plain substring match now, and a value that
looks like an OpenAI key is refused whatever the key is called.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@minerva-sky minerva-sky added the loop:drain Implemented from the improvements ledger by the drain loop label Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

loop:drain Implemented from the improvements ledger by the drain loop

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI and README steer the OpenAI key into $PWD/.agentic.yml, which nothing reads and nothing gitignores

1 participant