Security: GeiserX/Pumperly

SECURITY.md

Security Policy

Supported Versions

VersionSupported
latestYes

Only the latest version deployed from main receives security updates. There are no LTS or backport branches.

Reporting a Vulnerability

Do not open a public issue for security vulnerabilities.

Please report vulnerabilities privately via GitHub Security Advisories or by emailing support@pumperly.com. Include:

  • Description of the vulnerability
  • Steps to reproduce
  • Affected component (scraper, API, frontend, infrastructure)
  • Potential impact assessment

You can expect an initial response within 72 hours. Critical vulnerabilities affecting production will be patched and deployed within 24 hours of confirmation.

Security Architecture

Application Stack

LayerTechnologySecurity Considerations
FrontendNext.js (React)Server-rendered, CSP headers via Cloudflare
APINext.js Route HandlersServer-side only, no direct DB exposure
DatabasePostgreSQL + PostGISInternal network only, not internet-exposed
GeocodingPhoton (OpenSearch)Internal network only
RoutingValhallaInternal network only
Reverse ProxyCaddy + CloudflareTLS termination, DDoS protection
Container RuntimeDocker (Portainer)Non-root containers, read-only where possible

Network Boundaries

Internet → Cloudflare (WAF/DDoS) → Caddy (TLS) → Next.js App
├── PostGIS (internal only)
├── Photon (internal only)
└── Valhalla (internal only)
  • PostGIS, Photon, and Valhalla are never exposed to the internet. They are only reachable from the Next.js application container via Docker internal networking.
  • All external traffic passes through Cloudflare's WAF and Caddy's TLS termination.
  • API routes validate input with Zod schemas before any database interaction.

Data Handling

  • No user accounts or authentication. Pumperly is a read-only public tool. There are no user credentials, sessions, or personal data to protect.
  • No cookies or tracking. User preferences (theme, language, currency) are stored in localStorage only.
  • Fuel price data is public. All scraped data originates from government APIs, open data portals, or publicly accessible community sources.
  • No PII is collected, stored, or transmitted.

Input Validation

  • All API route parameters are validated with Zod schemas (coordinates, country codes, fuel types, pagination).
  • Scraper outputs are sanitized before database insertion (HTML stripping with loop-until-stable for malformed tags, numeric range checks for prices).
  • SQL injection is prevented by Prisma's parameterized queries — raw SQL is never used.
  • The frontend does not render user-supplied HTML; all dynamic content is rendered via React's built-in XSS protections.

Dependency Management

  • Dependabot is enabled for npm, GitHub Actions, and Docker base images with automatic PR creation.
  • npm overrides pin transitive dependencies to patched versions when upstream packages lag behind advisories.
  • CodeQL runs on every push and pull request via GitHub Actions, scanning for JavaScript/TypeScript vulnerabilities.
  • GitGuardian scans all commits for accidentally committed secrets.
  • Dependencies are reviewed before merging — major version bumps are manually inspected for breaking changes.

Container Security

  • The Docker image is built from node:lts-slim (minimal attack surface).
  • The application runs as a non-root user inside the container.
  • Only port 3000 is exposed from the application container.
  • Base image updates are tracked via Dependabot.

Secrets Management

  • All secrets (database credentials, API keys) are injected via environment variables at deploy time.
  • No secrets are committed to the repository. .env files are in .gitignore.
  • GitGuardian monitors all pushes for accidental secret exposure.

Known Limitations

  • Scraper data integrity: Fuel prices are scraped from third-party sources. While sanity checks exist (price range validation, staleness detection), Pumperly cannot guarantee the accuracy of upstream data.
  • No rate limiting at the application level: Rate limiting is handled by Cloudflare. Self-hosted instances should configure rate limiting at the reverse proxy layer.
  • No CSP headers at the application level: Content Security Policy is enforced by Cloudflare. Self-hosted instances should configure CSP in their reverse proxy (Caddy/Nginx).

Security Best Practices for Self-Hosters

If you're self-hosting Pumperly:

  1. Never expose PostGIS, Photon, or Valhalla to the internet. Keep them on an internal Docker network.
  2. Use a reverse proxy with TLS (Caddy, Nginx, Traefik) in front of the Next.js app.
  3. Set strong database credentials and restrict PostgreSQL to listen only on the Docker internal network.
  4. Enable rate limiting at your reverse proxy to prevent abuse of the geocoding and routing APIs.
  5. Keep images updated. Run docker compose pull regularly or enable Watchtower for automatic updates.
  6. Set environment variables securely. Use Docker secrets or a .env file with restrictive permissions (chmod 600).

Vulnerability Disclosure Timeline

DateEvent
2026-03-26Resolved all Dependabot advisories (hono, lodash, effect, brace-expansion) via npm overrides
2026-03-26Fixed CodeQL alerts for incomplete HTML sanitization in Finland scraper

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Security: GeiserX/Pumperly

SECURITY.md

Security Policy

Supported Versions

VersionSupported
latestYes

Only the latest version deployed from main receives security updates. There are no LTS or backport branches.

Reporting a Vulnerability

Do not open a public issue for security vulnerabilities.

Please report vulnerabilities privately via GitHub Security Advisories or by emailing support@pumperly.com. Include:

  • Description of the vulnerability
  • Steps to reproduce
  • Affected component (scraper, API, frontend, infrastructure)
  • Potential impact assessment

You can expect an initial response within 72 hours. Critical vulnerabilities affecting production will be patched and deployed within 24 hours of confirmation.

Security Architecture

Application Stack

LayerTechnologySecurity Considerations
FrontendNext.js (React)Server-rendered, CSP headers via Cloudflare
APINext.js Route HandlersServer-side only, no direct DB exposure
DatabasePostgreSQL + PostGISInternal network only, not internet-exposed
GeocodingPhoton (OpenSearch)Internal network only
RoutingValhallaInternal network only
Reverse ProxyCaddy + CloudflareTLS termination, DDoS protection
Container RuntimeDocker (Portainer)Non-root containers, read-only where possible

Network Boundaries

Internet → Cloudflare (WAF/DDoS) → Caddy (TLS) → Next.js App
├── PostGIS (internal only)
├── Photon (internal only)
└── Valhalla (internal only)
  • PostGIS, Photon, and Valhalla are never exposed to the internet. They are only reachable from the Next.js application container via Docker internal networking.
  • All external traffic passes through Cloudflare's WAF and Caddy's TLS termination.
  • API routes validate input with Zod schemas before any database interaction.

Data Handling

  • No user accounts or authentication. Pumperly is a read-only public tool. There are no user credentials, sessions, or personal data to protect.
  • No cookies or tracking. User preferences (theme, language, currency) are stored in localStorage only.
  • Fuel price data is public. All scraped data originates from government APIs, open data portals, or publicly accessible community sources.
  • No PII is collected, stored, or transmitted.

Input Validation

  • All API route parameters are validated with Zod schemas (coordinates, country codes, fuel types, pagination).
  • Scraper outputs are sanitized before database insertion (HTML stripping with loop-until-stable for malformed tags, numeric range checks for prices).
  • SQL injection is prevented by Prisma's parameterized queries — raw SQL is never used.
  • The frontend does not render user-supplied HTML; all dynamic content is rendered via React's built-in XSS protections.

Dependency Management

  • Dependabot is enabled for npm, GitHub Actions, and Docker base images with automatic PR creation.
  • npm overrides pin transitive dependencies to patched versions when upstream packages lag behind advisories.
  • CodeQL runs on every push and pull request via GitHub Actions, scanning for JavaScript/TypeScript vulnerabilities.
  • GitGuardian scans all commits for accidentally committed secrets.
  • Dependencies are reviewed before merging — major version bumps are manually inspected for breaking changes.

Container Security

  • The Docker image is built from node:lts-slim (minimal attack surface).
  • The application runs as a non-root user inside the container.
  • Only port 3000 is exposed from the application container.
  • Base image updates are tracked via Dependabot.

Secrets Management

  • All secrets (database credentials, API keys) are injected via environment variables at deploy time.
  • No secrets are committed to the repository. .env files are in .gitignore.
  • GitGuardian monitors all pushes for accidental secret exposure.

Known Limitations

  • Scraper data integrity: Fuel prices are scraped from third-party sources. While sanity checks exist (price range validation, staleness detection), Pumperly cannot guarantee the accuracy of upstream data.
  • No rate limiting at the application level: Rate limiting is handled by Cloudflare. Self-hosted instances should configure rate limiting at the reverse proxy layer.
  • No CSP headers at the application level: Content Security Policy is enforced by Cloudflare. Self-hosted instances should configure CSP in their reverse proxy (Caddy/Nginx).

Security Best Practices for Self-Hosters

If you're self-hosting Pumperly:

  1. Never expose PostGIS, Photon, or Valhalla to the internet. Keep them on an internal Docker network.
  2. Use a reverse proxy with TLS (Caddy, Nginx, Traefik) in front of the Next.js app.
  3. Set strong database credentials and restrict PostgreSQL to listen only on the Docker internal network.
  4. Enable rate limiting at your reverse proxy to prevent abuse of the geocoding and routing APIs.
  5. Keep images updated. Run docker compose pull regularly or enable Watchtower for automatic updates.
  6. Set environment variables securely. Use Docker secrets or a .env file with restrictive permissions (chmod 600).

Vulnerability Disclosure Timeline

DateEvent
2026-03-26Resolved all Dependabot advisories (hono, lodash, effect, brace-expansion) via npm overrides
2026-03-26Fixed CodeQL alerts for incomplete HTML sanitization in Finland scraper

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Security: GeiserX/Pumperly

SECURITY.md

Security Policy

Supported Versions

VersionSupported
latestYes

Only the latest version deployed from main receives security updates. There are no LTS or backport branches.

Reporting a Vulnerability

Do not open a public issue for security vulnerabilities.

Please report vulnerabilities privately via GitHub Security Advisories or by emailing support@pumperly.com. Include:

  • Description of the vulnerability
  • Steps to reproduce
  • Affected component (scraper, API, frontend, infrastructure)
  • Potential impact assessment

You can expect an initial response within 72 hours. Critical vulnerabilities affecting production will be patched and deployed within 24 hours of confirmation.

Security Architecture

Application Stack

LayerTechnologySecurity Considerations
FrontendNext.js (React)Server-rendered, CSP headers via Cloudflare
APINext.js Route HandlersServer-side only, no direct DB exposure
DatabasePostgreSQL + PostGISInternal network only, not internet-exposed
GeocodingPhoton (OpenSearch)Internal network only
RoutingValhallaInternal network only
Reverse ProxyCaddy + CloudflareTLS termination, DDoS protection
Container RuntimeDocker (Portainer)Non-root containers, read-only where possible

Network Boundaries

Internet → Cloudflare (WAF/DDoS) → Caddy (TLS) → Next.js App
├── PostGIS (internal only)
├── Photon (internal only)
└── Valhalla (internal only)
  • PostGIS, Photon, and Valhalla are never exposed to the internet. They are only reachable from the Next.js application container via Docker internal networking.
  • All external traffic passes through Cloudflare's WAF and Caddy's TLS termination.
  • API routes validate input with Zod schemas before any database interaction.

Data Handling

  • No user accounts or authentication. Pumperly is a read-only public tool. There are no user credentials, sessions, or personal data to protect.
  • No cookies or tracking. User preferences (theme, language, currency) are stored in localStorage only.
  • Fuel price data is public. All scraped data originates from government APIs, open data portals, or publicly accessible community sources.
  • No PII is collected, stored, or transmitted.

Input Validation

  • All API route parameters are validated with Zod schemas (coordinates, country codes, fuel types, pagination).
  • Scraper outputs are sanitized before database insertion (HTML stripping with loop-until-stable for malformed tags, numeric range checks for prices).
  • SQL injection is prevented by Prisma's parameterized queries — raw SQL is never used.
  • The frontend does not render user-supplied HTML; all dynamic content is rendered via React's built-in XSS protections.

Dependency Management

  • Dependabot is enabled for npm, GitHub Actions, and Docker base images with automatic PR creation.
  • npm overrides pin transitive dependencies to patched versions when upstream packages lag behind advisories.
  • CodeQL runs on every push and pull request via GitHub Actions, scanning for JavaScript/TypeScript vulnerabilities.
  • GitGuardian scans all commits for accidentally committed secrets.
  • Dependencies are reviewed before merging — major version bumps are manually inspected for breaking changes.

Container Security

  • The Docker image is built from node:lts-slim (minimal attack surface).
  • The application runs as a non-root user inside the container.
  • Only port 3000 is exposed from the application container.
  • Base image updates are tracked via Dependabot.

Secrets Management

  • All secrets (database credentials, API keys) are injected via environment variables at deploy time.
  • No secrets are committed to the repository. .env files are in .gitignore.
  • GitGuardian monitors all pushes for accidental secret exposure.

Known Limitations

  • Scraper data integrity: Fuel prices are scraped from third-party sources. While sanity checks exist (price range validation, staleness detection), Pumperly cannot guarantee the accuracy of upstream data.
  • No rate limiting at the application level: Rate limiting is handled by Cloudflare. Self-hosted instances should configure rate limiting at the reverse proxy layer.
  • No CSP headers at the application level: Content Security Policy is enforced by Cloudflare. Self-hosted instances should configure CSP in their reverse proxy (Caddy/Nginx).

Security Best Practices for Self-Hosters

If you're self-hosting Pumperly:

  1. Never expose PostGIS, Photon, or Valhalla to the internet. Keep them on an internal Docker network.
  2. Use a reverse proxy with TLS (Caddy, Nginx, Traefik) in front of the Next.js app.
  3. Set strong database credentials and restrict PostgreSQL to listen only on the Docker internal network.
  4. Enable rate limiting at your reverse proxy to prevent abuse of the geocoding and routing APIs.
  5. Keep images updated. Run docker compose pull regularly or enable Watchtower for automatic updates.
  6. Set environment variables securely. Use Docker secrets or a .env file with restrictive permissions (chmod 600).

Vulnerability Disclosure Timeline

DateEvent
2026-03-26Resolved all Dependabot advisories (hono, lodash, effect, brace-expansion) via npm overrides
2026-03-26Fixed CodeQL alerts for incomplete HTML sanitization in Finland scraper

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Security: GeiserX/Pumperly

SECURITY.md

Security Policy

Supported Versions

VersionSupported
latestYes

Only the latest version deployed from main receives security updates. There are no LTS or backport branches.

Reporting a Vulnerability

Do not open a public issue for security vulnerabilities.

Please report vulnerabilities privately via GitHub Security Advisories or by emailing support@pumperly.com. Include:

  • Description of the vulnerability
  • Steps to reproduce
  • Affected component (scraper, API, frontend, infrastructure)
  • Potential impact assessment

You can expect an initial response within 72 hours. Critical vulnerabilities affecting production will be patched and deployed within 24 hours of confirmation.

Security Architecture

Application Stack

LayerTechnologySecurity Considerations
FrontendNext.js (React)Server-rendered, CSP headers via Cloudflare
APINext.js Route HandlersServer-side only, no direct DB exposure
DatabasePostgreSQL + PostGISInternal network only, not internet-exposed
GeocodingPhoton (OpenSearch)Internal network only
RoutingValhallaInternal network only
Reverse ProxyCaddy + CloudflareTLS termination, DDoS protection
Container RuntimeDocker (Portainer)Non-root containers, read-only where possible

Network Boundaries

Internet → Cloudflare (WAF/DDoS) → Caddy (TLS) → Next.js App
├── PostGIS (internal only)
├── Photon (internal only)
└── Valhalla (internal only)
  • PostGIS, Photon, and Valhalla are never exposed to the internet. They are only reachable from the Next.js application container via Docker internal networking.
  • All external traffic passes through Cloudflare's WAF and Caddy's TLS termination.
  • API routes validate input with Zod schemas before any database interaction.

Data Handling

  • No user accounts or authentication. Pumperly is a read-only public tool. There are no user credentials, sessions, or personal data to protect.
  • No cookies or tracking. User preferences (theme, language, currency) are stored in localStorage only.
  • Fuel price data is public. All scraped data originates from government APIs, open data portals, or publicly accessible community sources.
  • No PII is collected, stored, or transmitted.

Input Validation

  • All API route parameters are validated with Zod schemas (coordinates, country codes, fuel types, pagination).
  • Scraper outputs are sanitized before database insertion (HTML stripping with loop-until-stable for malformed tags, numeric range checks for prices).
  • SQL injection is prevented by Prisma's parameterized queries — raw SQL is never used.
  • The frontend does not render user-supplied HTML; all dynamic content is rendered via React's built-in XSS protections.

Dependency Management

  • Dependabot is enabled for npm, GitHub Actions, and Docker base images with automatic PR creation.
  • npm overrides pin transitive dependencies to patched versions when upstream packages lag behind advisories.
  • CodeQL runs on every push and pull request via GitHub Actions, scanning for JavaScript/TypeScript vulnerabilities.
  • GitGuardian scans all commits for accidentally committed secrets.
  • Dependencies are reviewed before merging — major version bumps are manually inspected for breaking changes.

Container Security

  • The Docker image is built from node:lts-slim (minimal attack surface).
  • The application runs as a non-root user inside the container.
  • Only port 3000 is exposed from the application container.
  • Base image updates are tracked via Dependabot.

Secrets Management

  • All secrets (database credentials, API keys) are injected via environment variables at deploy time.
  • No secrets are committed to the repository. .env files are in .gitignore.
  • GitGuardian monitors all pushes for accidental secret exposure.

Known Limitations

  • Scraper data integrity: Fuel prices are scraped from third-party sources. While sanity checks exist (price range validation, staleness detection), Pumperly cannot guarantee the accuracy of upstream data.
  • No rate limiting at the application level: Rate limiting is handled by Cloudflare. Self-hosted instances should configure rate limiting at the reverse proxy layer.
  • No CSP headers at the application level: Content Security Policy is enforced by Cloudflare. Self-hosted instances should configure CSP in their reverse proxy (Caddy/Nginx).

Security Best Practices for Self-Hosters

If you're self-hosting Pumperly:

  1. Never expose PostGIS, Photon, or Valhalla to the internet. Keep them on an internal Docker network.
  2. Use a reverse proxy with TLS (Caddy, Nginx, Traefik) in front of the Next.js app.
  3. Set strong database credentials and restrict PostgreSQL to listen only on the Docker internal network.
  4. Enable rate limiting at your reverse proxy to prevent abuse of the geocoding and routing APIs.
  5. Keep images updated. Run docker compose pull regularly or enable Watchtower for automatic updates.
  6. Set environment variables securely. Use Docker secrets or a .env file with restrictive permissions (chmod 600).

Vulnerability Disclosure Timeline

DateEvent
2026-03-26Resolved all Dependabot advisories (hono, lodash, effect, brace-expansion) via npm overrides
2026-03-26Fixed CodeQL alerts for incomplete HTML sanitization in Finland scraper

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Security: GeiserX/Pumperly

SECURITY.md

Security Policy

Supported Versions

VersionSupported
latestYes

Only the latest version deployed from main receives security updates. There are no LTS or backport branches.

Reporting a Vulnerability

Do not open a public issue for security vulnerabilities.

Please report vulnerabilities privately via GitHub Security Advisories or by emailing support@pumperly.com. Include:

  • Description of the vulnerability
  • Steps to reproduce
  • Affected component (scraper, API, frontend, infrastructure)
  • Potential impact assessment

You can expect an initial response within 72 hours. Critical vulnerabilities affecting production will be patched and deployed within 24 hours of confirmation.

Security Architecture

Application Stack

LayerTechnologySecurity Considerations
FrontendNext.js (React)Server-rendered, CSP headers via Cloudflare
APINext.js Route HandlersServer-side only, no direct DB exposure
DatabasePostgreSQL + PostGISInternal network only, not internet-exposed
GeocodingPhoton (OpenSearch)Internal network only
RoutingValhallaInternal network only
Reverse ProxyCaddy + CloudflareTLS termination, DDoS protection
Container RuntimeDocker (Portainer)Non-root containers, read-only where possible

Network Boundaries

Internet → Cloudflare (WAF/DDoS) → Caddy (TLS) → Next.js App
├── PostGIS (internal only)
├── Photon (internal only)
└── Valhalla (internal only)
  • PostGIS, Photon, and Valhalla are never exposed to the internet. They are only reachable from the Next.js application container via Docker internal networking.
  • All external traffic passes through Cloudflare's WAF and Caddy's TLS termination.
  • API routes validate input with Zod schemas before any database interaction.

Data Handling

  • No user accounts or authentication. Pumperly is a read-only public tool. There are no user credentials, sessions, or personal data to protect.
  • No cookies or tracking. User preferences (theme, language, currency) are stored in localStorage only.
  • Fuel price data is public. All scraped data originates from government APIs, open data portals, or publicly accessible community sources.
  • No PII is collected, stored, or transmitted.

Input Validation

  • All API route parameters are validated with Zod schemas (coordinates, country codes, fuel types, pagination).
  • Scraper outputs are sanitized before database insertion (HTML stripping with loop-until-stable for malformed tags, numeric range checks for prices).
  • SQL injection is prevented by Prisma's parameterized queries — raw SQL is never used.
  • The frontend does not render user-supplied HTML; all dynamic content is rendered via React's built-in XSS protections.

Dependency Management

  • Dependabot is enabled for npm, GitHub Actions, and Docker base images with automatic PR creation.
  • npm overrides pin transitive dependencies to patched versions when upstream packages lag behind advisories.
  • CodeQL runs on every push and pull request via GitHub Actions, scanning for JavaScript/TypeScript vulnerabilities.
  • GitGuardian scans all commits for accidentally committed secrets.
  • Dependencies are reviewed before merging — major version bumps are manually inspected for breaking changes.

Container Security

  • The Docker image is built from node:lts-slim (minimal attack surface).
  • The application runs as a non-root user inside the container.
  • Only port 3000 is exposed from the application container.
  • Base image updates are tracked via Dependabot.

Secrets Management

  • All secrets (database credentials, API keys) are injected via environment variables at deploy time.
  • No secrets are committed to the repository. .env files are in .gitignore.
  • GitGuardian monitors all pushes for accidental secret exposure.

Known Limitations

  • Scraper data integrity: Fuel prices are scraped from third-party sources. While sanity checks exist (price range validation, staleness detection), Pumperly cannot guarantee the accuracy of upstream data.
  • No rate limiting at the application level: Rate limiting is handled by Cloudflare. Self-hosted instances should configure rate limiting at the reverse proxy layer.
  • No CSP headers at the application level: Content Security Policy is enforced by Cloudflare. Self-hosted instances should configure CSP in their reverse proxy (Caddy/Nginx).

Security Best Practices for Self-Hosters

If you're self-hosting Pumperly:

  1. Never expose PostGIS, Photon, or Valhalla to the internet. Keep them on an internal Docker network.
  2. Use a reverse proxy with TLS (Caddy, Nginx, Traefik) in front of the Next.js app.
  3. Set strong database credentials and restrict PostgreSQL to listen only on the Docker internal network.
  4. Enable rate limiting at your reverse proxy to prevent abuse of the geocoding and routing APIs.
  5. Keep images updated. Run docker compose pull regularly or enable Watchtower for automatic updates.
  6. Set environment variables securely. Use Docker secrets or a .env file with restrictive permissions (chmod 600).

Vulnerability Disclosure Timeline

DateEvent
2026-03-26Resolved all Dependabot advisories (hono, lodash, effect, brace-expansion) via npm overrides
2026-03-26Fixed CodeQL alerts for incomplete HTML sanitization in Finland scraper

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Security: GeiserX/Pumperly

SECURITY.md

Security Policy

Supported Versions

VersionSupported
latestYes

Only the latest version deployed from main receives security updates. There are no LTS or backport branches.

Reporting a Vulnerability

Do not open a public issue for security vulnerabilities.

Please report vulnerabilities privately via GitHub Security Advisories or by emailing support@pumperly.com. Include:

  • Description of the vulnerability
  • Steps to reproduce
  • Affected component (scraper, API, frontend, infrastructure)
  • Potential impact assessment

You can expect an initial response within 72 hours. Critical vulnerabilities affecting production will be patched and deployed within 24 hours of confirmation.

Security Architecture

Application Stack

LayerTechnologySecurity Considerations
FrontendNext.js (React)Server-rendered, CSP headers via Cloudflare
APINext.js Route HandlersServer-side only, no direct DB exposure
DatabasePostgreSQL + PostGISInternal network only, not internet-exposed
GeocodingPhoton (OpenSearch)Internal network only
RoutingValhallaInternal network only
Reverse ProxyCaddy + CloudflareTLS termination, DDoS protection
Container RuntimeDocker (Portainer)Non-root containers, read-only where possible

Network Boundaries

Internet → Cloudflare (WAF/DDoS) → Caddy (TLS) → Next.js App
├── PostGIS (internal only)
├── Photon (internal only)
└── Valhalla (internal only)
  • PostGIS, Photon, and Valhalla are never exposed to the internet. They are only reachable from the Next.js application container via Docker internal networking.
  • All external traffic passes through Cloudflare's WAF and Caddy's TLS termination.
  • API routes validate input with Zod schemas before any database interaction.

Data Handling

  • No user accounts or authentication. Pumperly is a read-only public tool. There are no user credentials, sessions, or personal data to protect.
  • No cookies or tracking. User preferences (theme, language, currency) are stored in localStorage only.
  • Fuel price data is public. All scraped data originates from government APIs, open data portals, or publicly accessible community sources.
  • No PII is collected, stored, or transmitted.

Input Validation

  • All API route parameters are validated with Zod schemas (coordinates, country codes, fuel types, pagination).
  • Scraper outputs are sanitized before database insertion (HTML stripping with loop-until-stable for malformed tags, numeric range checks for prices).
  • SQL injection is prevented by Prisma's parameterized queries — raw SQL is never used.
  • The frontend does not render user-supplied HTML; all dynamic content is rendered via React's built-in XSS protections.

Dependency Management

  • Dependabot is enabled for npm, GitHub Actions, and Docker base images with automatic PR creation.
  • npm overrides pin transitive dependencies to patched versions when upstream packages lag behind advisories.
  • CodeQL runs on every push and pull request via GitHub Actions, scanning for JavaScript/TypeScript vulnerabilities.
  • GitGuardian scans all commits for accidentally committed secrets.
  • Dependencies are reviewed before merging — major version bumps are manually inspected for breaking changes.

Container Security

  • The Docker image is built from node:lts-slim (minimal attack surface).
  • The application runs as a non-root user inside the container.
  • Only port 3000 is exposed from the application container.
  • Base image updates are tracked via Dependabot.

Secrets Management

  • All secrets (database credentials, API keys) are injected via environment variables at deploy time.
  • No secrets are committed to the repository. .env files are in .gitignore.
  • GitGuardian monitors all pushes for accidental secret exposure.

Known Limitations

  • Scraper data integrity: Fuel prices are scraped from third-party sources. While sanity checks exist (price range validation, staleness detection), Pumperly cannot guarantee the accuracy of upstream data.
  • No rate limiting at the application level: Rate limiting is handled by Cloudflare. Self-hosted instances should configure rate limiting at the reverse proxy layer.
  • No CSP headers at the application level: Content Security Policy is enforced by Cloudflare. Self-hosted instances should configure CSP in their reverse proxy (Caddy/Nginx).

Security Best Practices for Self-Hosters

If you're self-hosting Pumperly:

  1. Never expose PostGIS, Photon, or Valhalla to the internet. Keep them on an internal Docker network.
  2. Use a reverse proxy with TLS (Caddy, Nginx, Traefik) in front of the Next.js app.
  3. Set strong database credentials and restrict PostgreSQL to listen only on the Docker internal network.
  4. Enable rate limiting at your reverse proxy to prevent abuse of the geocoding and routing APIs.
  5. Keep images updated. Run docker compose pull regularly or enable Watchtower for automatic updates.
  6. Set environment variables securely. Use Docker secrets or a .env file with restrictive permissions (chmod 600).

Vulnerability Disclosure Timeline

DateEvent
2026-03-26Resolved all Dependabot advisories (hono, lodash, effect, brace-expansion) via npm overrides
2026-03-26Fixed CodeQL alerts for incomplete HTML sanitization in Finland scraper

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Security: GeiserX/Pumperly

SECURITY.md

Security Policy

Supported Versions

VersionSupported
latestYes

Only the latest version deployed from main receives security updates. There are no LTS or backport branches.

Reporting a Vulnerability

Do not open a public issue for security vulnerabilities.

Please report vulnerabilities privately via GitHub Security Advisories or by emailing support@pumperly.com. Include:

  • Description of the vulnerability
  • Steps to reproduce
  • Affected component (scraper, API, frontend, infrastructure)
  • Potential impact assessment

You can expect an initial response within 72 hours. Critical vulnerabilities affecting production will be patched and deployed within 24 hours of confirmation.

Security Architecture

Application Stack

LayerTechnologySecurity Considerations
FrontendNext.js (React)Server-rendered, CSP headers via Cloudflare
APINext.js Route HandlersServer-side only, no direct DB exposure
DatabasePostgreSQL + PostGISInternal network only, not internet-exposed
GeocodingPhoton (OpenSearch)Internal network only
RoutingValhallaInternal network only
Reverse ProxyCaddy + CloudflareTLS termination, DDoS protection
Container RuntimeDocker (Portainer)Non-root containers, read-only where possible

Network Boundaries

Internet → Cloudflare (WAF/DDoS) → Caddy (TLS) → Next.js App
├── PostGIS (internal only)
├── Photon (internal only)
└── Valhalla (internal only)
  • PostGIS, Photon, and Valhalla are never exposed to the internet. They are only reachable from the Next.js application container via Docker internal networking.
  • All external traffic passes through Cloudflare's WAF and Caddy's TLS termination.
  • API routes validate input with Zod schemas before any database interaction.

Data Handling

  • No user accounts or authentication. Pumperly is a read-only public tool. There are no user credentials, sessions, or personal data to protect.
  • No cookies or tracking. User preferences (theme, language, currency) are stored in localStorage only.
  • Fuel price data is public. All scraped data originates from government APIs, open data portals, or publicly accessible community sources.
  • No PII is collected, stored, or transmitted.

Input Validation

  • All API route parameters are validated with Zod schemas (coordinates, country codes, fuel types, pagination).
  • Scraper outputs are sanitized before database insertion (HTML stripping with loop-until-stable for malformed tags, numeric range checks for prices).
  • SQL injection is prevented by Prisma's parameterized queries — raw SQL is never used.
  • The frontend does not render user-supplied HTML; all dynamic content is rendered via React's built-in XSS protections.

Dependency Management

  • Dependabot is enabled for npm, GitHub Actions, and Docker base images with automatic PR creation.
  • npm overrides pin transitive dependencies to patched versions when upstream packages lag behind advisories.
  • CodeQL runs on every push and pull request via GitHub Actions, scanning for JavaScript/TypeScript vulnerabilities.
  • GitGuardian scans all commits for accidentally committed secrets.
  • Dependencies are reviewed before merging — major version bumps are manually inspected for breaking changes.

Container Security

  • The Docker image is built from node:lts-slim (minimal attack surface).
  • The application runs as a non-root user inside the container.
  • Only port 3000 is exposed from the application container.
  • Base image updates are tracked via Dependabot.

Secrets Management

  • All secrets (database credentials, API keys) are injected via environment variables at deploy time.
  • No secrets are committed to the repository. .env files are in .gitignore.
  • GitGuardian monitors all pushes for accidental secret exposure.

Known Limitations

  • Scraper data integrity: Fuel prices are scraped from third-party sources. While sanity checks exist (price range validation, staleness detection), Pumperly cannot guarantee the accuracy of upstream data.
  • No rate limiting at the application level: Rate limiting is handled by Cloudflare. Self-hosted instances should configure rate limiting at the reverse proxy layer.
  • No CSP headers at the application level: Content Security Policy is enforced by Cloudflare. Self-hosted instances should configure CSP in their reverse proxy (Caddy/Nginx).

Security Best Practices for Self-Hosters

If you're self-hosting Pumperly:

  1. Never expose PostGIS, Photon, or Valhalla to the internet. Keep them on an internal Docker network.
  2. Use a reverse proxy with TLS (Caddy, Nginx, Traefik) in front of the Next.js app.
  3. Set strong database credentials and restrict PostgreSQL to listen only on the Docker internal network.
  4. Enable rate limiting at your reverse proxy to prevent abuse of the geocoding and routing APIs.
  5. Keep images updated. Run docker compose pull regularly or enable Watchtower for automatic updates.
  6. Set environment variables securely. Use Docker secrets or a .env file with restrictive permissions (chmod 600).

Vulnerability Disclosure Timeline

DateEvent
2026-03-26Resolved all Dependabot advisories (hono, lodash, effect, brace-expansion) via npm overrides
2026-03-26Fixed CodeQL alerts for incomplete HTML sanitization in Finland scraper

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Security: GeiserX/Pumperly

SECURITY.md

Security Policy

Supported Versions

VersionSupported
latestYes

Only the latest version deployed from main receives security updates. There are no LTS or backport branches.

Reporting a Vulnerability

Do not open a public issue for security vulnerabilities.

Please report vulnerabilities privately via GitHub Security Advisories or by emailing support@pumperly.com. Include:

  • Description of the vulnerability
  • Steps to reproduce
  • Affected component (scraper, API, frontend, infrastructure)
  • Potential impact assessment

You can expect an initial response within 72 hours. Critical vulnerabilities affecting production will be patched and deployed within 24 hours of confirmation.

Security Architecture

Application Stack

LayerTechnologySecurity Considerations
FrontendNext.js (React)Server-rendered, CSP headers via Cloudflare
APINext.js Route HandlersServer-side only, no direct DB exposure
DatabasePostgreSQL + PostGISInternal network only, not internet-exposed
GeocodingPhoton (OpenSearch)Internal network only
RoutingValhallaInternal network only
Reverse ProxyCaddy + CloudflareTLS termination, DDoS protection
Container RuntimeDocker (Portainer)Non-root containers, read-only where possible

Network Boundaries

Internet → Cloudflare (WAF/DDoS) → Caddy (TLS) → Next.js App
├── PostGIS (internal only)
├── Photon (internal only)
└── Valhalla (internal only)
  • PostGIS, Photon, and Valhalla are never exposed to the internet. They are only reachable from the Next.js application container via Docker internal networking.
  • All external traffic passes through Cloudflare's WAF and Caddy's TLS termination.
  • API routes validate input with Zod schemas before any database interaction.

Data Handling

  • No user accounts or authentication. Pumperly is a read-only public tool. There are no user credentials, sessions, or personal data to protect.
  • No cookies or tracking. User preferences (theme, language, currency) are stored in localStorage only.
  • Fuel price data is public. All scraped data originates from government APIs, open data portals, or publicly accessible community sources.
  • No PII is collected, stored, or transmitted.

Input Validation

  • All API route parameters are validated with Zod schemas (coordinates, country codes, fuel types, pagination).
  • Scraper outputs are sanitized before database insertion (HTML stripping with loop-until-stable for malformed tags, numeric range checks for prices).
  • SQL injection is prevented by Prisma's parameterized queries — raw SQL is never used.
  • The frontend does not render user-supplied HTML; all dynamic content is rendered via React's built-in XSS protections.

Dependency Management

  • Dependabot is enabled for npm, GitHub Actions, and Docker base images with automatic PR creation.
  • npm overrides pin transitive dependencies to patched versions when upstream packages lag behind advisories.
  • CodeQL runs on every push and pull request via GitHub Actions, scanning for JavaScript/TypeScript vulnerabilities.
  • GitGuardian scans all commits for accidentally committed secrets.
  • Dependencies are reviewed before merging — major version bumps are manually inspected for breaking changes.

Container Security

  • The Docker image is built from node:lts-slim (minimal attack surface).
  • The application runs as a non-root user inside the container.
  • Only port 3000 is exposed from the application container.
  • Base image updates are tracked via Dependabot.

Secrets Management

  • All secrets (database credentials, API keys) are injected via environment variables at deploy time.
  • No secrets are committed to the repository. .env files are in .gitignore.
  • GitGuardian monitors all pushes for accidental secret exposure.

Known Limitations

  • Scraper data integrity: Fuel prices are scraped from third-party sources. While sanity checks exist (price range validation, staleness detection), Pumperly cannot guarantee the accuracy of upstream data.
  • No rate limiting at the application level: Rate limiting is handled by Cloudflare. Self-hosted instances should configure rate limiting at the reverse proxy layer.
  • No CSP headers at the application level: Content Security Policy is enforced by Cloudflare. Self-hosted instances should configure CSP in their reverse proxy (Caddy/Nginx).

Security Best Practices for Self-Hosters

If you're self-hosting Pumperly:

  1. Never expose PostGIS, Photon, or Valhalla to the internet. Keep them on an internal Docker network.
  2. Use a reverse proxy with TLS (Caddy, Nginx, Traefik) in front of the Next.js app.
  3. Set strong database credentials and restrict PostgreSQL to listen only on the Docker internal network.
  4. Enable rate limiting at your reverse proxy to prevent abuse of the geocoding and routing APIs.
  5. Keep images updated. Run docker compose pull regularly or enable Watchtower for automatic updates.
  6. Set environment variables securely. Use Docker secrets or a .env file with restrictive permissions (chmod 600).

Vulnerability Disclosure Timeline

DateEvent
2026-03-26Resolved all Dependabot advisories (hono, lodash, effect, brace-expansion) via npm overrides
2026-03-26Fixed CodeQL alerts for incomplete HTML sanitization in Finland scraper

There aren't any published security advisories