ADFA-4684 | Fix Gemini API key entry: show/hide, trim, and at-rest encryption - #49
Conversation
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
|
@claude review |
There was a problem hiding this comment.
Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.
Once credits are available, comment @claude review on this pull request to trigger a review.
c809089 to
4426b31
Compare
086fe7b to
3ded9d8
Compare
hal-eisen-adfa
left a comment
There was a problem hiding this comment.
Requesting changes. Two blocking items scoped to this PR's diff (the API-key security + FilePicker rewrite). The larger AI-plugin findings from the review belong to the base PR #41 and are posted there, not here.
The rest of the PR is solid: AES/GCM at-rest encryption with legacy-plaintext passthrough, inputType="textPassword" on the key field, save-failure surfaced instead of crashing, and the in-place FilePicker refresh that fixes the second-"Toggle All" crash.
3d33b7a to
b939ff5
Compare
3ded9d8 to
759d71d
Compare
5764d1f to
b44608f
Compare
45aa44d to
8f1b26a
Compare
6f2ea13 to
b91dd63
Compare
a830c7a to
3739da0
Compare
hal-eisen-adfa
left a comment
There was a problem hiding this comment.
Code review of the Gemini API-key security work. The crypto core is sound — AES/GCM with a fresh random 12-byte IV per encrypt, GCM tag verification, fail-closed decrypt, and a sensible legacy-plaintext migration. No blockers; 6 non-critical findings inline below, ranked by severity. Note this is a static review — the encryption, on-device migration, and FLAG_SECURE screenshot-blocking still need device verification (install both .cgp, save a key, confirm ciphertext in prefs, revoke the Keystore alias to exercise the 'unreadable' path).
- Fix file picker empty state and `BadTokenException` by using the correct project context (`IdeProjectService`) and moving I/O off the main thread. - Secure Gemini API key with hardware-backed Keystore encryption (including legacy migration) and add a show/hide toggle. - Improve UI by replacing emoji markers with vector drawables and extracting hardcoded strings to `strings.xml`.
…the file picker Encrypt the key with AES/GCM under an Android Keystore secret and run all crypto off the UI thread; confine the context-file picker to the open project via normalized canonical-path checks with off-thread listing and no fallback root.
3739da0 to
c25ee89
Compare
Encrypt the key with AES/GCM under an Android Keystore secret, migrating existing plaintext on first read; send it as a header, never a query string. Confine the context-file picker to the open project, failing closed on an unresolvable root, and fix the crash on a second "Toggle All".

Description
Fixes the Gemini API key input in the AI Assistant plugin, reported in appdevforall/CodeOnTheGo#1514 where keys wouldn't save correctly and produced 400 "invalid API key" errors. The field now has a working show/hide (eye) toggle that reveals the actual saved key, trims the value on save (dropping the trailing spaces/newlines Gemini rejects), and stops corrupting the key with a masked placeholder on edit. The key is also encrypted at rest with a hardware-backed Android Keystore secret instead of being stored as plaintext.
Details
Changes:
ic_visibility/ic_visibility_offdrawables and anImageButtonbeside the input; toggle swapsinputTypevia an explicit visibility flag (the previous bit-check never flipped back, so it always read "hidden").saveButtontrims before persisting (read side already trimmed).SecureApiKeyStore(AES/GCM, Android Keystore) in both ai-assistant (write/read) and ai-core (read for API calls); only ciphertext hits SharedPreferences, and legacy plaintext keys migrate transparently on next save.document_5111703426673150080.mp4
Ticket
ADFA-4684
Fixes:
Observation
SecureApiKeyStoreis duplicated in ai-assistay're separate Gradle projects with no shared module; the two copies must stay in sync (same aliascotg_ai_gemini_key_v1and transform) or ai-core can't decrypt what ai-assistant wrote. They interoperate because both plugins run in the host app's process (shared Keystore).