Files
jellytau/SECURITY.md
T
dtourolle 6897b290ed docs: add the governance and CI-operations files the project never had
The repo had no SECURITY.md, CONTRIBUTING.md, code of conduct, or issue
and PR templates. For a client that handles Jellyfin credentials and
ships signed binaries, the missing one that actually matters is
SECURITY.md: there was no stated way to report a vulnerability
privately, so the only available channel was the public tracker.

CONTRIBUTING.md documents the gates as they now stand, including the
three ratchets and which direction each is allowed to move, and the two
rules that surprise people: bug fixes start with a failing test, and
Jellyfin's taxonomy stays in Rust.

The bug template asks the three playback questions -- streaming or
downloaded, transcoding or direct, music or video -- because those
answers decide which of several very different code paths a report is
about, and reconstructing them over several round trips is most of the
cost of a playback bug report.

docs/build/ci-operations.md is the missing operations manual: how to
change the builder image and in what order (image pushed before the
workflow that names it, or CI breaks), why tags are dated rather than
:latest or per-SHA, what each secret is for, and what losing the updater
private key would mean -- installed desktop clients only accept payloads
signed by the key matching the public key they shipped with, so losing it
means everyone reinstalls by hand.

Disk exhaustion on the runner is documented as a manual check rather than
a scheduled job. A daily job would occupy the only slot on a single-slot
runner and pull the whole builder image to run `df` -- and `df` inside a
container does not reliably describe the host's disk, so it would spend
real build capacity reporting a number that might be wrong. What the doc
records instead is the part that is actually hard to rediscover: the
symptoms (cargo dying mid-link, docker refusing to pull, actions/cache
quietly not saving) and that `docker volume prune` needs `-a` to touch
named volumes, which is how it filled up unnoticed.

Two things in these docs are stated plainly because they are true and
were not written down anywhere: without branch protection every gate in
the pipeline is advisory, and the Gitea instance -- canonical remote,
signing secrets, registry, runner -- is not backed up by anything in this
repository.
2026-08-21 18:45:40 +02:00

2.8 KiB

Security Policy

Reporting a vulnerability

Email duncan@tourolle.paris with [JellyTau security] in the subject. Please do not open a public issue for a vulnerability — JellyTau handles Jellyfin credentials and media, and an unfixed issue in a public tracker is an advisory for everyone running it.

Include what you have: what the problem is, how to reproduce it, the version and platform, and what you think an attacker could do with it. A rough report is worth more than a polished one that never gets sent.

You can expect an acknowledgement within a week. If a fix is warranted it will ship in the next release, and you will be credited in the release notes unless you would rather not be.

Supported versions

JellyTau is a single-maintainer project without long-term support branches. Only the latest release receives fixes. Desktop builds can update themselves (Settings → Updates); on Android, install the latest APK from the releases page.

What is in scope

The application and its build pipeline:

  • The Tauri backend (src-tauri/) and the Svelte frontend (src/)
  • Credential storage — the system keyring and its encrypted-file fallback
  • The Android player service and its JNI bridge
  • The loopback media server used for downloaded playback
  • The release pipeline: artifact signing, the update manifest, the builder image

Out of scope: vulnerabilities in Jellyfin itself (report those to the Jellyfin project), and issues that require an already-compromised device or a malicious server the user deliberately configured and trusted.

What the project already does

Not a guarantee, but so you know what has been considered:

  • Credentials never go in plaintext config: the system keyring is used where available, with an AES-GCM encrypted file as fallback (see docs/architecture/09-security.md).
  • The webview runs under a restrictive CSP, and the asset protocol is scoped to the thumbnail cache directory only.
  • Path confinement is enforced on the cache and download roots — a server-supplied id cannot decide where a file lands (DR-210, DR-211).
  • Queries and URLs bind or encode their inputs rather than interpolating them (DR-212).
  • Dependencies are scanned on every build by cargo deny against the RustSec advisory database, and licence-checked against an allow-list (DR-216).
  • Releases carry SHA256SUMS and an SBOM, so you can verify a download and find out what went into it.
  • Desktop updates are signature-verified against a key held only in CI before anything is installed (DR-217).

Windows installers are not Authenticode-signed — SmartScreen will warn on first run. That is a cost and identity problem, not an oversight; verify the download against SHA256SUMS instead.