NukeBase

File Limits & Safety

LimitDefaultEnvironment variable
Maximum file size64 MBFILE_MAX_BYTES
Entries returned by one listing10,000FILE_MAX_DIR_ENTRIES
Uploads + deletes per IP per minute120FILE_WRITE_RATE_MAX
Store rootserver/files/FILES_DIR
Path depth64 segments
Segment length256 characters
Joined relative path200 characters

The size cap is enforced on the bytes that arrive, not on Content-Length — a client that lies about the length is cut off at FILE_MAX_BYTES mid-stream and the partial temp file is removed. A permissive fileValidate can never authorise unbounded disk use.

The upload rate limit exists because uploads are not messages. The WebSocket limiter allows 500,000 messages per second — a sane ceiling for JSON and a meaningless one for an operation costing a disk write and up to FILE_MAX_BYTES of space. Uploads and deletes get their own budget, keyed by IP rather than session, because an HTTP request may carry no session at all.

Path resolution is the security boundary. Every file operation turns its path array into a real filesystem path in one place and nowhere else, and it re-validates from scratch rather than trusting the caller — file operations arrive over HTTP and from server-side code, neither of which passes through the WebSocket message validator. Two separate checks run: a lexical containment check that catches ../-style escapes in the path itself, and a realpath check that catches a symlink already sitting inside the store pointing out of it — where the path is clean but the resolution is not.

Add server/files to exclude in sys/config.json. nukebase push and nukebase pull delete files that are absent on the other side. Without that entry, your first push wipes every user upload on the live server — your local server/files is empty or stale, and the deploy makes the live one match it.

{ "exclude": ["sys", "server/data", "server/files"] }

Atomic uploads

An upload lands in a $tmp- prefixed file beside its destination and is then renamed into place. Two properties fall out of that: readers see either the old bytes or the new ones and never a half-written file, and because a leading $ is a rejected path segment, an in-flight upload has no addressable path — it cannot be downloaded and it never appears in a listing. Leftovers from a crashed or aborted upload are swept at startup.