Skip to content

fix(cdk): PDF attachment screening broken — ambient pdf-parse decl describes v1 API against installed v2 #683

Description

@scottschreckengaust

Discovered while reviewing PR #673 (#607). Pre-existing — landed in #434 (2026-06-30), not introduced by #673.

Symptom

PDF attachment screening fails for all `application/pdf` inputs. Every PDF is reported as `PDF "" could not be processed. It may be corrupt or use unsupported features.` — indistinguishable from a genuinely corrupt file, so the failure is silent.

Root cause

`cdk/src/types/pdf-parse.d.ts` is an ambient `declare module 'pdf-parse'` describing the v1 API:

```ts
function pdfParse(data: Buffer, options?: { max?: number }): Promise;
export = pdfParse;
```

The installed package is `pdf-parse@2.4.5`, which exports no callable default:

```
$ node -e "const m=require('pdf-parse'); console.log(Object.keys(m)); console.log(typeof m.default)"
[ 'AbortException', ..., 'PDFParse', 'VerbosityLevel', 'getException' ]
undefined
```

The ambient declaration overrides v2's real bundled types (`dist/pdf-parse/cjs/index.d.cts`), so `tsc` stays green against a shape that no longer exists. At runtime, in `cdk/src/handlers/shared/attachment-screening.ts`:

  • `pdfParseFn = (mod as any).default ?? mod` resolves to the module namespace object (no default export).
  • Calling `pdfParseFn(content, { max })` throws `TypeError: pdfParseFn is not a function`, which is caught and rewrapped as the generic "could not be processed" error.

The test at `cdk/test/handlers/shared/attachment-screening.test.ts:365` uses a `{ virtual: true }` mock supplying `{ __esModule: true, default: jest.fn() }` — a v1 shape that no longer exists — so the suite cannot catch this.

Fix

  • Delete `cdk/src/types/pdf-parse.d.ts` and let v2's own bundled types apply.
  • Rewrite the call site to the v2 API: `new PDFParse({ data: content }).getText()` returning a `TextResult`.
  • Replace the virtual mock with one reflecting the real v2 module (a `PDFParse` class with a `getText()` method), and add a test that exercises a real (small) PDF end-to-end so a future API mismatch fails loudly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginfra-cdkCDK stacks/constructs, bootstrap, deploy topology, tags, IAM wiring, teardownsecurityCedar/HITL, IAM least-privilege, secrets, PII/DLP, guardrails, supply-chain/CVE

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions