UNPKG

@awesomate/hosting-mcp

Version:

Awesomate MCP server — lets Claude manage your Awesomate WordPress hosting, plan, limits, n8n automations, and build Node/static apps + databases

58 lines (48 loc) • 3.01 kB
# Security checklist — walk this before promoting to prod Two layers guard prod. The **automated gate** runs in every app's deploy workflow (`scripts/security-check.mjs` — report-only on dev/staging, BLOCKING on `main`, plus `npm audit --audit-level=critical`). This checklist is the **human layer**: the things a scanner cannot see. Walk it with the user in plain language before merging staging → main. ## What the automated gate already catches (don't re-litigate) Committed secrets / a tracked `.env` / private keys · SQL built by interpolation or concatenation · `eval` / `new Function` · shell exec with interpolated input · critical dependency advisories. If the prod deploy fails on the gate, read the Actions log — every finding prints its fix. **Never remove or bypass the gate step to make a deploy pass.** ## The human checks (scanner-blind spots) 1. **Authorization, not just authentication.** Logged-in is not allowed. For every route that reads/writes data: could user A pass user B's id and touch B's data? Filter by the session's user id server-side, never trust an id from the request body. 2. **Every input validated at the edge.** Each POST/PATCH handler starts with a zod `safeParse`, with sane max lengths. No handler touches `await c.req.json()` raw. 3. **Secrets flow one way.** Values live in env vars (set via `awesomate_app_set_env`), are never logged, never echoed in responses, never sent to the browser. 4. **Rendering is escape-safe.** Browser code uses `textContent` / `createElement` for user data; server HTML never string-interpolates user input without escaping. 5. **The n8n webhook is not world-callable.** If n8n is attached, the workflow checks the `X-Awesomate-Webhook-Secret` header (set during attach). Test: call the webhook without the header — it must refuse. 6. **Public API surface is intentional.** api-only starter: is `API_KEY` set for prod, or is a public API genuinely intended? CORS open on purpose? 7. **Sensitive data is minimized.** Only collect what the app needs; if it stores personal data, tell the user plainly: connections are TLS and secrets are encrypted, but the DATABASE is not blanket-encrypted at rest — sensitive fields deserve app-level encryption (ask before adding). 8. **Errors don't leak.** 500 responses return a generic message, not stack traces or SQL (the starters already do this — keep it). ## Static sites No server code, so the gate doesn't run — the risks are the lead form's webhook (point 5) and third-party scripts (don't add any that aren't needed). Never put an API key in page JavaScript: anything in a static page is public. ## How to talk about it Non-technical user — say what you checked, not the jargon: *"Before making it live I checked that people can only see their own data, that the contact form can't be abused, and that your API key never appears anywhere public. The deploy pipeline also scans every release automatically."*