input-validation — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited input-validation (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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
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
}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();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))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();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| 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 |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.