Security Sweep — qody.ba (MC #107297)
Security Sweep — qody.ba (MC #107297)
Date: 2026-08-18
Canonical repository: Azure DevOps QODY, GitHub private mirror
Production merge: 630f4cff5d7f1bfd6cf163e503223cbf23c4d671
Azure PR: #350 · CI build: #1120
Baseline
- Repository already private; reachable history and working candidate had zero Gitleaks findings.
- Live
wrangler.tomlreturned its exact control-file content. - Unknown/sensitive paths returned the landing homepage with HTTP 200 because no 404 page existed.
- Landing responses lacked CSP, HSTS, frame and permissions protection.
- Root asset directory mixed runtime files with Wrangler config, Functions, TypeScript source and generated caches.
- Contact Function threw on malformed JSON, had no OPTIONS/body/rate controls, logged name/venue/email/IP/country, and returned success without checking provider delivery.
apps/landing/was excluded from repository Semgrep scans.
Remediation
- Created physical runtime-only
apps/landing/public/root; Functions, config, source, tests and package metadata remain outside it. - Updated Wrangler output and DEPLOY-MAP to deploy only
public/after npm audit/preflight/type/tests. - Added true 404, CSP/HSTS/browser headers and defense-in-depth
.assetsignore. - Hardened contact Function with streaming 8 KiB bound, strict JSON/field/email/phone validation, origin/method controls, honeypot, rate limit, no PII logs, provider timeout/status enforcement, generic failures and no-store/security headers.
- Added honeypot consistently to HTML, TypeScript source and generated app.js; preflight asserts runtime/source consistency.
- Added pinned test/type tooling and 7 contact-control tests; npm audit zero.
- Added SHA-pinned GitHub mirror security CI and removed canonical landing from
.semgrepignore. - Canonical Azure build policy #1120 passed; AzDO PR #350 merged without bypass and GitHub main mirror fast-forwarded.
- Added exact Cloudflare edge tombstone for stale cached
/wrangler.tomluntil cache expiry.
Verification
- Local preflight/type/tests/audit: PASS; 7/7 tests.
- Semgrep landing: 0 findings / 0 errors.
- Gitleaks current/all reachable history: 0.
- Local Wrangler smoke: runtime root 200; config/source/package/unknown paths 404; Function controls pass.
- Independent review: PASS, P0=0, P1=0.
- Cloudflare preview Playwright: 21/21 PASS, zero console errors.
- Production Playwright: 21/21 PASS, zero console errors.
- Production sensitive/control paths: 404 after edge routing.
Boundaries and residuals
- In-memory rate limiting is best-effort per Worker isolate; add Cloudflare Rate Limiting/Turnstile only under a separate abuse-volume decision.
- MailChannels remains a third-party delivery dependency; Function now fails honestly on non-2xx delivery.
- Existing payment webhook replay finding MC #106337 remains separate and was not duplicated or modified.
- Canonical dirty developer checkout was not reset or cleaned; remediation used an isolated worktree.
Evidence
/Users/makinja/system/evidence/107297/
No comments to display
No comments to display