Skip to content

feat: security hardening for feedback worker — OWASP input validation, abuse rate limits, CSRF protection, secrets management #113

Description

@wcmchenry3-stack

In plain English

Harden the feedback worker against abuse: validate and sanitize all inputs, enforce strict rate limits, protect against CSRF, and ensure no secrets leak in responses or logs.

User story

As a developer, I want the feedback worker to be secure against common web attack vectors so that bad actors cannot spam issues, inject malicious content, or extract secrets through the feedback endpoint.

Context

The feedback worker (#109) is a public HTTP endpoint that creates GitHub issues and calls the Anthropic API. Without hardening it is a potential abuse surface. This story applies OWASP Top 10 mitigations appropriate for a Cloudflare Worker context.

Part of: #46
Depends on: #109 (worker core must exist first)

Acceptance criteria

Input validation (OWASP A03 — Injection)

  • All string fields (title, description, suggestedTranslation, etc.) sanitized: strip HTML tags, null bytes, control characters before processing
  • Field length limits enforced server-side: title ≤ 200 chars, description ≤ 5000 chars, sessionLogs ≤ 50 KB, screenshotBase64 ≤ 2 MB
  • appId validated against an allowlist (gaming_app, book_app) — unknown values return 400 immediately (no downstream calls)
  • type validated against allowlist (bug, feature, localization) — unknown values return 400
  • locale (for localization type) validated against BCP 47 format
  • JSON schema validation on the full request body — malformed payloads return 400 with a safe error message (no stack traces)

Rate limiting (OWASP A04 — Insecure Design)

CSRF protection

  • CORS Access-Control-Allow-Origin restricted to ALLOWED_ORIGINS env var values — wildcard * not permitted
  • Content-Type: application/json enforced — requests with other content types rejected with 415
  • Origin header validated against ALLOWED_ORIGINS on every POST request

Secrets management

  • ANTHROPIC_API_KEY and GITHUB_TOKEN stored only as Cloudflare Worker secrets (via wrangler secret put) — confirmed not in source or wrangler.toml
  • No secret values appear in worker logs (mask tokens in any log statements)
  • Error responses to clients never include internal details (API keys, model names, KV key names)

Abuse / content policy

Headers

  • Worker sets X-Content-Type-Options: nosniff on all responses
  • Worker does not expose Server header or Cloudflare worker internals

Technical notes

  • JSON schema validation: use ajv or a lightweight alternative compatible with Cloudflare Workers runtime (no Node.js built-ins)
  • IP hashing: crypto.subtle.digest('SHA-256', encoder.encode(ip)) — available in Workers runtime
  • Distributed burst limit: requires Cloudflare Durable Objects (strongly consistent counter) or accept KV eventual consistency risk (document the trade-off decision)
  • Prompt injection: add a check in the Claude validation prompt instructing Claude to flag any submission that appears to be attempting to override its instructions

Test coverage

Unit tests

  • Title > 200 chars returns 400
  • Description > 5000 chars returns 400
  • Unknown appId returns 400, no GitHub or Anthropic API calls made
  • Malformed JSON returns 400
  • Non-allowlisted Origin header returns 403
  • Content-Type not application/json returns 415
  • IP hash: confirm raw IP is not stored in KV

E2E tests

  • Rate limit: 6th submission within window returns 429 with Retry-After header

Performance

  • Input validation (schema check + sanitization) adds < 5 ms overhead to request processing

Regression

  • Valid submissions still succeed end-to-end after all hardening is applied

Documentation to update

  • CLAUDE.md — add security posture section for cloudflare/feedback-worker/ documenting rate limit config, CORS config, and secret names
  • cloudflare/feedback-worker/wrangler.toml — comment block listing all required secrets and their purpose

Unknowns / needs investigation

  • Cloudflare Workers AJV compatibility — verify which JSON schema libraries work in the Workers runtime without bundling Node.js polyfills
  • Durable Objects cost/complexity vs. KV eventual consistency for the distributed burst limit — make explicit decision and document

Out of scope

  • WAF rules at the Cloudflare zone level (out of scope for this codebase — a network-level concern)
  • DDoS mitigation (Cloudflare handles this at the platform level)
  • API key rotation automation

Dependencies

Definition of done

  • All acceptance criteria met
  • Test coverage added per above
  • Documentation updated
  • CI green (lint, type check, tests)
  • PR reviewed and merged to dev

Metadata

Metadata

Assignees

No one assigned

    Labels

    infrastructureCI/CD and tooling improvementspriority:highHigh priority - implement firstsecuritySecurity-related issues and improvements

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions