[GH-ISSUE #6603] [Bug] APK v1 inspection discards signer facts for a valid constructed BER signature #3989

Closed
opened 2026-10-31 00:45:50 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6603

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

inspect-apk-signature returns a v1 signer with certificate: null, certificates: [], and signer_infos: [] when its PKCS#7 SignerInfo signature uses a constructed BER OCTET STRING. The error is:

malformed PKCS#7: signerInfo 0 signature has tag 0x24, expected 0x4

The primitive-encoding control reports both embedded certificates and the named leaf signer. OpenSSL parses all three encodings into byte-identical normalized CMS output. This concerns static format compatibility and declared identity, not signature verification.

Reproduction

Executed once per case, through both ApkSignatureProvider.inspect and the public CLI:

  1. Take OPENSSL_BLOCK_ISSUER_SERIAL from tests/fixtures/apkSignature/v1SignatureBlock.ts.
  2. Preserve its certificate, signer identifier, algorithms, and signature bytes. At ContentInfo child path [1,0,4,0,4], replace the primitive signature 04 46 <70 bytes> with 24 4a 04 23 <first 35 bytes> 04 23 <last 35 bytes>, updating enclosing lengths. Also test the equivalent indefinite form 24 80 04 23 <first 35> 04 23 <last 35> 00 00.
  3. Use the same fixture's zipWith to store each block as META-INF/CERT.RSA, alongside META-INF/CERT.SF and META-INF/MANIFEST.MF.
  4. Run node scripts/rea.mjs inspect-apk-signature /artifacts/constructed.zip --json and inspect normalized_result.schemes.v1.signers[0].

The retained executable probe constructs all three files, calls the provider and CLI, and saves the complete results. No Android code executes.

Expected behavior

Preserve the same declared certificate and SignerInfo facts for the equivalent encodings, or accurately identify an intentionally unsupported encoding without calling valid BER malformed. RFC 2315 specifies BER for PKCS#7. REA's APK signature guide advertises PKCS#7 signer inspection and acceptance of BER indefinite lengths.

Impact and scope

Two structurally valid encoding variants lose all signer/certificate facts in the tested static reader; the primitive control succeeds. APK prevalence and Android/apksigner verification acceptance were not tested. These reduced ZIPs exercise declared-field inspection only; their manifest/signature-file contents are synthetic and no cryptographic validity is claimed. OpenSSL provides an observed alternative for reading the CMS fields, but no same-artifact REA workaround was demonstrated.

REA version

Main source aee249b1ddb3e643b22ce049909160f0ce37a63e, with its compiled CLI. Main-only: the 6.7.0 release tree at 27dc42d10249f0410904a75c0997842eb03b931c has no APK signature reader; release runtime was not tested.

Runtime and platform

Node.js v24.22.1, Linux x64; OpenSSL 3.6.5. No Android SDK, device, Hopper, or Ghidra used.

Target and artifact context

Three inert ZIPs containing the same two X.509 certificates and SignerInfo. Only the signature OCTET STRING encoding and enclosing lengths differ.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Signature encoding Named certificate SHA-256 Certificates / SignerInfos Decode error
Primitive 9224e30fd7981ebeb903d2593075845316d5c4f546c2f3e4675c03ef3302ef88 2 / 1 null
Constructed definite null 0 / 0 signature has tag 0x24, expected 0x4
Constructed indefinite null 0 / 0 same

Every CLI call exited 0 and retained the corresponding per-signer result. openssl cms -cmsout -inform DER -in block.p7 -print succeeded for each; all three normalized outputs have SHA-256 c81ff6bea05b181364b70bb754b8c30134749ddee3ff3b1471dfedb99e807058.

Source-derived cause: apkV1SignatureBlock.ts:330 requires the complete tag byte 0x04; constructed OCTET STRING uses 0x24. The adapter converts that rejection into malformed PKCS#7 and discards the block's decoded fields.

Evidence provenance: executed production provider, public CLI, and independent CMS parser. MCP transport, Android trust behavior, and real-world frequency remain untested.

Typed outcome or recovery expected

Report the declared signer facts, or a precise unsupported-encoding limitation rather than a malformed-PKCS#7 diagnosis.

Analysis or suspected cause

Source-derived as described above; no source changes made.

Additional context

Duplicate searches across open and closed issues: "constructed octet", "0x24" "signature", "constructed" "v1", and "OCTET STRING" "APK" found no matching report. #6574 concerns a different PE parser rejecting an indefinite outer envelope; this report concerns an APK SignerInfo field after a supported envelope has decoded. #6439 concerns different issuer string encodings and does not require a constructed signature.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: Both executed constructed-encoding cases lose the complete declared signer/certificate inventory through the production provider and CLI, while the primitive control and independent BER parser retain it.
  • Workaround status: unverified
  • Workaround basis: OpenSSL reads the standalone CMS fields, but a same-artifact REA workflow preserving the selected ZIP's identity and signer evidence was not demonstrated.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6603 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior `inspect-apk-signature` returns a v1 signer with `certificate: null`, `certificates: []`, and `signer_infos: []` when its PKCS#7 SignerInfo signature uses a constructed BER OCTET STRING. The error is: ```text malformed PKCS#7: signerInfo 0 signature has tag 0x24, expected 0x4 ``` The primitive-encoding control reports both embedded certificates and the named leaf signer. OpenSSL parses all three encodings into byte-identical normalized CMS output. This concerns static format compatibility and declared identity, not signature verification. ### Reproduction Executed once per case, through both `ApkSignatureProvider.inspect` and the public CLI: 1. Take `OPENSSL_BLOCK_ISSUER_SERIAL` from `tests/fixtures/apkSignature/v1SignatureBlock.ts`. 2. Preserve its certificate, signer identifier, algorithms, and signature bytes. At ContentInfo child path `[1,0,4,0,4]`, replace the primitive signature `04 46 <70 bytes>` with `24 4a 04 23 <first 35 bytes> 04 23 <last 35 bytes>`, updating enclosing lengths. Also test the equivalent indefinite form `24 80 04 23 <first 35> 04 23 <last 35> 00 00`. 3. Use the same fixture's `zipWith` to store each block as `META-INF/CERT.RSA`, alongside `META-INF/CERT.SF` and `META-INF/MANIFEST.MF`. 4. Run `node scripts/rea.mjs inspect-apk-signature /artifacts/constructed.zip --json` and inspect `normalized_result.schemes.v1.signers[0]`. The retained executable probe constructs all three files, calls the provider and CLI, and saves the complete results. No Android code executes. ### Expected behavior Preserve the same declared certificate and SignerInfo facts for the equivalent encodings, or accurately identify an intentionally unsupported encoding without calling valid BER malformed. [RFC 2315](https://www.rfc-editor.org/rfc/rfc2315.html#section-1) specifies BER for PKCS#7. [REA's APK signature guide](https://github.com/morluto/rea/blob/aee249b1ddb3e643b22ce049909160f0ce37a63e/docs/apk-signature.md) advertises PKCS#7 signer inspection and acceptance of BER indefinite lengths. ### Impact and scope Two structurally valid encoding variants lose all signer/certificate facts in the tested static reader; the primitive control succeeds. APK prevalence and Android/apksigner verification acceptance were not tested. These reduced ZIPs exercise declared-field inspection only; their manifest/signature-file contents are synthetic and no cryptographic validity is claimed. OpenSSL provides an observed alternative for reading the CMS fields, but no same-artifact REA workaround was demonstrated. ### REA version Main source `aee249b1ddb3e643b22ce049909160f0ce37a63e`, with its compiled CLI. Main-only: the `6.7.0` release tree at `27dc42d10249f0410904a75c0997842eb03b931c` has no APK signature reader; release runtime was not tested. ### Runtime and platform Node.js v24.22.1, Linux x64; OpenSSL 3.6.5. No Android SDK, device, Hopper, or Ghidra used. ### Target and artifact context Three inert ZIPs containing the same two X.509 certificates and SignerInfo. Only the signature OCTET STRING encoding and enclosing lengths differ. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence | Signature encoding | Named certificate SHA-256 | Certificates / SignerInfos | Decode error | | --- | --- | --- | --- | | Primitive | `9224e30fd7981ebeb903d2593075845316d5c4f546c2f3e4675c03ef3302ef88` | 2 / 1 | null | | Constructed definite | null | 0 / 0 | `signature has tag 0x24, expected 0x4` | | Constructed indefinite | null | 0 / 0 | same | Every CLI call exited 0 and retained the corresponding per-signer result. `openssl cms -cmsout -inform DER -in block.p7 -print` succeeded for each; all three normalized outputs have SHA-256 `c81ff6bea05b181364b70bb754b8c30134749ddee3ff3b1471dfedb99e807058`. Source-derived cause: [`apkV1SignatureBlock.ts:330`](https://github.com/morluto/rea/blob/aee249b1ddb3e643b22ce049909160f0ce37a63e/src/domain/apkSignature/apkV1SignatureBlock.ts#L330) requires the complete tag byte `0x04`; constructed OCTET STRING uses `0x24`. The adapter converts that rejection into `malformed PKCS#7` and discards the block's decoded fields. Evidence provenance: executed production provider, public CLI, and independent CMS parser. MCP transport, Android trust behavior, and real-world frequency remain untested. ### Typed outcome or recovery expected Report the declared signer facts, or a precise unsupported-encoding limitation rather than a malformed-PKCS#7 diagnosis. ### Analysis or suspected cause Source-derived as described above; no source changes made. ### Additional context Duplicate searches across open and closed issues: `"constructed octet"`, `"0x24" "signature"`, `"constructed" "v1"`, and `"OCTET STRING" "APK"` found no matching report. #6574 concerns a different PE parser rejecting an indefinite outer envelope; this report concerns an APK SignerInfo field after a supported envelope has decoded. #6439 concerns different issuer string encodings and does not require a constructed signature. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: Both executed constructed-encoding cases lose the complete declared signer/certificate inventory through the production provider and CLI, while the primitive control and independent BER parser retain it. - Workaround status: unverified - Workaround basis: OpenSSL reads the standalone CMS fields, but a same-artifact REA workflow preserving the selected ZIP's identity and signer evidence was not demonstrated.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3989
No description provided.