← Back to ERP system builders
See how it helps
Secure uploads and downloads
Protects file entry and delivery using content inspection, resource authorization and browser isolation rather than trusting filenames or links.
secure-upload-download
Team members using this skill
When is it useful?
Use it when accepting uploads, importing remote files or generating private download URLs for application records.
What does it help you do?
- Inspects actual content and guards archive paths and remote imports.
- Checks tenant and parent-resource access before signing URLs.
- Separates file-serving origin and restricts browser execution.
Try asking this
Reject a disguised HTML upload and prevent unauthorized signed-download links. Rename active HTML as an image and substitute another tenant's file ID. Content inspection and authorization should both fail before any signed link is issued.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Secure Upload & Download
User-uploaded files are untrusted binary inputs that can carry active scripts (XSS via SVG/HTML), path traversal payloads, decompression bombs, SSRF vectors or malware. Enforce defense in depth at both ingress (upload) and egress (download/preview).
1. Untrusted Input Validation (Beyond Extensions)
- Never trust
File.nameextension or the client'sContent-Typeheader:- Inspect magic bytes (file signatures) from the first chunk of the actual uploaded bytes (e.g.,
file-type/libmagic) and verify that the detected format matches the allowed allowlist for that feature. - For images, decode headers/dimensions with a battle-tested parser before accepting.
- Inspect magic bytes (file signatures) from the first chunk of the actual uploaded bytes (e.g.,
- High-risk formats:
- SVG, HTML, XML, XHTML, SWF: contain executable JavaScript (
<script>,onload=,foreignObject) and XXE vectors. Never allow raw SVG/HTML as user avatars or inline images served from the application origin; rasterize to PNG/WebP/AVIF or sanitize and serve only as an attachment from a sandboxed domain. - Archives (
.zip,.tar.gz,.docx,.xlsx): enforce strict Zip Slip path validation (path.resolve(destDir, entryName).startsWith(destDir + path.sep)), reject symlinks, and cap total uncompressed byte count, compression ratio and file count to prevent zip bombs.
- SVG, HTML, XML, XHTML, SWF: contain executable JavaScript (
- Remote URL imports (SSRF Prevention):
- If users can import files by URL, block private/loopback/link-local/cloud-metadata IP ranges (
127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.169.254, IPv6::1,fc00::/7,fe80::/10) at DNS resolution and socket connection time, disable redirects to internal hosts, and enforce strict byte and timeout limits.
- If users can import files by URL, block private/loopback/link-local/cloud-metadata IP ranges (
2. Resource-Level Authorization & Presigned URLs
- Verify tenant & resource permissions on every operation: check that the authenticated user is authorized to upload to, view, share or delete the target parent resource (project, task, message, invoice) before issuing a signed URL or streaming bytes.
- Scoped Direct-to-Object-Store Uploads:
- Never expose bucket-wide credentials to the browser.
- Issue short-lived presigned
PUTorPOSTpolicies (e.g., 5–15 minutes) locked to a single server-generated object key, exactContent-TypeandContent-Length/content-length-range.
- Signed Download URLs Are Bearer Tokens:
- Remember that a presigned S3/Blob
GETURL cannot be individually revoked once issued until its TTL expires. Keep signed download URL TTLs short (e.g., 60–300 seconds) and generate them on demand after checking current authorization, or proxy through an authenticated edge/application endpoint when instant revocation is required.
- Remember that a presigned S3/Blob
3. Safe File Serving & Browser Execution Isolation
When serving user files back to browsers:
- Always set
X-Content-Type-Options: nosniffso the browser never guesses executable HTML/JS from a text or image payload. - Serve from an isolated origin/bucket domain (e.g.,
files.example-usercontent.com) separate from the main application origin so an inline file can never read application cookies,localStorageor CSRF tokens. - Force
Content-Disposition: attachment; filename="..."; filename*=UTF-8''...for downloads and any file type not explicitly safe for inline rendering, and applyContent-Security-Policy: sandboxon file responses.
Included files 1
SKILL.md
