Added AI skills
This commit is contained in:
90
.agents/skills/zod/references/schema-string-validations.md
Normal file
90
.agents/skills/zod/references/schema-string-validations.md
Normal 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)
|
||||
Reference in New Issue
Block a user