Skip to content

security: harden webhook endpoint and fix multiple security findings#73

Merged
retardgerman merged 14 commits intomainfrom
fix/webhook-security
Mar 14, 2026
Merged

security: harden webhook endpoint and fix multiple security findings#73
retardgerman merged 14 commits intomainfrom
fix/webhook-security

Conversation

@retardgerman
Copy link
Contributor

@retardgerman retardgerman commented Mar 12, 2026

Security Fixes

This PR addresses several security vulnerabilities. Details will be disclosed after this PR is merged.

Changes

utils/auth.js

  • Auto-generate and persist WEBHOOK_SECRET on first start

app.js

  • Webhook authentication middleware (X-Webhook-Secret header required)
  • Rate limiter on webhook endpoint
  • Timing-safe secret comparison via crypto.timingSafeEqual
  • Preserve WEBHOOK_SECRET across config saves
  • Remove debug logs that exposed credential prefixes to log files

jellyfinWebhook.js

  • buildJellyfinUrl now always uses configured JELLYFIN_BASE_URL, ignoring the webhook-provided ServerUrl to prevent URL injection via poisoned metadata

utils/configFile.js

  • Validate config against Joi schema on startup (warn-only)

utils/validation.js

  • Add WEBHOOK_SECRET to schema
  • Fix USER_MAPPINGS schema type

lib/config.js

  • Add WEBHOOK_SECRET to config template

web/index.html + web/script.js

  • Secret display with copy button and step-by-step plugin setup instructions

README.md

  • Updated webhook setup section
  • Added ⚠️ Security Notice warning against public internet exposure

Migration

Existing installations will have a secret auto-generated on next startup — no manual action required. Users only need to copy the secret from the dashboard and add it as a custom HTTP header (X-Webhook-Secret) in their Jellyfin webhook plugin settings.

🤖 Generated with Claude Code

retardgerman and others added 5 commits March 12, 2026 12:32
…ok endpoint

- Auto-generate and persist WEBHOOK_SECRET on first start
- Reject webhook requests missing or with invalid X-Webhook-Secret header (401)
- Add rate limiter (60 req/min) to the webhook endpoint to prevent flooding
- Expose secret in dashboard with copy button and setup instructions
- Preserve WEBHOOK_SECRET across config saves
- Add X-Webhook-Secret header step to plugin setup guide in dashboard and README

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…c hosting warning

- Replace !== with crypto.timingSafeEqual to prevent timing attacks on X-Webhook-Secret
- Add ⚠️ Security Notice section to README warning against public internet exposure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… validation

- Remove debug logs that exposed DISCORD_TOKEN prefix to log files
- buildJellyfinUrl now always uses configured JELLYFIN_BASE_URL, ignoring
  the webhook-provided ServerUrl to prevent URL injection via poisoned metadata
- Validate config schema on startup using Joi (warn-only, non-fatal)
- Fix USER_MAPPINGS schema type (array of objects, not key-value object)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@retardgerman retardgerman changed the title security(webhook): add secret-based authentication for Jellyfin webhook endpoint security: harden webhook endpoint and fix multiple security findings Mar 12, 2026
retardgerman and others added 6 commits March 12, 2026 14:42
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…irement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sensitive fields (DISCORD_TOKEN, JELLYSEERR_API_KEY, JELLYFIN_API_KEY,
WEBHOOK_SECRET, JWT_SECRET, TMDB_API_KEY, OMDB_API_KEY) are now stored
with a "b64:" prefix and base64-encoded value. readConfig() decodes them
transparently; writeConfig() encodes them before writing.

Backwards-compatible: plain-text values (existing configs) are decoded
as-is until the next save, at which point they are automatically encoded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@retardgerman retardgerman force-pushed the fix/webhook-security branch 2 times, most recently from 9228444 to 7790230 Compare March 12, 2026 16:14
retardgerman and others added 3 commits March 12, 2026 17:59
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add data-i18n attributes and locale keys for strings introduced
in this branch: webhook secret description, Copy URL/Copy Secret
buttons, Headers setup step, and notification testing info note.

Translations added for EN, DE, and SV.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@retardgerman retardgerman merged commit 56ed59a into main Mar 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant