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