| name | astro-security |
| description | Security patterns for Astro lead generation websites on Cloudflare. Forms, headers, bot protection, GDPR. Use for any production lead gen site. |
Astro Security Skill
Security patterns for lead generation sites.
Core Rules (Non-Negotiable)
| Violation | Result |
|---|---|
| Production form without Turnstile + honeypot | FAIL |
| Secret exposed client-side | FAIL |
| User input stored without server validation | FAIL |
| Indexable staging environment | FAIL |
| Missing security headers | FAIL |
| Cookie banner missing before analytics | FAIL |
Form Security (Required)
Every form must have:
| Protection | Implementation |
|---|---|
| Turnstile | Cloudflare captcha (invisible mode) |
| Honeypot | Hidden field, reject if filled |
| Rate limit | Max 5 submissions/IP/hour |
| Validation | Server-side Zod, never trust client |
| Sanitize | Strip HTML, trim whitespace |
See references/forms.md.
Security Headers (Required)
CSP Rules:
- MUST disallow inline scripts unless hashed
- MUST restrict script-src to required domains only
- MUST test in report-only before enforcement
Add to _headers:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy: [see references]
Strict-Transport-Security: max-age=31536000; includeSubDomains
Environment Variables
# .env.example (commit this)
TURNSTILE_SITE_KEY=
TURNSTILE_SECRET_KEY=
RESEND_API_KEY=
GOOGLE_SHEETS_ID=
# .env (never commit)
# Add to .gitignore
Rules:
- Never expose secrets client-side
- Use
import.meta.envfor public vars only - Validate all env vars on build
Bot Protection
Cloudflare (free tier):
- Bot Fight Mode: ON
- Security Level: Medium
- Challenge Passage: 30 minutes
Application level:
- Turnstile on all forms
- Honeypot fields
- Rate limiting per IP
- Block empty referrer (optional)
Third-Party Scripts
- Use SRI (integrity hash) for CDN scripts
- Load async/defer
- Minimize scripts
- Review GTM tags regularly
GDPR Compliance
Required:
- Cookie banner (before non-essential cookies)
- Privacy policy page
- Form consent checkbox (if marketing)
- Data retention policy
- Right to deletion process
Cookie categories:
| Type | Consent | Examples |
|---|---|---|
| Necessary | No | Session, CSRF |
| Analytics | Yes | GA4, Hotjar |
| Marketing | Yes | Meta Pixel, Google Ads |
See references/gdpr.md.
Input Validation
Never: Trust client-side alone, store raw input, render unsanitized HTML.
See forms.md for Zod schemas.
File Uploads
If needed: Max 5MB, whitelist types, rename files, store outside webroot.
Staging Protection
Password protect OR Cloudflare Access. Add noindex, block in robots.txt.
Error Handling
- Error messages MUST NOT reveal stack traces or internals
- API errors MUST return generic messages (
Something went wrong) - Detailed errors allowed ONLY in development
- 404/500 pages must not leak tech stack info
Dependencies
- Minimize third-party scripts
- Remove unused dependencies before launch
- Review third-party access quarterly
- Prefer self-hosted over CDN when possible
Definition of Done
Security requirements before launch:
- Turnstile on all forms
- Honeypot fields added
- Rate limiting configured
- Security headers set
- HTTPS enforced
- .env in .gitignore
- No secrets in client code
- Cookie banner working
- Privacy policy linked
- Staging protected
- Error pages don't leak info
References
- forms.md — Form security patterns
- headers.md — CSP and headers
- gdpr.md — GDPR compliance