Skip to content

Fix base64 decode error for keystore signing - #1

Merged
GeneralKaos666 merged 1 commit into
mainfrom
copilot/fix-checks-issue
Jul 18, 2026
Merged

GeneralKaos666 merged 1 commit into
mainfrom
copilot/fix-checks-issue

Conversation

Copilot AI commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Problem

The workflow fails with base64: invalid input when decoding the KEYSTORE_B64 secret. This happens because:

  1. printf '%s' can produce output that base64 -d rejects
  2. Base64-encoded content (especially from tools like base64 or openssl) often contains newlines, which base64 -d rejects by default

Fix

Changed the decode command to:

echo "$KEYSTORE_B64" | base64 --decode --ignore-garbage
  • Reverts from printf '%s' back to echo (was working before)
  • Adds --ignore-garbage flag so newlines/whitespace in the base64 string are handled gracefully

@GeneralKaos666
GeneralKaos666 marked this pull request as ready for review July 18, 2026 01:19
Copilot AI review requested due to automatic review settings July 18, 2026 01:19
@GeneralKaos666
GeneralKaos666 merged commit 40ed2a0 into main Jul 18, 2026
1 check passed
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Fix keystore base64 decode in GitHub Actions signing step

🐞 Bug fix ⚙️ Configuration changes 🕐 Less than 5 minutes

Grey Divider

AI Description

• Decode KEYSTORE_B64 using base64 --decode with --ignore-garbage to tolerate whitespace/newlines
• Switch from printf back to echo to avoid base64 invalid input failures
• Keep generated JKS path unchanged for downstream signing configuration
Diagram

graph TD
  A["GitHub Actions workflow"] --> B["Decode KEYSTORE_B64"] --> C[("JKS keystore file")] --> D["Signing step"]
  S["GitHub Secrets"] --> B
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Normalize base64 input (strip whitespace) then strict decode
  • ➕ Keeps strict base64 decoding semantics (fails fast on truly invalid characters)
  • ➕ Avoids relying on GNU coreutils-specific --ignore-garbage behavior in some environments
  • ➖ More shell plumbing (e.g., tr/sed) and quoting edge-cases
  • ➖ Still depends on how the secret was produced and whether it includes CRLF/newlines
2. Store keystore as a binary secret/artifact instead of base64
  • ➕ Eliminates base64 decoding fragility entirely
  • ➕ Reduces risk of newline/whitespace corruption during copy/paste
  • ➖ May be harder to manage/rotate in GitHub Secrets UI depending on organization practices
  • ➖ Still requires secure handling on runner and cleanup

Recommendation: The chosen approach is appropriate for GitHub-hosted runners where base64 supports --ignore-garbage and the primary failure mode is whitespace/newlines in the secret. If portability across different runner environments becomes a concern, consider normalizing whitespace and keeping strict decoding, or switching to a binary-safe secret distribution method.

Files changed (1) +1 / -1

Other (1) +1 / -1
build.ymlMake keystore base64 decode tolerant of whitespace/newlines +1/-1

Make keystore base64 decode tolerant of whitespace/newlines

• Replaces printf|base64 -d with echo|base64 --decode --ignore-garbage when materializing the JKS keystore. This prevents CI failures caused by newline/whitespace characters in KEYSTORE_B64.

.github/workflows/build.yml

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the GitHub Actions build workflow to more reliably decode a base64-encoded Android signing keystore secret during release APK builds, addressing base64: invalid input failures.

Changes:

  • Switches keystore decoding to use base64 --decode --ignore-garbage to tolerate whitespace/newlines in the secret.
  • Adjusts the command used to feed KEYSTORE_B64 into base64 during workflow execution.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

KP: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
run: |
printf '%s' "$KEYSTORE_B64" | base64 -d > "$RUNNER_TEMP/ghost-rain.jks"
echo "$KEYSTORE_B64" | base64 --decode --ignore-garbage > "$RUNNER_TEMP/ghost-rain.jks"
@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Permissive base64 decode 🐞 Bug ☼ Reliability
Description
The workflow decodes KEYSTORE_B64 with base64 --ignore-garbage, which silently discards any
non-base64 characters instead of failing fast on malformed input. This can turn a paste-corrupted
secret into a different .jks file and defer the failure to Gradle signing with harder-to-diagnose
errors.
Code

.github/workflows/build.yml[28]

+          echo "$KEYSTORE_B64" | base64 --decode --ignore-garbage > "$RUNNER_TEMP/ghost-rain.jks"
Evidence
The workflow writes the keystore file from KEYSTORE_B64 using --ignore-garbage and then
generates keystore.properties; Gradle reads that properties file and uses it to configure release
signing, so any silently-corrupted decoded bytes will propagate into the signing process.

.github/workflows/build.yml[20-34]
app/build.gradle[35-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The workflow currently uses `base64 --decode --ignore-garbage` to decode the keystore secret. This weakens validation by silently discarding non-base64 characters, which can produce a corrupted keystore file and move the error to a later signing step.

## Issue Context
This decoded file is then referenced via `keystore.properties` and consumed by the Android Gradle signing configuration, so failing fast at decode time is valuable for diagnosability.

## Fix Focus Areas
- .github/workflows/build.yml[20-34]

## Suggested fix
Replace the permissive decode with a strict decode while only normalizing expected whitespace (e.g., remove `\r`/newlines) and keep decode errors fatal.

Example:
```bash
printf '%s' "$KEYSTORE_B64" | tr -d '\r\n' | base64 --decode > "$RUNNER_TEMP/ghost-rain.jks"
```
(Optionally, add a small validation step to ensure the sanitized string contains only base64 characters before decoding.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

KP: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
run: |
printf '%s' "$KEYSTORE_B64" | base64 -d > "$RUNNER_TEMP/ghost-rain.jks"
echo "$KEYSTORE_B64" | base64 --decode --ignore-garbage > "$RUNNER_TEMP/ghost-rain.jks"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

1. Permissive base64 decode 🐞 Bug ☼ Reliability

The workflow decodes KEYSTORE_B64 with base64 --ignore-garbage, which silently discards any
non-base64 characters instead of failing fast on malformed input. This can turn a paste-corrupted
secret into a different .jks file and defer the failure to Gradle signing with harder-to-diagnose
errors.
Agent Prompt
## Issue description
The workflow currently uses `base64 --decode --ignore-garbage` to decode the keystore secret. This weakens validation by silently discarding non-base64 characters, which can produce a corrupted keystore file and move the error to a later signing step.

## Issue Context
This decoded file is then referenced via `keystore.properties` and consumed by the Android Gradle signing configuration, so failing fast at decode time is valuable for diagnosability.

## Fix Focus Areas
- .github/workflows/build.yml[20-34]

## Suggested fix
Replace the permissive decode with a strict decode while only normalizing expected whitespace (e.g., remove `\r`/newlines) and keep decode errors fatal.

Example:
```bash
printf '%s' "$KEYSTORE_B64" | tr -d '\r\n' | base64 --decode > "$RUNNER_TEMP/ghost-rain.jks"
```
(Optionally, add a small validation step to ensure the sanitized string contains only base64 characters before decoding.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@GeneralKaos666
GeneralKaos666 deleted the copilot/fix-checks-issue branch July 18, 2026 03:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants