Skip to content

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:

CategoryWhat It DetectsExample
Crypto miningScripts that use visitor devices to mine cryptocurrencyCoinHive, WebAssembly mining modules
Data exfiltrationCode that collects and sends user data to external serversKeyloggers, cookie theft, form data harvesting
PhishingFake login forms or redirects that assign external URLs to window.locationCredential harvesting pages, window.location.href = "https://..."
ObfuscationHeavily encoded or hidden code that obscures its purposeeval(atob(...)), eval(String.fromCharCode(...)) chains
External script loadingLoading JavaScript from untrusted external sources<script src="..."> from unknown domains
Credential exposureHardcoded secrets, API keys, tokens, or high-entropy stringsAWS 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:

HeaderWhat It Does
Content-Security-PolicyControls which scripts, styles, and resources your widget can load
X-Content-Type-OptionsPrevents the browser from guessing file types (blocks MIME sniffing)
Referrer-PolicyLimits what URL information is shared when navigating away
X-Frame-OptionsControls 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 doWorks?Notes
Inline <script> tags (widgets)YesInline scripts are allowed by the security policy
Inline <style> tags (widgets)YesInline styles are allowed by the security policy
Relative asset paths (./styles.css)YesStandard relative paths work as expected
Load from trusted librariesYescdn.jsdelivr.net, cdnjs.cloudflare.com, unpkg.com, esm.sh are allowed
Load scripts from unknown domainsNoExternal scripts from untrusted sources are blocked
Use eval()NoBlocked by the Content Security Policy
Use new Function() from stringsNoBlocked by the Content Security Policy
Hardcode API keys or tokensNoDetected 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)

How to Resolve Each Category

CategoryWhat to change
crypto_miningRemove cryptocurrency mining scripts entirely
data_exfiltrationRemove code that sends user data to external servers. If you need to send data, use a Connector instead
phishing_redirectRemove fake login forms or deceptive redirects. Use your platform's built-in authentication
obfuscationReplace obfuscated code with readable source. If you use a bundler, check that its output is not overly minified
external_script_loadingLoad scripts from trusted sources only, or bundle dependencies into your widget directory
credential_exposureRemove 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

Gainsight CC Developer Portal