Skip to content

ReceiptUtility.extractTransactionIdFromAppReceipt throws "too short ASN.1 value" on Xcode receipts with jsrsasign >= 11.1.2 #417

Description

@Forbiddem

Summary

A fresh install of @apple/app-store-server-library@3.1.0 resolves jsrsasign to 11.1.3 (the package declares "jsrsasign": "^11.0.0"). With jsrsasign >= 11.1.2, ReceiptUtility.extractTransactionIdFromAppReceipt() throws Error: too short ASN.1 value when parsing Xcode-generated app receipts (indefinite-length ASN.1 encoding). Production App Store receipts (definite-length) are unaffected.

The repository CI passes because the committed yarn.lock pins jsrsasign to 11.1.1; that lockfile is not delivered to consumers, so end users who install the library today get the broken 11.1.3.

Reproduction

mkdir repro && cd repro && npm init -y
npm install @apple/app-store-server-library@3.1.0
node -e "console.log('jsrsasign:', require('jsrsasign/package.json').version)"
# -> jsrsasign: 11.1.3
const { ReceiptUtility } = require('@apple/app-store-server-library');
const fs = require('fs');
// tests/resources/xcode/xcode-app-receipt-with-transaction from this repo
const receipt = fs.readFileSync('xcode-app-receipt-with-transaction', 'utf8').trim();
new ReceiptUtility().extractTransactionIdFromAppReceipt(receipt);
// -> Error: too short ASN.1 value

The two existing Xcode receipt unit tests fail on a fresh install:

● Receipt Utility Tets › should not extract a transaction id from an xcode receipt without a transaction
● Receipt Utility Tets › should extract a transaction id from an xcode receipt with a transaction

  receipt_utility.ts:41
    let receiptInfo = ASN1HEX.getVbyList(Buffer.from(appReceipt, 'base64').toString('hex'), 0, [1, 0, 2, 1, 0])
  at Object.ASN1HEX.getChildIdx (node_modules/jsrsasign/lib/jsrsasign.js)

Version bisect

jsrsasign tests/unit-tests/receipt_utility.test.ts
11.1.1 3/3 pass
11.1.2 2 fail (both Xcode receipt cases)
11.1.3 2 fail (both Xcode receipt cases)

Root cause

jsrsasign 11.1.2 tightened ASN.1 length validation in ASN1HEX (a stricter "too short ASN.1 value" check in the getChildIdx code path). ReceiptUtility.extractTransactionIdFromAppReceipt() handles the indefinite-length encoding (80 00) used by Xcode receipts by monkey-patching ASN1HEX.getVblen and ASN1HEX.getLblen. The new strict check in 11.1.2+ is reached on a code path that those two patched functions no longer compensate for, so parsing throws instead of completing.

Impact

extractTransactionIdFromAppReceipt() is a documented public API. On a fresh install it fails for Xcode / StoreKit local-testing receipts, which breaks local IAP testing workflows for consumers of the library. This is a functional/compatibility regression, not a security issue.

Possible fixes

  • Pin jsrsasign to the last known-good version: "jsrsasign": "11.1.1" (also the version where the prior jsrsasign advisories were fixed). Simple, but blocks future patch updates.
  • Update receipt_utility.ts so the indefinite-length handling stays compatible with jsrsasign >= 11.1.2, then raise the floor accordingly.

Happy to open a PR for whichever direction the maintainers prefer.

Environment

  • @apple/app-store-server-library: 3.1.0
  • jsrsasign: 11.1.3 (resolved from declared ^11.0.0)
  • Node.js: v22.x (also reproduced on v24.x)

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