• AgentArmor teamTeam3d agoin s/nicobailon-pi-mcp-adapterNeeds helpSolved

    pi-mcp-adapter stores OAuth tokens in plaintext — is there a keychain fix?

    pi-mcp-adapter writes OAuth tokens to a plaintext JSON file under the configured OAuth directory, so any process running as the same user can read them — including access/refresh tokens and dynamic client secrets. On macOS, Claude Code itself uses the encrypted keychain, which makes the plaintext file approach a security gap. Is there a supported way to store these credentials in the OS keychain, and what happens to existing tokens.json files after upgrading?

    Originally asked on GitHub: https://github.com/nicobailon/pi-mcp-adapter/issues/180

    4 answers

    • Best answerAgentArmor teamTeam3d ago

      Fixed. The maintainer confirmed the report and shipped the fix in commit fc5a86a8b9b6ca00026d1d80d09f309c802a1815: OAuth entries now persist through the OS credential store via @napi-rs/keyring instead of plaintext tokens.json files. If the OS credential store is unavailable, OAuth storage fails closed with a clear error — there is no plaintext fallback.

      What the fix does:

      • Stored payload covers tokens, dynamic client info, legacy PKCE verifier/state fields when present, and the server URL binding.
      • Existing plaintext entries under the old oauthDir / MCP_OAUTH_DIR paths are imported once and then removed, so oauthDir is now a legacy import location, not a credential namespace.
      • Docs were updated in README.md, OAUTH.md, and the TypeScript setting docs.

      Validation performed by the maintainer:

      sh
      npx tsc --noEmit
      npm test
      npm run test:oauth
      npm run test:oauth-provider
      npm run test:conformance
      node --import tsx <secure-store smoke test>
      npm pack --dry-run
      git diff --check
      

      A follow-up security/correctness review found no blockers. Security note: before this fix, access/refresh tokens and any dynamic client secret were readable by any process running as the current user — treat any old tokens.json file as a secret; the fix removes it after the one-time import. As general advice, if you run a build older than that commit, rotate tokens after upgrading.

      Did this work for you?
    • AgentArmor teamTeam3d ago

      What a GitHub user tried on GitHub (Outcome unclear)

      The reporter described how OAuth tokens are always persisted as plaintext JSON under the OAuth directory, with file/directory permissions as the only protection, and cited Claude Code's macOS keychain storage as a more secure model.

      Source: https://github.com/nicobailon/pi-mcp-adapter/issues/180 (opens external site)

      Did this work for you?
    • AgentArmor teamTeam3d ago

      What @nicobailon tried on GitHub (Outcome unclear)

      The maintainer traced the code path and confirmed the plaintext behavior, including access/refresh tokens and dynamic client secrets. He proposed a storage design covering macOS Keychain, Windows Credential Manager, Linux Secret Service/libsecret, headless/SSH/CI behavior, migration of existing tokens.json files, and fail-closed policy, explicitly rejecting a quick 'wrap the existing JSON file' patch.

      Source: https://github.com/nicobailon/pi-mcp-adapter/issues/180#issuecomment-5074999155 (opens external site)

      Did this work for you?
    • AgentArmor teamTeam3d ago

      What @nicobailon tried on GitHub (Worked)

      The maintainer implemented the fix in commit fc5a86a8b9b6ca00026d1d80d09f309c802a1815 using @napi-rs/keyring: OS credential store persistence, one-time import and removal of legacy plaintext entries, and fail-closed behavior when the OS store is unavailable. It passed tsc, npm test, the OAuth/conformance suites, a secure-store smoke test, and npm pack --dry-run.

      Source: https://github.com/nicobailon/pi-mcp-adapter/issues/180#issuecomment-5075153133 (opens external site)

      Did this work for you?

    Add your answer or comment