sast-analysis
Perform codebase analysis and architecture mapping as the first phase of a security assessment. Explores the tech stack,…
Detect insecure file upload vulnerabilities in a codebase using a three-phase approach: discovery (find all upload sites), batched verify (check extension bypass and related issues in parallel subagents, 3 sites each), and merge (consolidate batch results). Requires
Claude Code
$ npx -y skills add utkusen/sast-skills --skill sast-fileupload --agent claude-code
Codex
$ npx skills add utkusen/sast-skills --skill sast-fileupload -a codex -y
Cursor
$ npx skills add utkusen/sast-skills --skill sast-fileupload -a cursor -y
Gemini CLI
$ npx skills add utkusen/sast-skills --skill sast-fileupload -a gemini-cli -y
GitHub Copilot
$ npx skills add utkusen/sast-skills --skill sast-fileupload -a github-copilot -y
OpenCode
$ npx skills add utkusen/sast-skills --skill sast-fileupload -a opencode -y
Windsurf
$ npx skills add utkusen/sast-skills --skill sast-fileupload -a windsurf -y
name: sast-fileupload description: >- Detect insecure file upload vulnerabilities in a codebase using a three-phase approach: discovery (find all upload sites), batched verify (check extension bypass and related issues in parallel subagents, 3 sites each), and merge (consolidate batch results). Requires sast/architecture.md (run sast-analysis first). Outputs findings to sast/fileupload-results.md. Use when asked to find file upload, unrestricted upload, or extension bypass bugs.
You are performing a focused security assessment to find insecure file upload vulnerabilities in a codebase. This skill uses a three-phase approach with subagents: **discovery** (find all places where uploaded files are received and stored), **batched verify** (check bypass vectors in parallel batches of up to 3 upload sites each), and **merge** (consolidate batch reports into one results file).
**Prerequisites**: `sast/architecture.md` must exist. Run the analysis skill first if it doesn't.
---
Insecure file upload occurs when an application accepts files from users without properly validating or restricting what can be uploaded, allowing an attacker to upload executable or malicious files. The most critical outcome is **Remote Code Execution (RCE)**: an attacker uploads a web shell (e.g., a `.php` file) and the server executes it when accessed via a direct URL.
The core pattern: *a user-supplied file reaches a storage location without adequate extension validation, and the stored file is accessible or executable.*
Do not flag these as file upload vulnerabilities:
When you see these patterns together, the code is likely **not vulnerable**:
**1. Allowlist of safe extensions (most important)**
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'pdf'}
ext = filename.rsplit('.', 1)[-1].lower()
if ext not in ALLOWED_EXTENSIONS:
abort(400)**2. Magic byte / file content validation (defense in depth)**
import magic
mime = magic.from_buffer(file.read(2048), mime=True)
ALLOWED_MIMES = {'image/png', 'image/jpeg', 'image/gif'}
if mime not in ALLOWED_MIMES:
abort(400)**3. Filename sanitization using a trusted library**
from werkzeug.utils import secure_filename filename = secure_filename(file.filename) # strips path separators and dangerous chars
**4. Storing uploads outside the web root**
/var/uploads/ ← not served by the web server /var/www/html/ ← web root (do NOT store uploads here)
**5. Serving uploads through a controlled endpoint with Content-Disposition**
@app.route('/download/<filename>')
def download(filename):
return send_from_directory(UPLOAD_FOLDER, filename,
as_attachment=True) # forces download, prevents execution**6. Renaming the file to a server-generated UUID**
import uuid stored_name = str(uuid.uuid4()) + '.jpg' # extension is server-controlled, not user-controlled
---
# VULNERABLE: no extension check, file stored in web-accessible directory
@app.route('/upload', methods=['POST'])
def upload():
f = request.files['file']
f.save(os.path.join('static/uploads', f.filename))
return 'uploaded'
# VULNERABLE: content-type only check (trivially bypassed with curl -H)
@app.route('/upload', methods=['POST'])
def upload():
f = request.files['file']
if f.content_type not in ['image/png', 'image/jpeg']:
abort(400)
f.save(os.path.join('static/uploads', f.filename))
return 'uploaded'
# VULNERABLE: blocklist — .phtml/.phar/.php5 not covered
BLOCKED = {'.php', '.sh', '.exe'}
@app.route('/upload', methods=['POST'])
def upload():
f = request.files['file']
ext = os.path.splitext(f.filename)[1].lower()
if ext in BLOCKED:
abort(400)
f.save(os.path.join('static/uploads', f.filename))
return 'uploaded'
# SECURE: allowlist + sanitized filename + outside web root
ALLOWED = {'png', 'jpg', 'jpeg', 'gif'}
UPLOAD_FOLDER = '/var/uploads' # outside web root
@app.route('/upload', methods=['POST'])
def upload():
f = request.files['file']
filename = secure_filename(f.filename)
ext = filename.rsplit('.', 1)[-1].A collection of agent skills that turn your LLM coding assistant into a fully functional SAST scanner to find vulnerabilities in your codebase. Works natively with Claude Code, Codex, Opencode, Cursor and any other assistant that supports agent skills.
Perform codebase analysis and architecture mapping as the first phase of a security assessment. Explores the tech stack,…
Detect business logic vulnerabilities in a codebase using a three-phase approach: threat modeling (domain analysis and attack…
Detect GraphQL injection vulnerabilities in a codebase using a three-phase approach: recon (confirm GraphQL usage and find unsafe…
Detect hardcoded sensitive data (API keys, access tokens, private keys, passwords, etc.) in publicly accessible code — frontend…
Detect Insecure Direct Object Reference (IDOR) vulnerabilities in a codebase using a three-phase approach: recon (find…
Use for authorized security assessment of REST, GraphQL, WebSocket, or SOAP APIs, including discovery, authentication,…
Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys)…
Clean and finalize authorized natural-language text intended for readers by auditing suspicious invisible Unicode and rewriting…