Input validation
Security skills for AI coding agents. Install once, write secure code every time.
npx -y skills add hereshecodes/secureskills --skill input-validationAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 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.
What its author says it does
Copied from the file, not written here
Use when processing user input, form data, file uploads, or query parameters
SKILL.md
2.9 KB, as published. Nobody here has run it
Input Validation
Validate everything that enters your system. Server-side. Every time. Client-side validation is UX, not security.
Related: injection-prevention, xss-csrf, api-security, security-context
Rule 1: Validate Server-Side (Always)
Client-side validation can be bypassed with one curl command.
// WRONG — only client-side validation
<input type="email" required> // Attacker skips this entirely
// RIGHT — validate on the server
function createUser(req, res) {
const { email, name } = req.body;
if (!email || !isValidEmail(email)) return res.status(400).json({ error: 'Valid email required' });
if (!name || name.length > 100) return res.status(400).json({ error: 'Name required, max 100 chars' });
// proceed
}
Rule 2: Whitelist, Don't Blacklist
Reject everything except what you expect. Blacklists always miss something.
// WRONG — trying to block bad characters
if (input.includes('<script>')) reject();
// RIGHT — only allow expected format
if (!/^[a-zA-Z0-9\s\-]{1,100}$/.test(input)) reject();
Rule 3: Validate Type, Length, and Range
Every field has constraints. Enforce them.
# WRONG — no validation
age = request.form['age']
save_user(age=age)
# RIGHT — validate type, range, and length
age = request.form.get('age')
if not age or not age.isdigit() or not (0 <= int(age) <= 150):
return bad_request('Age must be a number between 0 and 150')
save_user(age=int(age))
Rule 4: Validate File Uploads
Check extension, MIME type, and file signature. Never trust the filename.
// WRONG — trusts the file extension
if (file.originalname.endsWith('.jpg')) saveFile(file);
// RIGHT — check MIME type AND magic bytes
const allowedMimes = ['image/jpeg', 'image/png', 'image/webp'];
if (!allowedMimes.includes(file.mimetype)) reject();
const fileBuffer = fs.readFileSync(file.path);
const type = await fileTypeFromBuffer(fileBuffer);
if (!type || !allowedMimes.includes(type.mime)) reject();
Rule 5: Sanitize Before Storage, Escape Before Display
Two different operations. Both required.
// Sanitize on input (remove dangerous content)
const cleanHtml = DOMPurify.sanitize(userInput);
await saveToDb(cleanHtml);
// Escape on output (prevent XSS in different contexts)
element.textContent = storedValue; // HTML context
Quick Reference
| Do | Don't |
|---|---|
| Validate server-side on every request | Rely on client-side validation alone |
| Whitelist expected formats | Blacklist known bad patterns |
| Enforce type, length, and range limits | Accept any value from the client |
| Check file MIME type AND magic bytes | Trust file extensions |
| Sanitize on input, escape on output | Skip either step |
| Return clear error messages | Silently accept bad input |