Skip to content

Google EAB - fail to register account with EAB. #1218

@tanmoy-bb

Description

@tanmoy-bb

Bug Report: EAB Account Registration Fails Due to Missing Contact Email

  |   -- | -- Report Title | EAB Account Registration with Google Public CA Fails Due to Missing Contact Email Date of Report | 16 October 2025 Affected Component | nginxproxy/acme-companion Identified Version | v2.6.1-18-g8fedf68 (image tag v2.6.1) Severity | High (Blocks all certificate issuance with EAB-required CAs)

1. Executive Summary

When using the acme-companion container to obtain a certificate from a Certificate Authority (CA) that requires External Account Binding (EAB), such as Google Public CA, the process fails during the initial account creation. The script constructs and executes an acme.sh --register-account command that includes the EAB credentials but omits the mandatory contact email address.

This malformed request is rejected by the CA, but not before the single-use EAB key is consumed. This action invalidates the key and causes all subsequent registration attempts to fail with an authorization error. The container becomes stuck in an unrecoverable loop, permanently preventing certificate issuance for that environment until a manual intervention is performed.

2. Environment and Configuration

  • acme-companion version: v2.6.1-18-g8fedf68 (from container logs)

  • acme.sh version: 3.1.1 (from container logs)

  • Certificate Authority: Google Public CA (https://dv.acme-v02.api.pki.goog/directory)

  • Scenario: First-time setup on a clean environment with no pre-existing Docker volumes for acme or vhost.d.

3. Detailed Analysis of Failure Sequence

The failure unfolds in a precise, reproducible sequence of events:

Step A: Initial Registration Attempt The container correctly identifies the need to register a new account and calls acme.sh. However, the constructed command is missing the email parameter (-m or --accountemail).

Log Snippet of the flawed command:

Calling acme.sh --register-account with the following parameters : --log /dev/null ... --server [https://dv.acme-v02.api.pki.goog/directory](https://dv.acme-v02.api.pki.goog/directory) --eab-kid ... --eab-hmac-key ...

Step B: First Failure - Malformed Request The Google CA server receives the request but rejects it because the contact information is missing, as per ACME protocol requirements.

Error Log Snippet:

{
  "type": "urn:ietf:params:acme:error:malformed",
  "detail": "Accounts must have at least one contact."
}

Step C: Consequence - EAB Key is Consumed Crucially, this failed transaction consumes and invalidates the single-use EAB key.

Step D: Second Failure - Unauthorized The container enters a retry loop. On the next attempt, it sends the same request, but the EAB key is now invalid. The CA rejects it with a different error.

Error Log Snippet:

{
  "type": "urn:ietf:params:acme:error:unauthorized",
  "detail": "Unknown external account binding (EAB) key."
}

The container is now permanently stuck, as it cannot register the account and does not have the logic to request a new EAB key.

4. Steps to Reproduce

  1. Begin with a clean Docker environment (no acme or vhost.d volumes).

  2. Generate a fresh, unused EAB key from Google Cloud.

  3. Use a docker-compose.yml file similar to the one below, populated with valid credentials.

  4. Run docker compose up -d and monitor the logs of the acme-companion container. The failure sequence described above will occur within minutes.

Example docker-compose.yml:

version: '3.7'

services:
nginx-proxy:
image: nginxproxy/nginx-proxy
# ... ports, volumes, networks ...

acme-companion:
image: nginxproxy/acme-companion:v2.6.1 # Bug is present in this version
volumes:
# ... standard volumes ...
- acme:/etc/acme.sh
environment:
- DEFAULT_EMAIL=your-valid-email@example.com
- ACME_CA_URI=https://dv.acme-v02.api.pki.goog/directory
- ACME_EAB_KID=[PASTE_YOUR_NEW_EAB_KID]
- ACME_EAB_HMAC_KEY=[PASTE_YOUR_NEW_EAB_HMAC_KEY]
# ... rest of config ...

my-web-app:
image: httpd:alpine
environment:
- VIRTUAL_HOST=your.domain.com
- LETSENCRYPT_HOST=your.domain.com
# ... rest of config ...

volumes:
acme:

... other volumes ...


5. Proven Manual Workaround

The issue was successfully resolved by manually executing the correct registration command from within the container. This proves that acme.sh itself is capable, but the command constructed by acme-companion is flawed.

  1. Generate a new EAB key, as the previous one is invalid.

  2. exec into the running acme-companion container.

  3. Run the following command, which explicitly includes the --config-home and -m parameters that the automated script omits:

    /app/acme.sh --register-account 
    --server https://dv.acme-v02.api.pki.goog/directory
    --config-home '/etc/acme.sh/your-valid-email@example.com'
    -m 'your-valid-email@example.com'
    --eab-kid '[PASTE_YOUR_NEW_EAB_KID]'
    --eab-hmac-key '[PASTE_YOUR_NEW_EAB_HMAC_KEY]'

  4. This command succeeds immediately. After restarting the container, it finds the pre-created account files and proceeds with certificate issuance normally.

6. Suggested Fix

The entrypoint script within the acme-companion image needs to be modified. The logic responsible for building the acme.sh --register-account command must be updated to ensure the contact email (-m or --accountemail) is always included as a parameter whenever ACME_EAB_KID and ACME_EAB_HMAC_KEY are present.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions