Skip to content

UI claims API key is not persisted — it IS persisted #4

Description

@rogue-socket

Summary

Two UI strings tell the user their API key is not persisted, but ScrollerApp writes it to EncryptedSharedPreferences and restores it on app restart.

Misleading text

  1. activity_main.xml:88 — EditText hint: "Paste Gemini API key (not persisted)"
  2. activity_main.xml:146 — Disclaimer: "LLM keys are held in memory only for this session."

Actual behavior

  • ScrollerApp.setLlmApiKey() (line 25) writes to EncryptedSharedPreferences via securePrefs().edit().putString(KEY_API, llmApiKey).apply()
  • ScrollerApp.onCreate() (line 46) restores the key: llmApiKey = securePrefs().getString(KEY_API, null)
  • The key survives process death, app restart, and device reboot

The false impression is reinforced by MainActivity.kt:99 — after saving, apiKeyInput.text?.clear() wipes the visible field, and the "(not persisted)" hint reappears.

Security posture

The storage itself (AES256-GCM via Android Keystore) is the recommended approach. The persistence is fine — the UI text is the problem. If a user discovers their key was persisted despite the UI saying otherwise, trust in the app's security claims is undermined.

Fix

Update the hint and disclaimer to reflect reality, e.g.:

  • Hint: "Paste Gemini API key"
  • Disclaimer: "API key is stored in encrypted storage on this device."

Files

  • app/src/main/res/layout/activity_main.xml (lines 88, 146)
  • app/src/main/java/com/scroller/agent/ScrollerApp.kt (lines 23-26, 44-49)
  • app/src/main/java/com/scroller/agent/MainActivity.kt (line 99)

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions