Security
Security at Learning Whistle
Last updated: May 2026
This page describes the technical and organisational controls we use to protect your data. We publish this in the spirit of transparency — not as marketing copy, but as an honest account of what we do and where our gaps are. Our controls are designed to align with OWASP Top 10 (2021), OWASP ASVS Level 2, and Google CASA Tier 2.
7-page technical whitepaper — suitable for compliance reviews, enterprise procurement, and school IT departments.
Reporting a Vulnerability
If you discover a security issue, please report it privately before disclosing publicly. Email learn@learningwhistle.com with the subject line [SECURITY] followed by a brief description.
We commit to:
- Acknowledging your report within 48 hours
- Providing a remediation timeline within 7 days
- Crediting you in our changelog (unless you prefer anonymity)
- Not taking legal action against good-faith researchers
A machine-readable disclosure policy is published at /.well-known/security.txt in accordance with RFC 9116.
Platform Architecture
Learning Whistle runs entirely on Google Cloud Platform. All compute is serverless — there are no long-lived servers to patch. The stack is selected to minimise attack surface and shift security responsibility to hardened managed services.
- Hosting: Google Cloud Run — managed containers, automatic TLS, no persistent servers
- Authentication: Firebase Auth with Google OAuth only — no passwords
- Database: Cloud Firestore — server-enforced security rules, strict per-user isolation
- Secrets: Google Secret Manager — credentials mounted at runtime, never in source code
- AI: Google Gemini — server-side only, user content never leaves the GCP boundary
- Payments: Stripe — card data is never stored by or transmitted through our servers
Authentication & Session Management
Aligned with OWASP A07 and ASVS §2–3.
- Google OAuth only. There are no passwords to breach or reset flows to abuse. MFA is enforced at the Google identity provider layer.
- Session cookies are
HttpOnly,Secure, andSameSite=Strict— unreadable by JavaScript, mitigating XSS-based session theft. - Every protected route performs a live revocation check against the identity provider — not just JWT signature validation.
- Account suspensions take effect promptly without requiring a forced logout.
- Age gate: Users who report being under 13 have their identity token revoked server-side immediately. No data is written before this gate passes. Reference: FTC COPPA Rule (16 CFR Part 312).
Authorization — Least Privilege at Every Layer
Aligned with OWASP A01 and ASVS §4.
Database Security Rules
- Users can only read and write their own documents — enforced at the database layer, not the application layer
- Users cannot self-promote to admin or modify their own token balances client-side
- Admin and audit log collections block all client access — server-only via Admin SDK
- Audit trail collections are append-only — no updates or deletes permitted
Cloud Infrastructure Access Control
All cloud service accounts follow a least-privilege model: the application runtime has only the minimum permissions required for its function, scoped to specific resources. The CI/CD deploy pipeline uses keyless authentication via Workload Identity Federation — no static service account keys exist in the repository or CI environment. Aligned with OWASP A02 and ASVS §2.10.
AI Content Safety
Learning Whistle is a 13+ platform that uses AI to generate educational content. We take age-appropriate content safety seriously and operate the following controls:
- Google Gemini safety filters: All AI generation routes use Google Gemini with safety filtering enabled. Content that triggers safety thresholds is blocked before reaching the user.
- Topic sanitisation: User-supplied topics are sanitised and capped at a fixed length before being forwarded to the model. The platform operates within 20 defined learning categories — arbitrary topic combinations are constrained by design.
- Educational framing: All generation prompts explicitly instruct the model to produce factual, educational content appropriate for the user's selected learning level (Grade 3 to Grade 12).
- Server-side output handling: AI-generated content is written to the database via server-side Admin SDK before being served. It is never streamed directly to the client without server-side routing.
- No user-to-user content: The platform has no in-app social feed, no user-submitted content displayed to other users, and no direct messaging. Official Learning Whistle social media accounts are external to the platform and subject to each platform's own moderation controls.
We acknowledge that AI-generated content safety is an evolving area. We monitor OWASP Top 10 for LLM Applications guidance and will strengthen these controls as standards mature.
Data Protection
Aligned with OWASP A02, ASVS §6–8, and GDPR Article 5 (data minimisation).
- At rest: All data encrypted with AES-256 using Google-managed keys
- In transit: TLS 1.2+ enforced end-to-end, independently verified at SSL Labs A+; HSTS with one-year max-age and preload
- Payments: Card data handled entirely by Stripe (PCI DSS certified) — never stored by us
- Secrets: All server credentials in Google Secret Manager — never in source code or image layers
- Profile photo: Stored as a reference URL only — never displayed on any public surface
- Account deletion: Learning progress and personal data deleted within 30 days of a verified deletion request (GDPR Article 17)
Application Security Controls
Aligned with OWASP A03, A05, ASVS §5, §11, §13, and §14.
- Session verification: Every protected route verifies the caller's session before executing any logic. No code path reaches user data without a valid, non-revoked identity assertion.
- Rate limiting: AI generation and write-path routes are rate-limited per authenticated user and per anonymous IP, enforced server-side. Exceeded limits return HTTP 429.
- Input validation: All API inputs validated with schema-based validation before any business logic runs. Category selection validated against a fixed allow-list. Invalid payloads return HTTP 400 with no internal detail exposed.
- AI prompt injection mitigation: User-supplied content is sanitised before reaching the AI model. Content is capped at a fixed character limit. Reference: OWASP LLM01:2025.
- Security headers: All responses include a Content Security Policy, HSTS, frame denial, content-type sniff protection, and Permissions-Policy.
- Framework vulnerability patching: Known framework-level vulnerabilities are patched immediately upon public disclosure. Security updates are monitored continuously via automated tooling.
Supply Chain Security
Aligned with OWASP A06, A08, and ASVS §14.
- Dependabot monitors all dependencies continuously for CVEs
- Critical advisory watcher sends notification within 2 hours of any new high or critical CVE
- Semgrep SAST runs on every push using OWASP Top 10, TypeScript, Node.js, and secrets rulesets
- Exact lockfile installs in all pipelines — no silent dependency drift
- Every deploy audits dependencies and blocks on high-severity findings
Incident Response
Breach notification follows GDPR Article 33 standards regardless of user geography.
- Affected users notified within 72 hours of confirming a breach
- Public post-mortem published within 30 days of resolution
- Payment data is Stripe-scoped — their breach notification process applies to card data
Known Gaps
We believe transparency includes honesty about what we have not yet done:
- Nonce-based Content Security Policy — planned Q3 2026 (ASVS §14.4)
- CBC cipher suite disablement — requires Cloudflare Advanced Certificate Manager ($10/month subscription). Deferred pending business case. Mitigated in practice: Cloudflare preference order prioritises GCM ciphers; CBC is only negotiated with clients that do not support GCM. SSL Labs A+ rating is maintained.
- Staging environment for DAST testing — planned Q4 2026 (ASVS §14.2)
- Formal third-party CASA Tier 2 assessment — targeted 2027
Questions? Email learn@learningwhistle.com — we respond to all security enquiries within 48 hours.