Quarantine media files stored before the playlist check
Maintainers usually reply within 1 day
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
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
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
.mp3and a real audio file in a temp data root, runs the migration, and asserts the playlist is renamed.quarantinedwhile the audio file is untouched. A second run is a no-op. - The migration follows
scripts/migrations/migrationConventions.guard.test.js, imports only_lib.jsprimitives and pureserver/libhelpers, 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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from atomantic/PortOS
-
bug
Difficulty 5/5 Over a week Newbie friendliness 35/100
Maintainers usually reply within 1 day
-
GitHub inbox: Dependabot and Actions PRs count as outside, and Enterprise accounts cannot trust their own instancePossibly taken @atomantic claimed this today. Openarea:devtools effort:medium enhancement in-progress model:heavy plan
atomantic/PortOS#13203 · 1 assignee ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 4/5 3-5 days Newbie friendliness 48/100
Maintainers usually reply within 1 day
-
GitHub inbox: make triage suggestion pills actionable buttonsPossibly taken @atomantic claimed this today. Openarea:devtools effort:medium enhancement model:light plan ux
atomantic/PortOS#13193 · 1 assignee ·
Maintainers usually reply within 1 day
-
GitHub inbox: add an automation rule from any item so similar items are handled on AutopilotPossibly taken @atomantic claimed this today. Openarea:devtools effort:high enhancement model:heavy plan
atomantic/PortOS#13192 · 1 assignee ·
Maintainers usually reply within 1 day
All issues in atomantic/PortOS
Similar issues
-
enhancement good first issue help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
DepressionCenter/agentprise#50 ·
Maintainers usually reply within 1 day
-
enhancement help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
ccomkhj/product-demo#10 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 1/5 Under an hour Newbie friendliness 73/100
-
`at-root-no-redundant` suggested fix breaks `@at-root { ... }` (at-root not followed by a selector)Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
stylelint-scss/stylelint-scss#1368 ·