Appearance
Are you an LLM? You can read better optimized documentation at /docs/custom-widgets/v2/content-security.md for this page in Markdown format
Content Security
The platform automatically checks your extension code — widgets, scripts, and stylesheets — for security issues before publishing. This keeps your community safe without requiring you to configure anything.
What the Platform Checks
Every time you push code, the platform runs a series of checks before publishing your extensions. The sections below describe each check and the specific rules enforced.
Content Scanning
Your code is scanned for patterns that could harm your community.
Widgets: For source widgets (directories of files), the platform scans HTML and JavaScript files (.html, .htm, .js, .mjs, .jsx). CSS, images, and fonts are not scanned since they cannot contain executable patterns.
Scripts: JavaScript files are scanned for executable patterns and credential exposure.
Stylesheets: CSS files are scanned for unsafe rules or obfuscated content.
The platform checks for:
| Category | What It Detects | Example |
|---|---|---|
| Crypto mining | Scripts that use visitor devices to mine cryptocurrency | CoinHive, WebAssembly mining modules |
| Data exfiltration | Code that collects and sends user data to external servers | Keyloggers, cookie theft, form data harvesting |
| Phishing | Fake login forms or redirects that assign external URLs to window.location | Credential harvesting pages, window.location.href = "https://..." |
| Obfuscation | Heavily encoded or hidden code that obscures its purpose | eval(atob(...)), eval(String.fromCharCode(...)) chains |
| External script loading | Loading JavaScript from untrusted external sources | <script src="..."> from unknown domains |
| Credential exposure | Hardcoded secrets, API keys, tokens, or high-entropy strings | AWS keys, private keys, JWTs, password = "..." |
TIP
Loading scripts from popular libraries like cdn.jsdelivr.net, cdnjs.cloudflare.com, unpkg.com, and esm.sh is allowed. Only untrusted sources are flagged.
TIP
Template-style placeholders like ${API_KEY} are not flagged as credentials. UUIDs and sequential strings are also excluded from credential detection.
Security Headers
The platform adds browser-level protections to every widget response:
| Header | What It Does |
|---|---|
| Content-Security-Policy | Controls which scripts, styles, and resources your widget can load |
| X-Content-Type-Options | Prevents the browser from guessing file types (blocks MIME sniffing) |
| Referrer-Policy | Limits what URL information is shared when navigating away |
| X-Frame-Options | Controls where your widget can be embedded |
Size Limits
Each extension has maximum size limits to ensure fast loading and prevent abuse:
- Widget directories: Limited to 100 files and 10 MB total
- Individual files: 512 KB limit
- Scripts and stylesheets: No individual size limit, but counted toward total repository size
Path Validation
Widget file paths must stay within the widget directory. Paths containing ../ (directory traversal) or starting with / (absolute paths) are rejected.
Immediate Removal
When you delete an extension, it is immediately removed from the platform. Previously cached copies are invalidated so stale content is never served after removal.
What This Means for Your Code
Most extension code works without any changes. Here is what to keep in mind:
| What you want to do | Works? | Notes |
|---|---|---|
Inline <script> tags (widgets) | Yes | Inline scripts are allowed by the security policy |
Inline <style> tags (widgets) | Yes | Inline styles are allowed by the security policy |
Relative asset paths (./styles.css) | Yes | Standard relative paths work as expected |
| Load from trusted libraries | Yes | cdn.jsdelivr.net, cdnjs.cloudflare.com, unpkg.com, esm.sh are allowed |
| Load scripts from unknown domains | No | External scripts from untrusted sources are blocked |
Use eval() | No | Blocked by the Content Security Policy |
Use new Function() from strings | No | Blocked by the Content Security Policy |
| Hardcode API keys or tokens | No | Detected as credential exposure — use Connectors instead |
What Happens When Content Is Rejected
If the platform detects a security issue in your code, the entire build fails — no extensions from that push are published. Previously published content remains available until a clean push succeeds.
The error message includes the category of the issue:
Widget 'my-widget' rejected: content policy violation (categories: obfuscation)1
How to Resolve Each Category
| Category | What to change |
|---|---|
crypto_mining | Remove cryptocurrency mining scripts entirely |
data_exfiltration | Remove code that sends user data to external servers. If you need to send data, use a Connector instead |
phishing_redirect | Remove fake login forms or deceptive redirects. Use your platform's built-in authentication |
obfuscation | Replace obfuscated code with readable source. If you use a bundler, check that its output is not overly minified |
external_script_loading | Load scripts from trusted sources only, or bundle dependencies into your widget directory |
credential_exposure | Remove hardcoded secrets from your code. Use environment variables, a secrets manager, or Connectors to handle credentials securely |
Best Practices
- Write readable code — Heavily minified or encoded code may trigger the obfuscation check. Standard minification from popular bundlers (webpack, Vite, esbuild) is fine
- Use relative paths for assets — Store CSS, JS, and images alongside your extension and reference them with relative paths
- Bundle external dependencies — Instead of loading scripts from external URLs, include them in your repository
- Use Connectors for external data — Instead of making direct API calls from widget code, use Connectors to route requests securely through the backend
- Never hardcode secrets — API keys, tokens, and passwords should never appear in code. Use Connectors or environment variables instead
Next Steps
- Error Codes — Full error reference including content scan rejections
- Build & Publish — The publishing pipeline
- Common Issues — Common issues and solutions

