Skip to content

fix(security): block direct access to uploaded demos - #78

Merged
Rushaway merged 2 commits into
mainfrom
fix/demo-direct-access
Oct 26, 2026
Merged

Rushaway merged 2 commits into
mainfrom
fix/demo-direct-access

Conversation

@Rushaway

@Rushaway Rushaway commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Cherry-pick of upstream sbpp#1608 and sbpp#1610.

Problem

Uploaded demos (including uploads from the anonymous Submit a ban form) are stored without an extension in web/demos/, which was directly reachable over HTTP. A browser could content-sniff an uploaded file as HTML. The public form also named files md5(SteamID . time()), which is guessable.

Fix

  • UploadHandler::randomDiskName() (CSPRNG, 32-char hex) for both upload paths.
  • demos/ denied in docker/apache/sbpp-prod.conf, a new docker/apache/sbpp-dev.conf, and a shipped web/demos/.htaccess (whitelisted in .gitignore, checked in the release zip). getdemo.php stays the only download path.
  • X-Content-Type-Options: nosniff on every response (init.php + both Apache confs).
  • Docs: nginx / IIS rules in the quickstart.
  • fix(docker): make demos/ writable in the dev web container sbpp/sourcebans-pp#1610: demos/ is writable in the dev web container.

Fork adaptations

  • page.submit.php keeps the fork's empty-upload guard.
  • AGENTS.md / docker/README.md keep the fork's rows (srcdslab image name, dev-prepend line); upstream's CLA row isn't carried over.

Tests

DemoUploadHardening|UploadHandler|Submit|ProdApacheConfig|GetDemo: 18 tests OK. apache2 -t with the new dev conf: Syntax OK. The new E2E spec demo-direct-access.spec.ts needs a rebuilt dev image (the conf is baked in), not run locally.

Self-hosters on nginx / IIS need to add the deny rule themselves (documented in the quickstart).

CHANGELOG: 2.2.2-srcdslab.

Cherry-pick of upstream sbpp#1608 (60d822f) and sbpp#1610
(120209b).

Name uploaded demos from a CSPRNG, deny direct /demos/ access in the
Apache confs and a shipped .htaccess, and send
X-Content-Type-Options: nosniff on every response. Demos (including
uploads from the anonymous submission form) are stored without an
extension; serving them straight from /demos/ let a browser sniff
them as HTML. The public submit form also named the file
md5(SteamID . time()), which is guessable.

sbpp#1610 makes demos/ writable in the dev web container so uploads keep
working under the new layout.

Fork adaptations:
- page.submit.php keeps the fork's empty-upload guard around
  move_uploaded_file();
- AGENTS.md / docker/README.md keep the fork's rows (srcdslab image
  name, dev-prepend description); the CLA row is not carried over.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Rushaway
Rushaway requested review from cmer81 and maxijabase October 26, 2026 07:53
@Rushaway
Rushaway merged commit 6e81f14 into main Oct 26, 2026
7 checks passed
@Rushaway
Rushaway deleted the fix/demo-direct-access branch October 26, 2026 08:06
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.

2 participants