Added AI skills

This commit is contained in:
Jose Selesan
2026-09-04 16:49:24 -03:00
parent 778f3fdcad
commit dfa7f73ebb
368 changed files with 51560 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
---
title: Apply String Validations at Schema Definition
impact: CRITICAL
impactDescription: Unvalidated strings allow SQL injection, XSS, and malformed data; validating at schema level catches issues at the boundary
tags: schema, string, validation, security
---
## Apply String Validations at Schema Definition
Plain `z.string()` accepts any string including empty strings, extremely long strings, and malicious content. Apply constraints like `min()`, `max()`, `email()`, `url()`, or `regex()` at schema definition to reject invalid data at the boundary.
**Incorrect (no string validations):**
```typescript
import { z } from 'zod'
const commentSchema = z.object({
author: z.string(), // Empty string passes
email: z.string(), // "not-an-email" passes
content: z.string(), // 10MB string passes, script tags pass
website: z.string().optional(), // "javascript:alert(1)" passes
})
// All of these pass validation
commentSchema.parse({
author: '', // Empty - who wrote this?
email: 'invalid', // Not a real email
content: '<script>alert("XSS")</script>'.repeat(100000), // XSS + huge
website: 'javascript:void(0)', // Dangerous URL
})
```
**Correct (string validations applied):**
```typescript
import { z } from 'zod'
const commentSchema = z.object({
author: z.string()
.min(1, 'Author is required')
.max(100, 'Author name too long'),
email: z.string()
.email('Invalid email address'),
content: z.string()
.min(1, 'Comment cannot be empty')
.max(5000, 'Comment too long'),
website: z.string()
.url('Invalid URL')
.refine(
url => url.startsWith('http://') || url.startsWith('https://'),
'Only http/https URLs allowed'
)
.optional(),
})
// Invalid data is rejected
commentSchema.parse({
author: '',
email: 'invalid',
content: '',
})
// ZodError with all violations listed
```
**Common string validations:**
```typescript
z.string().min(1) // Non-empty (most common need)
z.string().max(255) // Database varchar limit
z.string().length(36) // Exact length (UUIDs)
z.string().email() // Email format
z.string().url() // URL format
z.string().uuid() // UUID format
z.string().cuid() // CUID format
z.string().regex(/^[a-z0-9-]+$/) // Custom pattern (slugs)
z.string().startsWith('https://') // Prefix check
z.string().endsWith('.pdf') // Suffix check
z.string().includes('@') // Contains check
z.string().trim() // Strips whitespace (transform)
z.string().toLowerCase() // Normalizes case (transform)
```
**When NOT to use this pattern:**
- When accepting arbitrary user content for display only (sanitize on output instead)
- When building a passthrough/proxy that shouldn't validate content
Reference: [Zod API - Strings](https://zod.dev/api#strings)