A secure PDF viewer component for React. Uses canvas-only rendering to prevent XSS attacks from malicious PDF files.
Standard PDF viewers that render text layers and annotation layers into the DOM are vulnerable to XSS attacks embedded in crafted PDF files. This component renders PDF pages exclusively to <canvas> elements, eliminating all DOM injection vectors.
npm install secure-pdf-viewer-react pdfjs-distimport { SecurePdfViewer } from 'secure-pdf-viewer-react';
function App() {
return (
<div style={{ width: '100%', height: '100vh' }}>
<SecurePdfViewer src="https://example.com/document.pdf" />
</div>
);
}import { useState } from 'react';
import { SecurePdfViewer } from 'secure-pdf-viewer-react';
function App() {
const [file, setFile] = useState<File | undefined>();
return (
<div>
<input
type="file"
accept=".pdf"
onChange={(e) => setFile(e.target.files?.[0])}
/>
{file && <SecurePdfViewer file={file} />}
</div>
);
}import { SecurePdfViewer } from 'secure-pdf-viewer-react';
function App({ pdfData }: { pdfData: ArrayBuffer }) {
return <SecurePdfViewer data={pdfData} />;
}import { useRef } from 'react';
import { SecurePdfViewer, SecurePdfViewerRef } from 'secure-pdf-viewer-react';
function App() {
const viewerRef = useRef<SecurePdfViewerRef>(null);
const jumpToPage5 = () => viewerRef.current?.goToPage(5);
const getInfo = () => console.log(viewerRef.current?.getState());
return (
<div>
<button onClick={jumpToPage5}>Go to Page 5</button>
<button onClick={getInfo}>Log State</button>
<SecurePdfViewer ref={viewerRef} src="/document.pdf" />
</div>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
src |
string |
— | URL of the PDF file |
file |
File |
— | File object (from <input type="file">) |
data |
ArrayBuffer | Uint8Array |
— | Raw PDF data |
initialScale |
number |
1.0 |
Initial zoom level |
minScale |
number |
0.25 |
Minimum zoom level |
maxScale |
number |
5.0 |
Maximum zoom level |
showToolbar |
boolean |
true |
Show the built-in toolbar |
className |
string |
'' |
CSS class for the container |
style |
CSSProperties |
— | Inline styles for the container |
workerSrc |
string |
— | Custom path to pdf.worker.min.mjs |
pixelRatio |
number |
devicePixelRatio |
Device pixel ratio for rendering |
disableDownload |
boolean |
false |
Disable the download button |
Note: Provide exactly one of
src,file, ordata.
| Callback | Signature | Description |
|---|---|---|
onLoadStateChange |
(state: 'idle' | 'loading' | 'ready' | 'error') => void |
Fires when load state changes |
onPageChange |
(page: number, totalPages: number) => void |
Fires when the current page changes |
onScaleChange |
(scale: number) => void |
Fires when the zoom level changes |
onError |
(error: Error) => void |
Fires when an error occurs |
Access these via a React ref (useRef<SecurePdfViewerRef>):
| Method | Signature | Description |
|---|---|---|
goToPage |
(page: number) => void |
Navigate to a specific page |
setScale |
(scale: number) => void |
Set the zoom level |
getState |
() => { currentPage, totalPages, scale } |
Get current viewer state |
This component enforces multiple layers of security:
- Canvas-only rendering — PDF pages are rasterized to
<canvas>. NotextLayerorannotationLayerDOM elements are created, eliminating all XSS injection vectors. - JavaScript execution disabled —
isEvalSupported: falseprevents PDF.js from executing any JavaScript embedded in PDF files. - External resource blocking —
disableAutoFetch: trueblocks external resource loading, preventing SSRF attacks. - Font injection prevention —
disableFontFace: trueblocks@font-faceCSS injection from PDF fonts.
For production use, place pdf.worker.min.mjs from the pdfjs-dist package in your public directory and pass its path via the workerSrc prop:
<SecurePdfViewer
src="/document.pdf"
workerSrc="/pdf.worker.min.mjs"
/>This avoids relying on the CDN fallback and ensures CSP compliance.
| Key | Action |
|---|---|
| Arrow Left / Up | Previous page |
| Arrow Right / Down | Next page |
Ctrl + + |
Zoom in |
Ctrl + - |
Zoom out |
MIT - see LICENSE for details.