Skip to main content

Security Sweep — snowit.ba (MC #107296)

Security Sweep — snowit.ba (MC #107296)

Date: 2026-08-17
Tenant: SnowIT-BA (operated, not owned by ALAI)
Repository: snowitba/snowit-sitePRIVATE
Production merge: c9d6724738b994264cab057b9093fc4b825480db
Pull request: snowitba/snowit-site#2

Trigger

A domain-specific sweep was ordered using the same gated principle as alai.no. The read-only baseline proved that the Vercel root deployment publicly served CLAUDE.md, BUILD-BLUEPRINT.md, and DEPLOY-MAP.md, while the public GitHub repository exposed the same operational history.

Confirmed baseline

  • GitHub repository public with zero forks.
  • Three internal Markdown files returned exact source content from production.
  • Eight tenant-local secret findings: one expired Vercel OIDC token plus active ignored Terraform variables/state.
  • Eight high production dependency advisories.
  • Forty-four initial Semgrep findings, including IMDSv1, Host-header, h2c upgrade, API validation/CORS/HTML sinks, and XML parsing.
  • Canonical tenant checkout was six commits behind with unrelated tracked/untracked work; it was preserved untouched.

Remediation

Repository and deployment

  • Made the repository private; anonymous raw access now returns 404.
  • Removed tracked CLAUDE.md and .claude/** from current source.
  • Expanded .vercelignore to exclude agent metadata, internal docs, infrastructure, scripts, state, backups, tests and evidence.
  • Added deterministic deploy preflight, sensitive-path tombstones, real 404 page, global CSP/HSTS/browser headers, SHA-pinned security CI and Dependabot.
  • Vercel local build proved sensitive files absent from static output.

Public APIs and protected team page

  • Hardened contact, calculator, audit, Meta lead and tim-login endpoints with strict methods/origins/content types/body and field limits, safe email/phone/URL validation, rate controls, no-store/security headers, privacy-safe logs and generic errors.
  • Hardened mail transports with file/URL access disabled and upgraded the active mail dependency.
  • tim-login now uses constant-time password comparison, SameSite=Strict/HttpOnly/Secure 8-hour cookie, bounded body and origin/rate controls.
  • Existing middleware path normalization remained intact; no-cookie clean/encoded/dot-segment tim variants all resolve to the login page.

Dependencies and infrastructure

  • Removed two unused vulnerable dependencies and unused vulnerable framework/type tooling.
  • Complete npm audit now reports zero vulnerabilities.
  • Enforced IMDSv2 on BookStack, Planka and Documenso EC2 definitions.
  • Pinned Nginx upstream Host headers to configured server names.
  • Normalized WebSocket Upgrade/Connection values to literal allowlists; independent review adjudicated the two syntax-only h2c warnings as mitigated.
  • Replaced standard XML parsing with defusedxml.

Tenant-local cleanup

  • Deleted the expired Vercel OIDC token.
  • Restricted active ignored Terraform variables/state to mode 0600.
  • Restricted prospect/lead output to 0700 directories and 0600 files.
  • No tenant credential value is recorded in this page or evidence summaries.

Verification

  • Local API security tests: 19/19 PASS.
  • Preview Playwright: 34/34 PASS, zero console errors.
  • Production Playwright: 34/34 PASS, zero console errors.
  • GitHub Security checks: PASS.
  • Vercel automatic production deployment: READY.
  • Gitleaks reachable history/current candidate: 0 findings.
  • npm audit: 0 vulnerabilities.
  • Semgrep: P0=0 / P1=0; two WebSocket warnings independently adjudicated as mitigated.
  • Independent review: PASS, P0=0, P1=0.

Residual low risks / follow-up

  1. In-memory serverless rate controls are best-effort per instance. A separate tenant-approved Vercel WAF/central rate-limit design is recommended if abuse volume increases.
  2. Active Terraform state remains local but ignored and mode 0600. Migration to encrypted remote state requires a separate tenant infrastructure change and validated AWS ownership.
  3. The canonical dirty SnowIT checkout remains preserved; it must be reconciled by its owner before fast-forwarding to main.

Evidence

  • /Users/makinja/system/evidence/107296/
  • /tmp/evidence-107296-preview/browser-verification.json
  • /tmp/evidence-107296-production/browser-verification.json