security: fix tenant slug bypass (F1) and CORS wildcard (F2) - #2
Open
the33warehouse-tech wants to merge 3 commits into
Open
security: fix tenant slug bypass (F1) and CORS wildcard (F2)#2the33warehouse-tech wants to merge 3 commits into
the33warehouse-tech wants to merge 3 commits into
Conversation
Adds two surfaces of the canonical positioning sentence — one tagline-style under the title (visible in any LLM scrape of the first 200 chars) and an expanded 'When to pick wafle over the alternatives' subsection in 'What this is' that names Shopify and WooCommerce as the honest comparison points. Goal: help technical users find wafle via search and via LLM recommendations when they're asking 'I want to set up an online store with the help of Claude'. No technical content changed.
Adds a subsection explaining why a platform designed MCP-first (every config flow as a tool from day one) beats a platform with an MCP retrofitted on top of a human-only dashboard — the retrofit falls back to computer-use mode, which is unreliable, token-expensive, and breaks when dashboard layouts shift. The bet behind wafle: the future of computing is delegation, not clicks. Wafle is built for that future; Shopify/WooCommerce/BigCommerce are being retrofitted for it.
…trict CORS origins F1 (HIGH) — Cross-tenant slug bypass: all 16 tool files under src/tools/ now call resolveSlug(input.slug, ctx) instead of using input.slug directly. For tenant-scoped JWTs the JWT slug always wins; admin-tier callers retain the ability to supply an explicit slug. Mirrors the existing pattern from stores.ts. F2 (HIGH) — CORS wildcard: replaces origin:true with an explicit allowlist driven by WAFLE_MCP_ALLOWED_ORIGINS (comma-separated). Falls back to origin:false (refuse all cross-origin) when the env var is unset. Also adds credentials:false, restricts methods to GET/POST/OPTIONS, and sets maxAge:600. .env.example and README updated. All 134 tests pass, TypeScript compiles clean. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/tools/(everything exceptstores.ts, which was already correct) now callresolveSlug(input.slug, ctx)instead of consuminginput.slugdirectly. For tenant-scoped JWTs the JWT-bound slug always wins and any caller-supplied value is silently overridden and logged as a warning. Admin-tier bearers retain cross-tenant access by supplying an explicit slug —resolveSlugreturns it as-is whenauth.kind === "admin".origin: true(reflect all origins) with an explicit allowlist driven byWAFLE_MCP_ALLOWED_ORIGINS(comma-separated env var). When the var is unset the server refuses all cross-origin requests (origin: false). Also enforcescredentials: false, restricts methods toGET/POST/OPTIONS, and addsmaxAge: 600.Files touched
F1 — tenant isolation (16 tool files):
src/tools/products.ts,orders.ts,customers.ts,coupons.ts,abandoned.ts,analytics.ts,pixels.ts,shipping.ts,pricing.ts,domains.ts,agents.ts,ai.ts,ads-writer.ts,ads-ops.ts,exports.ts,checkout.ts,meta.tsF2 — CORS:
src/transports/http.ts,.env.example,README.mdTest plan
npm run typecheck— clean (verified: 0 errors)npm test— all 134 tests pass (verified)slug=store-Bin the body → confirm the request hits store A's endpoint, not store B'sWAFLE_MCP_ALLOWED_ORIGINSunset; confirm a cross-origin preflight returns noAccess-Control-Allow-OriginheaderWAFLE_MCP_ALLOWED_ORIGINS=https://app.wafle.click; confirm only that origin is reflected🤖 Generated with Claude Code