Skip to content

[e-signature] Race condition in ICP-Brasil policy cache — concurrent calls trigger multiple downloads #16

Description

@Yorizel

Summary

The module-level cachedPolicyData variable is checked before each policy fetch, but multiple concurrent callers can all pass the null check before any of them has resolved and written the cache, triggering redundant parallel downloads.

Root Cause

icp-brasil.ts:145-147:

if (cachedPolicyData) {
    return cachedPolicyData;
}
// ... await fetch(...)   ← multiple callers reach here simultaneously
cachedPolicyData = { ... };

JavaScript's event loop means the await fetch(...) yields control. Two concurrent calls both read cachedPolicyData === null, both proceed to fetch, and both write the result. Not a data-corruption bug (last write wins with same data), but causes unnecessary network traffic.

Affected Files

  • libraries/e-signature/src/icp-brasil.ts:145-201 — unguarded concurrent fetch

Evidence

// Concurrent batch signing with pades-icp-brasil:
await Promise.all([
  signPdf(pdf1, { policy: "pades-icp-brasil", ... }),
  signPdf(pdf2, { policy: "pades-icp-brasil", ... }),
]);
// Both calls reach downloadAndParsePolicyDocument simultaneously
// Both see cachedPolicyData === null
// Both fetch the policy document

Suggested Fix

  • Replace the null check with an in-flight promise lock:
    let inflight: Promise<{ hashAlgOid: string; policyHash: Uint8Array }> | null = null;
    
    async function downloadAndParsePolicyDocument() {
      if (cachedPolicyData) return cachedPolicyData;
      if (!inflight) {
        inflight = fetchAndParse().finally(() => { inflight = null; });
      }
      return inflight;
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions