Repository navigation
keys-sync can approve key groups without a compliant signer; validation is not bound to release signing #10
Description
What's broken
keys-sync Step 1 validates the primary public key without checking signing subkeys or requiring a usable signing-capable key.
An accepted certify-only primary can therefore produce verdict: proceed when:
- Its only signing subkey is below the helper’s existing strength floor.
- Its signing subkeys are already unusable.
- The key group has no signing capability.
There is also a workflow gap: the RM-key flow in rc-cut emits gpg --detach-sign --armor <artefact> without explicitly selecting the key validated by keys-sync. Checking a key group therefore does not establish that the eventual signature uses a checked signer. See the current signing recipe.
Which layer
The keys-sync deterministic helper, and the relationship between public-key admission, release signing and signature verification.
The demonstrated helper defect and the broader workflow proposal are distinguished below.
How to reproduce
Run the unpatched helper with Python 3.11+ and GPG on Linux. This example uses disposable keys in an isolated keyring.
set -euo pipefail
test_home=$(mktemp -d)
chmod 700 "$test_home"
trap 'gpgconf --homedir "$test_home" --kill gpg-agent; rm -rf -- "$test_home"' EXIT
gpg --homedir "$test_home" --batch \
--pinentry-mode loopback --passphrase '' \
--quick-gen-key 'Example RM <rm@example.invalid>' ed25519 cert never
fingerprint=$(gpg --homedir "$test_home" --with-colons --list-keys \
| awk -F: '$1 == "fpr" {print $10; exit}')
gpg --homedir "$test_home" --batch \
--pinentry-mode loopback --passphrase '' \
--quick-add-key "$fingerprint" rsa1024 sign 1d
gpg --homedir "$test_home" --armor --export "$fingerprint" \
> "$test_home/public.asc"
python3 plugins/magpie-release-management/skills/keys-sync/scripts/check_key.py \
--key-file "$test_home/public.asc" --fingerprint "$fingerprint"Actual result: verdict: proceed and strength_check: pass, although the only signer is RSA-1024 and falls below the helper’s existing floor.
Omitting the --quick-add-key command produces the same admission result with no signing-capable key at all.
Expected vs actual
A primary-key strength check should not be treated as evidence that a release signer is usable and compliant.
The policy for a group containing both a compliant signer and an active weak signer is a separate design choice. Rejecting that entire group should not be presented as an independently established ASF requirement. This report concerns enforcement of the helper’s existing rules; changes to algorithm thresholds are a separate discussion. ASF signing guidance
Two possible approaches
Option 1 — Conservative key-group validation, proposed by GPT/Codex
A reference implementation is available in fork Draft PR #9.
It preserves the primary-key checks, requires at least one usable compliant signer, and checks every usable signing subkey against the existing rules. An active weak signing subkey blocks admission. Retired subkeys do not block a compliant replacement.
Advantages: smaller scope, stable CLI/JSON interfaces, and an implemented repair for the demonstrated helper false positives.
Tradeoffs: it rejects a mixed group even when the RM intends to use only its compliant signer. It therefore does not match an actual-signer-only workflow. It also leaves the downstream signer-selection gap unresolved.
This is a conservative admission policy proposed by GPT/Codex, rather than a complete redesign of release signing.
Option 2 — Bind validation to the selected signer, proposed by the reporter
The reporter proposes the following workflow:
- Determine the exact primary key or signing subkey intended for the release.
- Validate that signer and its relationship to the expected RM key group.
- Sign using that same selected key.
- Verify the signature and confirm that the actual signer matches the selection.
GPG supports forcing an exact key using a fingerprint followed by !. Its machine-readable status provides signer fingerprints, but cryptographic validity must also be evaluated with expiry and revocation results. These are possible implementation building blocks, not a prescribed design. GPG key selection, GPG signature status
Advantages: this more closely matches the reporter’s normal release workflow. A compliant selected signer could be accepted despite another unused weak signing subkey.
Tradeoffs: it requires broader coordination of configuration, signing recipes, verification, key rotation and regression coverage. Primary-key identity, validity and applicable strength requirements must still be preserved. Signing and private-key custody would remain with the RM.
This approach has not been implemented or tested. The reporter prefers it on workflow grounds, while leaving the final design—and whether to adopt Option 1 first—to the maintainers.
Could you please take a look and determine which solution is better for the repair? Or if there's an even better solution I haven't considered, I'd really appreciate your idea.
Acceptance criteria for discussion
- A group without a usable compliant signer must not receive an admission pass.
- An unusable primary must remain blocked.
- GPG’s already-expired status must be respected on the expiry date; an earlier date override must not reactivate it.
- Retired weak subkeys must not block a compliant replacement.
- The mixed active strong/weak case must have an explicit policy: Option 1 rejects the group; Option 2 permits a compliant selected signer only when its use is enforced and verified.
- Under Option 2, a different actual signer or failed verification must block staging or publication.
- The agent must continue to handle public information only; the RM retains signing-key custody.
Environment and supporting evidence
The helper defect was reproduced with Python 3.12 and GPG 2.2.40 using isolated disposable keys. The helper at upstream commit 0a1f044e has the same Git blob as the reproduced fork base 4556f693.
Option 1’s reference implementation at ee5cc5b7 passed 61 keys-sync tests on Windows, 240 sibling-script tests on Linux, nine saved real-GPG listing replays and 11 additional boundary checks. Its 11 remote CI checks succeeded. The full model-eval suite is not all green; that limitation remains disclosed in the PR.
Related material: fork issue #8 and fork Draft PR #9. This new discussion does not automatically close either.
The separate existing Windows/MSYS GPG import compatibility problem is outside this issue.
AI disclosure: This issue text was jointly written by the reporter and OpenAI Codex (GPT-6). Option 1 and its reference implementation were proposed/generated by Codex; Option 2 and the request for maintainer feedback were contributed by the reporter. The final wording awaits the reporter’s review.
Activity