Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Quarantine media files stored before the playlist check

Closed
#12,530 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@atomantic is already working on this.

Since Oct 20, 2026.

  • #12545 by @atomantic — merged

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
javascript
Domain
backend, security

Research direction

Read scripts/migrations/migrationConventions.guard.test.js and the pure detectMediaManifest helper in server/lib/mimeTypes.js first. Add a migration under scripts/migrations/ that checks the first MiB of files in the six named data directories and renames matches to .quarantined, logging the format without the user path segment. Add a migration test with a playlist-bodied .mp3 and real audio file in a temporary data root; done means the match is renamed, audio is unchanged, a second run is a no-op, and the conventions guard passes.

Written by the indexing model from the issue text.

Description

effort:medium model:medium plan planner:opus-5-5 security

Audit slice: uploaded and synced media reaching ffmpeg (security audit, 2026-10-20).

Problem

ffmpeg picks a demuxer from the file's content, not its name. ffmpeg 4.4 and 5.1 (the Ubuntu 22.04 and Debian 12 packages; 6.1 and later refuse) open a .mp3, .wav or .mp4 whose bytes are an HLS playlist, and read the local media files it names into a probe, thumbnail or render. This was reproduced in a container with no network.

The security audit PR adds detectMediaManifest (server/lib/mimeTypes.js) and refuses such files at every ingest:

  • local uploads: server/lib/uploads.js, services/pipeline/musicLibrary.js#importUploadedTrack, services/musicVideo/vocalStem.js, services/videoGen/prepareParams.js#stageUploadDurable
  • peer asset pulls: services/sharing/peerSyncAssets.js#pullOneAsset

Files that landed in data/music, data/uploads, data/videos, data/audio, data/images or data/image-refs before that change were never checked. Library consumers then hand them straight to ffmpeg. One example is services/videoGen/prepareParams.js#stageExistingAudioDurable, which copies an existing library track for an audio-to-video render. Others include the Music Video render's master audio and gallery thumbnails.

Impact: a disguised playlist planted before the upgrade (for example through the password-free upload routes) still makes older ffmpeg read other local media files into renders a caller can download. Exposure needs a pre-existing malicious file plus distro ffmpeg 4.4/5.1. Severity 2.

Decided fix

Add a one-time migration in scripts/migrations/ that walks those six data directories and runs the pure detectMediaManifest from server/lib/mimeTypes.js over each file's first MiB. Server libs are importable per the migration conventions. Each match is renamed to <name>.quarantined and logged with one line per file, naming the format but never the path's user segment. Nothing is deleted. Consumers already reject unknown extensions, so a quarantined file drops out of every library list. Migrations run on upgrade, so no consumption-time checks are needed.

Acceptance criteria

  • A migration test plants a playlist-bodied .mp3 and a real audio file in a temp data root, runs the migration, and asserts the playlist is renamed .quarantined while the audio file is untouched. A second run is a no-op.
  • The migration follows scripts/migrations/migrationConventions.guard.test.js, imports only _lib.js primitives and pure server/lib helpers, and declares no owned output paths.

Scope: small. model:medium because it is a new migration that has to satisfy the migration conventions guard. effort:medium because the directory list and the rename-not-delete choice are decided here.

Dominant language
JavaScript
Stars
38
Forks
32
Avg merge
36m
Merged PRs (30d)
989

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from atomantic/PortOS

All issues in atomantic/PortOS

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.