Skip to content

Open-source MCP server (BYO-AI) + security hardening (RLS, SSRF, coupons, rate-limits, admin auth, CI)#1

Merged
vedantggwp merged 3 commits into
masterfrom
cc/interesting-dirac-3a1619
Jun 11, 2026
Merged

Open-source MCP server (BYO-AI) + security hardening (RLS, SSRF, coupons, rate-limits, admin auth, CI)#1
vedantggwp merged 3 commits into
masterfrom
cc/interesting-dirac-3a1619

Conversation

@vedantggwp

@vedantggwp vedantggwp commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Turns NeuroEdge into an open-source, bring-your-own-AI agent and closes the audit's security findings. Every change here was verified by an independent adversarial review pass (details at bottom).

1. neuroedge-mcp-server — open-source, BYO-AI accessibility agent

Standalone MCP server exposing neuroedge_scan_website over stdio. Returns structured axe-core/WCAG findings; the host AI (Claude Desktop, Cursor, any model) does the translation. No server-side LLM, no keys, nothing leaves the user's machine. Self-contained (extracts cleanly), SSRF-hardened, Chromium lazy-loaded. 37 tests, tsc clean, real stdio handshake verified, npm-publish-ready (MIT, name available).

2. Supabase RLS lockdown (critical — applied to live DB)

Live DB had RLS disabled + anon full CRUD (migration 002 never applied). 003_lockdown_rls.sql revokes anon grants, enables RLS, hardens the coupon fn. Applied + verified live (anon privileges (none); advisor rls_disabled_in_public cleared). Client reads moved server-side (/api/scans/[id], /api/report-status, service-role + rate-limited).

3. Hosted-product hardening (audit C2–C5) + CI

  • C2 SSRF (the gap still lived in the VPS engine): scan-service now blocks private IPv6 + broader IPv4, resolves A+AAAA, and re-validates every redirect hop via request interception. (41/41 bypass probes blocked: decimal/octal/hex IP literals, IPv4-mapped, userinfo@, redirects, metadata.)
  • C4 coupon idempotency: webhook increments coupon usage exactly once (pre-insert lookup + 23505 handling); 004_reports_unique_session.sql adds UNIQUE(stripe_session_id) to close the concurrent-retry race.
  • C3 rate limiting: added to coupon-validate, estimate, regenerate (20/min) and admin-login (5/15min).
  • C5 admin auth: cookie is now an HMAC-signed, expiring, timing-safe token — no longer the plaintext password.
  • CI: .github/workflows/ci.yml runs tsc + tests + build for all three packages on push/PR.

Verification (independent agent, adversarial)

3-package builds green · scan-service 52 tests · mcp-server 37 tests · app next build clean · 41/41 SSRF bypass attempts blocked · coupon increment traced exactly-once across all paths · admin token forgery infeasible · PR-scope confirmed (no stray edits). Two defects were caught mid-review (non-idempotent webhook, gitignored CI) and fixed + re-verified before this update.

Go-live checklist (owner: you — one-way doors / your creds)

  • Merge this PR
  • Apply supabase/migrations/004 to the live DB (like 003) — closes the coupon concurrent-retry race
  • Redeploy the app to Vercel (required for results/report pages against the locked DB)
  • Unpause the Supabase project
  • npm login → publish neuroedge-mcp-server (optional: dedicated public repo)
  • Rotate possibly-exposed secrets (Supabase/Resend/LLM)

Not addressed here (follow-ups)

LLM provider consolidation (Anthropic↔Gemini drift), and the low-severity sub-resource SSRF note (DNS-resolving private hostname for embedded sub-resources only; main navigation + redirects are fully checked).

…tor)

Standalone MCP server that exposes the NeuroEdge scan engine as a single
tool (neuroedge_scan_website) over stdio. Returns structured axe-core/WCAG
findings for the host AI to translate — no server-side LLM, no API keys,
no data leaves the user's machine. Works with any MCP host (Claude Desktop,
Cursor, etc.).

- Self-contained: own copy of scan/score/CMS logic; no Supabase/LLM deps.
- SSRF-hardened: blocks private/reserved IPv4 AND IPv6, resolves A+AAAA,
  and re-validates every redirect hop (fixes the redirect/rebind gap).
- Chromium lazy-loaded so the server starts and lists tools instantly.
- 37 tests (SSRF guard, scoring, full MCP round-trip via InMemoryTransport);
  tsc clean; real stdio handshake verified.
- npm-publish ready (MIT, dist-only tarball).
The live DB had RLS disabled and the public anon key held full CRUD on
scans/reports/coupons (migration 002 was never applied), exposing customer
PII and allowing anyone to mint coupons or truncate tables.

- supabase/migrations/003_lockdown_rls.sql: revoke all anon/authenticated
  grants, enable RLS on all three tables, and pin increment_coupon_usage's
  search_path. Applied to the live project and verified (anon privileges
  now none; advisor rls_disabled_in_public cleared).
- Because anon can no longer read, move the two client reads server-side:
  new app/api/scans/[id] (GET) and app/api/report-status (POST, rate-limited)
  use the service-role client; scan/[id] and report/[id] pages now fetch
  these routes instead of the anon Supabase client.
- Verified with next build (type-check + 15 routes compile).

Note: the live Vercel app must be redeployed for the results/report pages
to work against the locked DB, and the project unpaused when going live.
Hardening pass over the hosted product (audit findings C2–C5) plus CI.
All changes verified by an independent adversarial review: 3-package
builds green, scan-service 52 tests pass, 41/41 SSRF bypass probes blocked,
app next build clean.

scan-service (C2 — SSRF, previously only in mcp-server):
- url-validator.ts: block private IPv6 (::1, fc00::/7, fe80::/10, IPv4-mapped)
  + broaden IPv4 (CGNAT/0.0.0.0/8/etc); resolve A AND AAAA; export isPrivateIp
  + checkHostSafety. scanner.ts: request interception re-validates every
  main-frame redirect and aborts private targets.

app (C3/C4/C5):
- C4: webhook now increments coupon usage idempotently — pre-insert lookup +
  23505 handling, increment only on a confirmed new insert; migration 004 adds
  UNIQUE(stripe_session_id) to close the concurrent-retry race (apply at deploy).
- C3: rate-limit coupon-validate, estimate, regenerate (20/min) and admin-login
  (5/15min).
- C5: admin cookie is now an HMAC-signed, expiring token (lib/admin-auth.ts),
  verified timing-safe; no longer stores the plaintext password.

- .github/workflows/ci.yml: tsc + tests + build for all three packages
  (also fixes .gitignore so .github is tracked).
@vedantggwp vedantggwp changed the title Open-source MCP server (BYO-AI) + Supabase RLS lockdown Open-source MCP server (BYO-AI) + security hardening (RLS, SSRF, coupons, rate-limits, admin auth, CI) Jun 11, 2026
@vedantggwp vedantggwp merged commit e4ac4ba into master Jun 11, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant