From 9d3f8e46a07c6553188406e031cc45cdbe3fbdca Mon Sep 17 00:00:00 2001 From: Jarian Date: Sun, 5 Jul 2026 08:10:04 +0000 Subject: [PATCH] feat: Docker deployment, nginx security config, audit report (#11, #14-#22) - Add Dockerfile with MediaInfo, non-root user, slim base - Add docker-compose.yml with env_file and volume mounts - Add nginx.conf with security headers (CSP, HSTS, X-Frame-Options, X-Content-Type-Options) - Hide server version (server_tokens off) - Add SECURITY.md with full audit report and deployment guide - Add .dockerignore for clean builds Closes #11, #14, #21, #22 --- .dockerignore | 12 +++++++++ Dockerfile | 29 +++++++++++++++++++++ SECURITY.md | 60 +++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 22 ++++++++++++++++ nginx.conf | 63 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 186 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 SECURITY.md create mode 100644 docker-compose.yml create mode 100644 nginx.conf diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ec69913 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +.git +.gitignore +*.md +__pycache__ +*.pyc +src/.tvdb_cache +config.json +.env +.dockerignore +Dockerfile +docker-compose.yml +nginx.conf diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..747936f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM python:3.12-slim AS base + +WORKDIR /app + +RUN apt-get update && apt-get install -y --no-install-recommends \ + libmediainfo0v \ + zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +RUN python -m compileall src/ + +ARG USER=epmatcher +ARG UID=1000 +ARG GID=1000 + +RUN groupadd -g "$GID" "$USER" && \ + useradd -u "$UID" -g "$GID" -m -s /bin/bash "$USER" && \ + mkdir -p /app/src/.tvdb_cache && \ + chown -R "$USER":"$USER" /app + +USER $USER + +ENTRYPOINT ["python"] +CMD ["episode_matcher.py"] diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..ec3b12f --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,60 @@ +# Security Audit Report — Episode Matcher + +## Fixed Issues + +### Critical +- **[CWE-22] Path Traversal in TVDB Cache (#2)** — Sanitized series names, validated cache paths stay within cache directory. + +### High +- **[CWE-798] Hardcoded API Key (#3, #4, #5)** — TVDB_API_KEY now read from environment variable. config.json removed from git history, added to .gitignore. +- **[CWE-22] Incomplete .gitignore (#6)** — Added config.json, __pycache__, .env, build artifacts. +- **[CWE-22] Unsafe File Deletion (#8)** — `--auto-delete-duplicates` now requires `--force` flag. Deletions logged to recovery manifest. + +### Medium +- **[CWE-561] sys.path Manipulation (#7)** — Added pyproject.toml for proper packaging with editable install support. +- **[CWE-20] Duplicate Detection (#9)** — Added SHA-256 hash comparison alongside duration for duplicate detection. + +### Low +- **[CWE-346] Single Format Support (#12)** — Now supports .mkv, .mp4, .avi, .mov, .wmv, .flv, .webm, .m4v. +- **Hardcoded Fallback Ratio (#13)** — MediaInfo fallback ratio configurable via `duration_minutes_per_gb` in config.json. + +## Web Security (tv.home.ms / Jellyfin) + +The following issues affect the Jellyfin web interface served at tv.home.ms. +Fixes are in `nginx.conf` (reverse proxy configuration) or require Jellyfin upstream changes. + +### Fixed via nginx.conf +| Issue | Severity | Fix | +|-------|----------|-----| +| #14 Missing security headers | High | CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy added | +| #21 Server version exposed | Low | `server_tokens off` hides nginx version | +| #22 Response time leaked | Low | `more_clear_headers` directive (requires headers-more module) | + +### Requires Jellyfin Upstream Fix +| Issue | Severity | Type | Notes | +|-------|----------|------|-------| +| #15 Console error (scroll behavior) | Medium | BROKEN | Jellyfin JS bundle bug — report to Jellyfin | +| #16 Buttons missing labels | Medium | A11Y | Jellyfin UI — needs aria-label on icon buttons | +| #17 Heading order incorrect | Medium | A11Y | Jellyfin HTML structure — H3 before H1 | +| #18 Inputs lack labels | Medium | A11Y | Jellyfin login form — needs `