1 · Threat model
LLMs produce markup. Markup goes into web apps. The two together mean prompt injection and HTML injection are the primary classes of attack Morphis defends against:
- Prompt injection — A hostile prompt tries to make the model produce unsafe markup.
- HTML injection — Generated content contains scripts, event handlers, or dangerous URLs.
- Style leakage — Scoped CSS escapes into the host application's design system.
- Data exfiltration — Generated content tries to read the parent page's cookies or DOM.
2 · Defense in depth
Morphis applies four independent layers. Any one of them stopping an attack is enough; together they form a chain that's very hard to bypass.
Layer 1 — LLM behavioral constraints
The system prompt forbids script, onclick, onerror,javascript: URIs, and any event-handler attributes. It caps output to 4,096 tokens and requires strict JSON.
Layer 2 — Sanitization
The backend passes the model output through a bleach + BeautifulSoup AST walker that removes scripts, event handlers, hostile CSS, javascript: URLs, and data:text/html links. CSS url() values are validated against an explicit allowlist — only data:image/* values survive.
If the sanitized output is empty, the API fails loudly — no partial payload is ever served.
Layer 3 — Scoped CSS
All generated styles are wrapped under .morphis-root, the rendered component's outer wrapper class. Your page's button, input, and global styles cannot collide with generated components.
Layer 4 — Iframe sandbox
The SDK mounts generated content inside sandbox="allow-scripts" iframes with srcdoc. No top-level navigation, no form submission to your origin, no access to your DOM, cookies, or localStorage. Communication happens only via scoped postMessage.
3 · API key hygiene
- Keys are hashed at rest with SHA-256 — only the hash exists in our database.
- Shown to you once at creation; after that, it's permanently unreadable.
- Revocation in the dashboard is instantaneous — our runtime reads from the database on every call.
- Each key is scoped to a tenant, so one leaked key cannot affect another customer's quota.
4 · In transit
- All traffic uses HTTPS with TLS 1.3 (forced via ALB redirect).
- WebSocket connections are not used. The API is stateless REST with a short timeout.
- Password hashing uses PBKDF2-SHA256 (100,000 iterations) with per-user salting.
5 · Responsible disclosure
Found a security issue? We take it seriously. Email ibrahim@getmorphis.com with:
- The vulnerability class (XSS, SSRF, injection, auth bypass, etc.)
- Steps or payload that prove it
- The affected endpoint or component
We respond within 48 hours. We do not currently run a formal bug bounty — but we credit researchers in a Hall of Fame on this page.