File upload security
Skill ShieldNet-360/secure-vibe/dist/agent-skills/.agents/skills/file-upload-security
Validate user uploads: MIME magic bytes, filename sanitization, size limits, separate serving domain, AV scanning, polyglot detection — Applies to: when generating an HTTP file-upload endpoint; when wiring presigned-URL upload to S3 / GCS / Azure Blob; when adding image/PDF/document processing of user uploads; when reviewing user-generated-content storage and servingFrom its SKILL.md
npx -y skills add ShieldNet-360/secure-vibe --skill file-upload-securityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 15 stars15 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 3 commands, including `convert in.jpg out.jpg` and 2 more.
SKILL.md
4.7 KB, ~1.0k tokens by cl100k_base, as published. Nobody here has run it
File Upload Security
Validate user uploads: MIME magic bytes, filename sanitization, size limits, separate serving domain, AV scanning, polyglot detection
ALWAYS
- Verify magic bytes of every upload server-side.
Content-Typeand file extension are attacker-controlled and never sufficient. Use libmagic,file-type(Node),mimetypes-magic(Python), or Tika. - Maintain an allowlist of accepted types per endpoint (
image/png,image/jpeg,application/pdf, …). Deny everything else, includingtext/html,image/svg+xml(carries<script>),text/xml, andapplication/octet-stream. - Sanitize filenames: strip directory components, normalize Unicode, reject
.., NUL byte, control chars, reserved Windows names (CON,PRN,AUX,NUL,COM1-9,LPT1-9), and any non[a-zA-Z0-9._-]characters. Store as a UUID / hash and keep the original filename in a separate, escaped metadata column. - Enforce a size limit at the proxy / API gateway and at the application — at least double-layer. The proxy limit prevents bandwidth DoS; the app limit prevents memory exhaustion when a proxy is misconfigured.
- Store uploads outside the document root and serve them from a separate domain (
usercontent.example.net) on a CDN. SetContent-Disposition: attachmentfor non-image types and aContent-Security-Policy: default-src 'none'; sandboxheader to neutralize any inline-rendered HTML/SVG. - Run a virus scanner (ClamAV, VirusTotal, Sophos) on every upload before making it accessible to other users — out of band so the request itself isn't latency-bound.
- Re-encode media server-side:
convert in.jpg out.jpg(ImageMagick with a strictpolicy.xml),ffmpeg -ifor video,pdftocairofor PDFs. Re-encoding strips most polyglot / steganographic payloads and exotic codec exploits. - For SVG specifically: either render server-side to a raster format, or pass through a strict allowlist sanitizer (DOMPurify in Node,
lxml.html.cleanin Python) that strips<script>,<iframe>,<foreignObject>,xlink:hrefwithjavascript:, and CSS expression / url() with non-data URIs.
NEVER
- Trust
Content-Typefrom the client. The mime sniffer in IE / older Chrome reads the body for type clues — an HTML payload disguised asimage/pngwill run as HTML when served same-origin. - Construct the storage path with the user-supplied filename. Path traversal (
../../etc/passwd) and the Windows reserved-name class both reduce to "let attacker pick where to write." - Serve uploads from the same origin as the application. Serving on
api.example.com/uploads/x.htmlmeans a malicious HTML upload runs with full access to api.example.com cookies and CORS. - Use a stack that processes uploads with ImageMagick / libraw / ExifTool / ffmpeg without strict policy.xml / sandbox / version control. ImageTragick (CVE-2016-3714) and GitLab ExifTool (CVE-2021-22205) both relied on a server happily handing user-controlled bytes to a media library.
- Allow PDF upload + render in-browser without verifying the PDF passes structural validation (e.g.
pdfinfo). Malicious PDFs are a common JavaScript-in-PDF / XFA RCE primitive against Adobe Reader on the recipient side, even when the server is safe. - Use
.docx/.xlsx/.zipextraction withunziporpython -m zipfilewithout a path-traversal-safe extractor. Zip slip (CVE-2018-1002201) extracted files outside the target directory through../entries. - Use S3 / GCS presigned upload URLs without a strict
Content-Typesigned condition and a fixed object-key prefix. Without the conditions, the client can upload anything to any key.
KNOWN FALSE POSITIVES
- Internal-only admin uploads (e.g. an ops dashboard) may legitimately trust file extension because the trust boundary is the SSO + IP allowlist. Document this as a deliberate decision in the endpoint.
- Some integrations (e.g. exporting CSV from BI tools) need to round-trip user-supplied filenames; preserve them in metadata, but the on-disk name must still be a UUID.
- Tarballs / DEBs / RPMs in a build pipeline don't need AV scan — the trust boundary is the build pipeline's signing key, not the AV.
What ships with it: 1 file
1.0 KB alongside SKILL.md
- metadata.json1.0 KB