-
Notifications
You must be signed in to change notification settings - Fork 4
Security
John Williams edited this page Mar 6, 2026
·
1 revision
If you discover a security vulnerability, please report it responsibly:
- Do NOT open a public issue
- Email: See SECURITY.md
- Include: description, reproduction steps, impact assessment
All Google Ads write operations follow the Confirm → Execute → Post-check protocol:
- Confirm: Agent describes the change, shows preview, asks for explicit user approval
-
Execute: Only runs with
confirmed: true— never auto-executes - Post-check: Pre-write snapshot is compared against post-write state
- No wildcard origins — all endpoints validate against an allowlist
- Allowlist:
googleadsagent.ai,www.googleadsagent.ai,*.pages.dev,localhost:8788 - Middleware enforces CORS at the gateway level
Per-endpoint rate limits enforced in _middleware.js:
| Endpoint | Limit |
|---|---|
/api/brain |
30 req/min |
/api/gads |
40 req/min |
/api/auth |
20 req/min |
/api/crux |
20 req/min |
| Other APIs | 30 req/min |
| What | Algorithm | Where |
|---|---|---|
| OAuth tokens (stored) | AES-256-GCM |
auth.js, notifications.js
|
| BYOK API keys (client) | AES-256-GCM | Browser sessionStorage
|
| Session tokens | crypto.randomUUID() |
Server-generated |
- GAQL injection prevention: Date range values whitelisted
-
Path traversal: Report keys validated (blocks
..,/,\) - URL validation: SSRF protection blocks private/internal addresses in webhooks
- XSS prevention: HTML/SVG escaping on user-controlled chart inputs
- Google OAuth 2.0: SSO via Google with encrypted token storage
- Session fixation prevention: Server generates session IDs (never accepts client-provided)
- Open redirect protection: Return URLs validated against path allowlist
- Sensitive data in redirects: No email/name in redirect parameters
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy: [strict policy with explicit allowlists]
- Store credentials in
.envfile (gitignored) - Never commit credentials to version control
- Use environment variables in production
- Rotate refresh tokens if compromised
- OAuth tokens encrypted with AES-256-GCM at rest
- BYOK keys encrypted client-side before storage
- Cloudflare Secrets for server-side API keys
- Session IDs are server-generated UUIDs
| Item | Risk | Mitigation |
|---|---|---|
| Google Ads write access | High | CEP protocol, pre-write snapshots, rollback log |
| API key exposure | High | AES-256-GCM encryption, gitignore, Cloudflare Secrets |
| CORS | Medium | Origin allowlist, no wildcards |
| Rate limits | Medium | Per-endpoint limits, IP-based |
| XSS in charts | Low | HTML/SVG escaping |
| Hardcoded emails | Low | Operational only, no secrets |