secure-pdf-viewer-react
v1.0.0
Published
Secure PDF viewer for React - Canvas-only rendering prevents XSS attacks from malicious PDFs
Downloads
102
Maintainers
Readme
secure-pdf-viewer-react
A secure PDF viewer component for React. Uses canvas-only rendering to prevent XSS attacks from malicious PDF files.
Why?
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.
Installation
npm install secure-pdf-viewer-react pdfjs-distQuick Start
Load from URL
import { SecurePdfViewer } from 'secure-pdf-viewer-react';
function App() {
return (
<div style={{ width: '100%', height: '100vh' }}>
<SecurePdfViewer src="https://example.com/document.pdf" />
</div>
);
}Load from File Upload
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>
);
}Load from ArrayBuffer
import { SecurePdfViewer } from 'secure-pdf-viewer-react';
function App({ pdfData }: { pdfData: ArrayBuffer }) {
return <SecurePdfViewer data={pdfData} />;
}Using Ref Methods
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>
);
}Props
| 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.
Callbacks
| 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 |
Ref Methods
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 |
Security Features
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.
Worker Configuration
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.
Keyboard Shortcuts
| Key | Action |
|-----|--------|
| Arrow Left / Up | Previous page |
| Arrow Right / Down | Next page |
| Ctrl + + | Zoom in |
| Ctrl + - | Zoom out |
License
MIT - see LICENSE for details.
