Skip to content

Commit edcd0d0

Browse files
committed
fix: harden pdf.js worker copy and drop ineffective CSP directive
1 parent eb5c435 commit edcd0d0

3 files changed

Lines changed: 45 additions & 18 deletions

File tree

public/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
All file processing happens client-side; the only outbound traffic is
1515
Google Fonts (CSS + woff2/ttf) used for the UI and the PDF generator.
1616
-->
17-
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; img-src 'self' data: blob:; connect-src 'self' https://fonts.gstatic.com; worker-src 'self' blob:; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" />
17+
<!-- frame-ancestors is intentionally omitted; browsers ignore it in <meta> CSP. -->
18+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; img-src 'self' data: blob:; connect-src 'self' https://fonts.gstatic.com; worker-src 'self' blob:; base-uri 'self'; form-action 'self'" />
1819
<!-- Google Fonts -->
1920
<link rel="preconnect" href="https://fonts.googleapis.com">
2021
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

scripts/copy-pdf-worker.js

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,54 @@
11
// Copies the pdf.js worker into public/ at build/dev time so the app can serve
22
// it from its own origin instead of pulling it from a CDN at runtime.
3+
//
4+
// pdfjs-dist's layout has shifted across major versions, so we discover
5+
// whatever pdf.worker.* file exists rather than hardcoding one name.
36
const fs = require('fs');
47
const path = require('path');
58

6-
const candidates = [
7-
'pdf.worker.min.mjs',
8-
'pdf.worker.mjs',
9-
'pdf.worker.min.js',
10-
'pdf.worker.js',
9+
const root = path.join(__dirname, '..');
10+
const searchDirs = [
11+
path.join(root, 'node_modules', 'pdfjs-dist', 'build'),
12+
path.join(root, 'node_modules', 'pdfjs-dist', 'legacy', 'build'),
1113
];
1214

13-
const fromDir = path.join(__dirname, '..', 'node_modules', 'pdfjs-dist', 'build');
14-
const toDir = path.join(__dirname, '..', 'public');
15+
// Higher = better. We prefer the minified .mjs, then any .mjs, then .min.js,
16+
// then .js. Only files starting with `pdf.worker` are considered.
17+
function score(name) {
18+
if (!name.startsWith('pdf.worker')) return -1;
19+
if (name.endsWith('.min.mjs')) return 4;
20+
if (name.endsWith('.mjs')) return 3;
21+
if (name.endsWith('.min.js')) return 2;
22+
if (name.endsWith('.js')) return 1;
23+
return 0;
24+
}
25+
26+
let best = null;
27+
for (const dir of searchDirs) {
28+
if (!fs.existsSync(dir)) continue;
29+
for (const name of fs.readdirSync(dir)) {
30+
const s = score(name);
31+
if (s <= 0) continue;
32+
if (!best || s > best.score) {
33+
best = { dir, name, score: s };
34+
}
35+
}
36+
}
1537

16-
const found = candidates.find((name) => fs.existsSync(path.join(fromDir, name)));
17-
if (!found) {
18-
console.error('[copy-pdf-worker] no pdf.worker.* found in', fromDir);
38+
if (!best) {
39+
console.error(
40+
'[copy-pdf-worker] could not find pdf.worker.* in any of:\n ' +
41+
searchDirs.join('\n ') +
42+
'\nIs pdfjs-dist installed?'
43+
);
1944
process.exit(1);
2045
}
2146

22-
const src = path.join(fromDir, found);
23-
const dst = path.join(toDir, found);
24-
fs.mkdirSync(toDir, { recursive: true });
47+
const dstDir = path.join(root, 'public');
48+
// Always write to a deterministic name; runtime references this exact path.
49+
const dstName = 'pdf.worker.mjs';
50+
const src = path.join(best.dir, best.name);
51+
const dst = path.join(dstDir, dstName);
52+
fs.mkdirSync(dstDir, { recursive: true });
2553
fs.copyFileSync(src, dst);
26-
console.log(`[copy-pdf-worker] ${src} -> ${dst}`);
54+
console.log(`[copy-pdf-worker] ${path.relative(root, src)} -> ${path.relative(root, dst)}`);

src/hooks/usePdfHandler.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ import { extractAndMergeColors } from '../utils/colorExtractor';
1212

1313
// Use the worker copied to public/ at build time (see scripts/copy-pdf-worker.js)
1414
// so the app doesn't depend on a third-party CDN at runtime.
15-
const WORKER_BASENAME = 'pdf.worker.min.mjs';
16-
const WORKER_PUBLIC_PATH = `${process.env.PUBLIC_URL || ''}/${WORKER_BASENAME}`;
17-
pdfjsLib.GlobalWorkerOptions.workerSrc = WORKER_PUBLIC_PATH;
15+
pdfjsLib.GlobalWorkerOptions.workerSrc = `${process.env.PUBLIC_URL || ''}/pdf.worker.mjs`;
1816

1917
// Maximum file size allowed (25MB)
2018
const MAX_FILE_SIZE = 25 * 1024 * 1024;

0 commit comments

Comments
 (0)