MOB-71 — trim Play upload keystore passphrase at the prompt - #80
Merged
Merged
Conversation
`Mix.shell().prompt/1` returns the whole input line including the trailing newline, and `SetupWizard.generate_keystore/2` passed the raw value into both `keytool -storepass` and `android/keystore.properties`. Gradle read that file literally on subsequent release signing, so the keystore held a password ending in `\n` — a value nobody could re-type at the next Play upload. The failure is silent until an AAB upload rejects the signature. - Extract `keystore_properties_content/1` as a public pure function that trims defensively, so the fix is testable at the seam. - Prompt values (passphrase, name, org) run through a new `prompt_trimmed/2` helper. The `-dname` and `-storepass`/`-keypass` keytool args then get already-clean strings. - Three tests on the content function; two flip on revert. Verified by temporarily removing the `String.trim` and rerunning — two assertions fail, one (the clean-passphrase happy-path anchor) passes either way. Other prompt sites in the file (project number, developer account id, package name) already trim their input; only the three keystore prompts were leaking the newline through. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Mix.shell().prompt/1returns the input line including the trailing newline.SetupWizard.generate_keystore/2passed that raw value into bothkeytool -storepass/-keypassandandroid/keystore.properties. Gradle later read that file literally on release signing, so every subsequent AAB was signed with a password ending in\n— a value nobody could re-type at the Play upload console. The failure is silent until an upload rejects the signature deep inbundletool, and by then the keystore is committed to being that value (Play Console binds the app to its signature).Changes
prompt_trimmed/2— new private helper wrappingshell.prompt/1+String.trim/1. All three prompts ingenerate_keystore/2(passphrase, name, org) now go through it.keystore_properties_content/1— extracted fromwrite_keystore_properties/2as a@doc'd public function, so the trim is testable at the seam without needing to mockMix.shell(). Trims defensively — a raw string in still becomes a clean line out.Tests
Three tests in
test/mob_dev/google_play/setup_wizard_test.exs(describe "keystore_properties_content/1"):does NOT bake a trailing newline— feeds\"secret\\n\", asserts the file body containsstorePassword=secreton its own line and NOTstorePassword=secret\\n\\n. Flips on revert.strips leading/trailing whitespace— feeds\" secret \", asserts the same. Flips on revert.leaves an already-clean passphrase alone— happy-path anchor; passes either way.Manually revert-verified: temporarily removed
String.trim(passphrase)from the pure function, forced a recompile, and reran the test — 2 of the 3 assertions fail with the actual expected diagnostic output. Restored → 15/15 pass.Scope check
Other
shell.promptsites in the file (project number/id at line 282, developer account id at line 424, package name at line 510) already trim their input. Only the three keystore prompts were leaking the newline; the audit's "inconsistent" description was accurate.Gates
mix test: 2450 pass, 0 failmix format --check-formatted: cleanmix credo --strict: 0 issues (3752 mods/funs)mix compile --warnings-as-errors --force: cleanmix mob.security_scan: 0 findingsCloses MOB-71.