BentoPDF is a PDF toolkit that does all its work inside your browser. Merge, split, reorder, compress, rotate, sign, watermark, redact, add page numbers, run OCR, and convert to and from Word, Excel, images, Markdown and ebook formats, more than 50 tools in all, without uploading a single file to a server.
That makes it a private alternative to the free PDF websites most people use, and you can use it at bentopdf.com or host your own copy with one Docker command. Self-hosting suits teams that handle contracts, medical or financial files, and it can be set up for air-gapped networks, with custom branding and individual tools switched off.
It is AGPL-3.0, with about 16,150 stars and 78 contributors, at v2.8.10 when scanned. The heavier tools rely on WebAssembly builds of PyMuPDF, Ghostscript and LibreOffice that load from the jsDelivr CDN by default, so the first use of those tools downloads large files.
- Repository: github.com/alam00000/bentopdf
- Licence: AGPL-3.0 (GNU Affero General Public License v3.0)
- Language: JavaScript. Stars: 16.1K. Forks: 1,437. Last push: Oct 26, 2026.
- Scan: safe, Oct 26, 2026, commit 7abb219
Who it is for
Anyone who edits PDFs and would rather not upload them to a stranger's website, and IT teams that want an internal PDF tool for staff.
Getting started
1. Run the self-hosted build in Docker
docker run -p 3000:8080 ghcr.io/alam00000/bentopdf-simple:latest2. Open it in your browser
http://localhost:3000Podman works with the same image, and the image is also on Docker Hub as bentopdfteam/bentopdf-simple. For offline networks, scripts/prepare-airgap.sh bundles the WASM files so nothing loads from a CDN.
Safety scan
We cloned alam00000/bentopdf at commit 7abb219 on Oct 26, 2026 and ran the checks described on the GitHub Tools page: credential patterns, decode-and-execute code, install-time scripts, committed binaries, risky CI workflows, every host the code talks to, known vulnerabilities in pinned dependencies, and project hygiene. A person read every hit. This is what we found.
- No secrets and no suspicious patterns across 4,822 files and about 833,000 lines, most of it translations and bundled PDF.js viewer assets. The one binary is a small ICC colour profile used by the PDF.js viewer.
- The single bare-IP URL is in cloudflare/cors-proxy-worker.js, which queries Cloudflare's 1.1.1.1 DNS-over-HTTPS service. That optional worker is only needed for the Digital Signature tool, to fetch certificate chains that lack CORS headers.
- 12 known advisories (5 high) in package-lock.json, none critical. Some are build tooling (Vite); others, such as node-forge and the xlsx library, ship in the browser bundle, where they work on files you open yourself.
- PyMuPDF, Ghostscript and CoherentPDF are loaded at runtime from jsDelivr by default. Your files stay in the browser either way, but self-hosters who want no third-party requests can point those URLs at their own server.
- 10 workflows, all 21 third-party actions pinned to commits. The one pull_request_target workflow is the CLA assistant, which never checks out PR code. Security policy, Dependabot and CodeQL are all present.
What the scanner counted
| Check | Result |
|---|---|
| Secrets | None found. |
| Suspicious code | None found. |
| Install-time code | 1 npm lifecycle script |
| Committed binaries | 1 executable or compiled object committed; listed under the raw findings. |
| CI workflows | 10 workflows. 1 uses pull_request_target, none check out the pull request head. 0 of 21 third-party actions pinned to a tag rather than a commit. |
| Network hosts | 35 distinct hosts referenced from source; most often cdn.jsdelivr.net, rawcdn.githack.com, internal.example.com, www.bentopdf.com. 1 URL to a bare IP address, listed under the raw findings. |
| Known vulnerabilities | 12 advisories across 963 pinned packages: 0 critical, 5 high, 5 moderate, 2 low. package-lock.json: 1,003 packages, 12 advisories. |
| Project hygiene | Has security policy, automated dependency updates, CodeQL, licence file, contributing guide. |
| OpenSSF Scorecard | Not scored: the project is not in Scorecard's weekly index. |
The raw findings
Every hit the scanner wrote out, with a link to the exact line at the scanned commit. Secrets candidates are redacted.
URLs to bare IP addresses (1)
| Where | Rule | Match |
|---|---|---|
| cloudflare/cors-proxy-worker.js:216 | ip-literal-url | `https://1.1.1.1/dns-query?name=${encodeURIComponent(clean)}&type=${type}`, |
npm lifecycle scripts (1)
package.jsonprepare:husky
Committed binaries (1)
public/pdfjs-viewer/iccs/CGATS001Compat-v2-micro.icc: .icc, 8 KB
Worst known vulnerabilities (12 of 12)
| Advisory | Severity | Package | Summary |
|---|---|---|---|
| GHSA-86w9-cpqp-85rv | high | node-forge@1.4.0 | node-forge RSA PKCS#1 v1.5 signature verification accepts extra nested DigestAlgorithm elements |
| GHSA-587h-7wmj-h5pm | high | vite@5.4.21 | launch-editor: `fs.existsSync()` existence check can be bypassed on Windows |
| GHSA-fx2h-pf6j-xcff | high | vite@5.4.21 | vite: `server.fs.deny` bypass on Windows alternate paths |
| GHSA-4r6h-8v6p-xvw6 | high | xlsx@0.20.3 | Prototype Pollution in sheetJS |
| GHSA-5pgg-2g8v-p4x9 | high | xlsx@0.20.3 | SheetJS Regular Expression Denial of Service (ReDoS) |
| GHSA-4w7w-66w2-5vf9 | moderate | vite@5.4.21 | Vite Vulnerable to Path Traversal in Optimized Deps `.map` Handling |
| GHSA-698v-4r3x-3vcv | moderate | vite@5.4.21 | launch-editor: escapeCmdArgs() omits % escaping on Windows |
| GHSA-r825-w8mm-5pxw | moderate | vite@5.4.21 | launch-editor: Editor CLI flag misinterpretation causing arbitrary command execution for some editors |
| GHSA-rq7h-c2jc-7f22 | moderate | vite@5.4.21 | Vite: Files outside `server.fs.allow` could be served when project paths match system paths on non-Windows machine |
| GHSA-v6wh-96g9-6wx3 | moderate | vite@5.4.21 | launch-editor: NTLMv2 hash disclosure via UNC path handling on Windows |
| GHSA-848j-6mx2-7j84 | low | elliptic@6.6.1 | Elliptic Uses a Cryptographic Primitive with a Risky Implementation |
| GHSA-9jrq-w75r-8gcw | low | vite@5.4.21 | Vite: Cross origin script execution through Vite custom middleware |
Workflows worth a look
- .github/workflows/cla.yml: pull_request_target
By the numbers
| Stars | 16.1K |
|---|---|
| Forks | 1,437 |
| Contributors | 78 |
| Commits | 1,143 |
| Open issues | 127 |
| Open pull requests | 44 |
| Releases | 60 |
| Latest release | v2.8.10 |
| Licence | AGPL-3.0 |
| Main language | JavaScript |
| Project age | 1 year |
| Last push | Oct 26, 2026 |
| Tracked files | 4,822 |
| Lines of code | 832.8K |
| Checkout size | 218 MB |
Lines by language: JSON 237.2K, Markdown 227.2K, JavaScript 150.7K, TypeScript 104.4K, HTML 82.7K, CSS 27.6K.
Questions
Is BentoPDF free?
Yes, under AGPL-3.0, both at bentopdf.com and self-hosted. If you build it into a closed-source product, a commercial licence costs $79 once.
Does BentoPDF upload my files?
No. Processing happens in your browser with JavaScript and WebAssembly, so documents never reach a server. The browser does download the processing libraries themselves, from jsDelivr by default.
Can I run BentoPDF without internet access?
Yes. The air-gapped setup in the README packages the Docker image and all WASM files together, and serves them from your own network.
This post is part of GitHub Tools, where every repository is cloned and scanned before it is written up. The scan is a snapshot of one commit on one day; the repository has moved on since, so check it before you install.
