Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add tmj-90/gaffer --skill file-uploadsgit clone --depth 1 https://github.com/tmj-90/gafferWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/tmj-90/gaffer/file-uploads)<a href="https://agentmods.dev/skills/tmj-90/gaffer/file-uploads"><img src="https://agentmods.dev/badge/skills/tmj-90/gaffer/file-uploads/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/tmj-90/gaffer/file-uploads"><img src="https://agentmods.dev/badge/skills/tmj-90/gaffer/file-uploads.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00093 | $0.01525 |
| Opus 5.5 | $0.00037 | $0.00610 |
| Sonnet 5.5 | $0.00019 | $0.00305 |
| Haiku 4.5 | $0.00009 | $0.00153 |
Grade A, and why
file-uploads scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 16d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 98 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Handle file uploads and downloads safely
An upload is untrusted input that is large, binary, and often stored for years. Limit it before you read it, verify what it really is, write it under a name you chose, atomically, in a place that cannot execute, and serve it back with headers that stop the browser guessing. Source: OWASP File Upload Cheat Sheet; OWASP ASVS 5 V5 (file handling).
Steps
- Use the repo's storage and upload path. Object storage with presigned URLs, a
local store behind an abstraction, or existing multipart middleware. Call
search_lorefor bucket layout, key naming and size limits. Do not add a second storage mechanism. - Authorise and limit before reading. Check the caller may upload here (the
security-authzskill) and that the form is CSRF-protected if cookie-authenticated. Enforce a maximum body size at the edge (proxy and framework), a maximum part count, and a request timeout; reject with413without buffering. Stream to storage; never hold a whole file in memory. For presigned uploads, sign the exact key,Content-Typeand size limit (acontent-length-rangePOST-policy condition, or a signedContent-Lengthfor PUT), with a short expiry. - Validate content, not labels. Allow-list extensions (after normalising case and
rejecting double extensions like
x.jpg.php, NUL bytes and:), check the declaredContent-Typeagainst the allow-list, then detect the real type from the bytes (magic numbers) and reject any mismatch. None of these alone is sufficient. - Defuse the dangerous formats. Images: cap pixel dimensions before decoding
(decompression bombs), then decode and re-encode to strip metadata and payloads.
Archives: cap total uncompressed size and entry count, and reject entries whose
resolved path escapes the target directory (zip slip). SVG, HTML and XML are active
content: refuse them, sanitise them, or serve them only as attachments; parse XML with
external entities disabled (XXE). CSV/XLSX imports: cap rows and cell size, treat every
cell as untrusted text, and on export prefix cells starting with
=,+,-,@, tab or CR with'(formula injection). - Generate the storage key; never trust the filename. Key = random id (UUID) plus an extension derived from the detected type. Keep the original name only as sanitised display metadata (length-capped, no path separators, no leading dot).
- Write atomically and collision-free. Concurrent uploads are normal. Write to a
unique temporary key (random suffix, never a timestamp or the user's name), then
rename/commit to the final key; object storage
PUTis already atomic per key. Insert the metadata row in the same transaction that marks the file available, or use apending → availablestatus so a half-written file is never served. Replacing a file (a new avatar) writes a new key and swaps the pointer with a conditional update (WHERE version = ?); it never overwrites bytes in place. Orphaned temp objects are swept by a job (thescheduled-jobsskill). - Store where nothing executes. Object storage or a directory outside the web root, no execute permission, no per-directory config overrides; private by default and access-checked on every read.
- Serve safely. Presigned GET with a short expiry, or an authenticated route that
sets
Content-Disposition: attachmentfor anything not meant to render inline, the stored detectedContent-Type,X-Content-Type-Options: nosniff, and ideally a separate cookieless origin with a restrictive CSP (default-src 'none') so a malicious file cannot run in the app's origin. - Scan and quarantine where the repo requires it (malware scan, CDR, moderation)
asynchronously through a job (the
background-jobsskill); the file stays unavailable until cleared.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 16d ago Changed · +30 lines 850f7782593a
- 19d ago First seen · 68 lines · 93 tokens per session scan A ff99f02a511e
file-uploads is a skill published in the GitHub repository tmj-90/gaffer (2 stars, last pushed 17d ago), licensed Apache-2.0. It adds 93 tokens to every session and 1,525 once invoked, about $0.0004 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-28.
Other skills, from other repositories
bulwark-brainstorm
Role-based brainstorming with dual modes: --scoped (sequential Task tool, 5 roles) and --exploratory (Agent Teams peer debate, 4 roles). Use for feasibility assessment and idea validation.
plan-creation
Create structured implementation plans via a 4-role scrum team (Product Owner, Architect, Eng/Delivery Lead, QA/Critic) with optional Agent Teams peer debate mode.
anthropic-validator
Validates Claude Code assets (skills, hooks, agents, commands, MCP servers, plugins) against official Anthropic standards. Fetches latest docs dynamically and produces structured validation reports.
create-subagent
Generates single-purpose Claude Code sub-agents for use via the Task tool. Use when creating dedicated sub-agents, scaffolding agent definitions, or generating agents with diagnostics and permissions setup.
test-audit
Audit test suites for T1-T4 violations using AST analysis, mock detection, and multi-stage synthesis. Invoke when user asks to audit tests, check test quality, find mock violations, review test effectiveness, or inspect test suites for over-mocking. Triggers automatic rewrites when quality gates fail.
code-review
Comprehensive code review with distinct aspect based sections. Use when reviewing code, checking for security issues, finding type safety problems, auditing code quality, or when user asks to review code, PRs or changes. Three-phase workflow runs static tools, LLM judgment, and writes diagnostic log.