diff --git a/Dockerfile b/Dockerfile index a6eefff6..245e52a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,6 +19,8 @@ COPY . . # Pass SIMPLE_MODE environment variable if provided ARG SIMPLE_MODE=false ENV SIMPLE_MODE=$SIMPLE_MODE +ARG DISABLE_GITHUB_STARS=false +ENV DISABLE_GITHUB_STARS=$DISABLE_GITHUB_STARS ARG COMPRESSION_MODE=all ENV COMPRESSION_MODE=$COMPRESSION_MODE diff --git a/Dockerfile.nonroot b/Dockerfile.nonroot index 38f2bb82..aa16f550 100644 --- a/Dockerfile.nonroot +++ b/Dockerfile.nonroot @@ -19,6 +19,8 @@ COPY . . ARG SIMPLE_MODE=false ENV SIMPLE_MODE=$SIMPLE_MODE +ARG DISABLE_GITHUB_STARS=false +ENV DISABLE_GITHUB_STARS=$DISABLE_GITHUB_STARS ARG COMPRESSION_MODE=all ENV COMPRESSION_MODE=$COMPRESSION_MODE diff --git a/README.md b/README.md index 0c81ee36..83e64fe5 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ - [Commercial Build](#-commercial-build) - [Custom Branding](#-custom-branding) - [Disabling Specific Tools](#-disabling-specific-tools) + - [Disabling the GitHub Star Counter](#-disabling-the-github-star-counter) - [WASM Configuration](#wasm-configuration) - [Air-Gapped / Offline Deployment](#air-gapped--offline-deployment) - [Security Features](#-security-features) @@ -934,6 +935,24 @@ You can also disable specific features inside the PDF Editor (e.g., redaction, f For the full list of editor categories, see the [self-hosting docs](https://bentopdf.com/docs/self-hosting/docker#disabling-editor-features). +### 🔕 Disabling the GitHub Star Counter + +The navbar shows a live GitHub star count, fetched from `api.github.com` on page load. The only external request that isn't serving a PDF feature. Self-hosters who want zero non-essential network calls can disable it at build time. This removes the fetch code from the bundle entirely and drops `api.github.com` from the Content-Security-Policy. + +Simple Mode builds (`bentopdf-simple`) always skip the star counter — this flag is only needed on the Commercial build or custom full builds. + +**Docker:** + +```bash +docker build --build-arg DISABLE_GITHUB_STARS=true -t bentopdf . +``` + +**Building from source:** + +```bash +DISABLE_GITHUB_STARS=true npm run build +``` + ### 🔒 Security Features BentoPDF runs as a non-root user using nginx-unprivileged for enhanced security: diff --git a/docs/self-hosting/docker.md b/docs/self-hosting/docker.md index 2baff7f0..54f7297b 100644 --- a/docs/self-hosting/docker.md +++ b/docs/self-hosting/docker.md @@ -115,6 +115,7 @@ docker run -d -p 3000:8080 bentopdf:custom | `VITE_BRAND_LOGO` | Logo path relative to `public/` | `images/favicon-no-bg.svg` | | `VITE_FOOTER_TEXT` | Custom footer/copyright text | `© 2026 BentoPDF. All rights reserved.` | | `DISABLE_TOOLS` | Comma-separated tool IDs to hide | _(empty; all tools enabled)_ | +| `DISABLE_GITHUB_STARS` | Skip the GitHub star-count fetch on page load and drop `api.github.com` from the CSP. Simple Mode builds always skip it. | `false` | WASM module URLs are pre-configured with CDN defaults — all advanced features work out of the box. Override these for air-gapped or self-hosted deployments. @@ -263,6 +264,16 @@ You can also disable specific features inside the PDF Editor (e.g., redaction, a Categories are hierarchical — disabling a parent (e.g., `annotation`) disables all its children. +### Disabling the GitHub Star Counter + +The navbar shows a live GitHub star count, fetched from `api.github.com` on page load. The only external request that isn't serving a PDF feature. Disable it at build time to remove the fetch code from the bundle and drop `api.github.com` from the Content-Security-Policy: + +```bash +docker build --build-arg DISABLE_GITHUB_STARS=true -t bentopdf . +``` + +Simple Mode builds (`bentopdf-simple`) always skip the star counter — this flag is only needed on the Commercial build or custom full builds. + ### Custom WASM URLs (Air-Gapped / Self-Hosted) > [!IMPORTANT] diff --git a/scripts/generate-security-headers.mjs b/scripts/generate-security-headers.mjs index f8329566..dffc184c 100644 --- a/scripts/generate-security-headers.mjs +++ b/scripts/generate-security-headers.mjs @@ -56,6 +56,11 @@ const connectOrigins = uniq([ ]); const fontOrigins = uniq([ocrFontOrigin].filter(Boolean)); +const githubStarsDisabled = + process.env.DISABLE_GITHUB_STARS === 'true' || + process.env.SIMPLE_MODE === 'true'; +const githubApiSource = githubStarsDisabled ? '' : ' https://api.github.com'; + const directives = [ `default-src 'self'`, `script-src 'self' 'wasm-unsafe-eval' 'unsafe-eval' blob: ${scriptOrigins.join(' ')}`.trim(), @@ -63,7 +68,7 @@ const directives = [ `style-src 'self' 'unsafe-inline' https://fonts.googleapis.com`, `img-src 'self' data: blob: https:`, `font-src 'self' data: https://fonts.gstatic.com ${fontOrigins.join(' ')}`.trim(), - `connect-src 'self' blob: https://api.github.com https://fonts.gstatic.com ${connectOrigins.join(' ')}`.trim(), + `connect-src 'self' blob:${githubApiSource} https://fonts.gstatic.com ${connectOrigins.join(' ')}`.trim(), `object-src 'none'`, `base-uri 'self'`, `frame-src 'self' blob:`, @@ -77,7 +82,7 @@ const docsDirectives = [ `style-src 'self' 'unsafe-inline' https://fonts.googleapis.com`, `img-src 'self' data: blob: https:`, `font-src 'self' data: https://fonts.gstatic.com ${fontOrigins.join(' ')}`.trim(), - `connect-src 'self' https://api.github.com https://fonts.gstatic.com ${connectOrigins.join(' ')}`.trim(), + `connect-src 'self'${githubApiSource} https://fonts.gstatic.com ${connectOrigins.join(' ')}`.trim(), `object-src 'none'`, `base-uri 'self'`, `frame-ancestors 'self'`, diff --git a/src/js/main.ts b/src/js/main.ts index 78d4c41d..755aae23 100644 --- a/src/js/main.ts +++ b/src/js/main.ts @@ -545,7 +545,11 @@ const init = async () => { document.getElementById('github-stars-mobile'), ]; - if (githubStarsElements.some((el) => el) && !__SIMPLE_MODE__) { + if ( + githubStarsElements.some((el) => el) && + !__SIMPLE_MODE__ && + !__DISABLE_GITHUB_STARS__ + ) { fetch('https://api.github.com/repos/alam00000/bentopdf') .then((response) => response.json()) .then((data) => { diff --git a/src/types/globals.d.ts b/src/types/globals.d.ts index e2b983e0..2a2b08ad 100644 --- a/src/types/globals.d.ts +++ b/src/types/globals.d.ts @@ -13,4 +13,5 @@ interface ImportMeta { } declare const __SIMPLE_MODE__: boolean; +declare const __DISABLE_GITHUB_STARS__: boolean; declare const __DISABLED_TOOLS__: string[]; diff --git a/vite.config.ts b/vite.config.ts index 4ba45dc6..26570fd9 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -571,6 +571,9 @@ export default defineConfig(() => { ], define: { __SIMPLE_MODE__: JSON.stringify(process.env.SIMPLE_MODE === 'true'), + __DISABLE_GITHUB_STARS__: JSON.stringify( + process.env.DISABLE_GITHUB_STARS === 'true' + ), __BRAND_NAME__: JSON.stringify(process.env.VITE_BRAND_NAME || ''), __DISABLED_TOOLS__: JSON.stringify( (process.env.DISABLE_TOOLS || '')