ShipEasy Docs
Advanced

Security

ShipEasyI18n security model — API key types, domain allowlists, CDN security, CSP integration, and secret management.

Credential types

ShipEasyI18n uses two types of credentials with separate trust levels:

CredentialPrefixWhere it livesWhat it can do
Public keyi18n_pk_HTML <head>, client-side JSFetch label files from CDN
Secret tokeni18n_at_Environment variable, CI secretsFull management API access

Public keys are safe to expose. They appear in your HTML and identify your account for CDN routing. They cannot authenticate management operations.

Secret tokens must never be exposed. Store them in environment variables only. Never commit to version control, log to console, or include in client-side code.


Public key domain allowlist

Restrict a public key to specific origins to prevent other sites from using your CDN quota:

PATCH /v1/api-keys/public/:id
Authorization: Bearer i18n_at_...
Content-Type: application/json

{
  "allowedDomains": ["myapp.com", "staging.myapp.com"]
}

The CDN loader script sends an Origin header on every request. Requests from origins not in the allowlist receive a 403 response with no label data.

For local development, add localhost and 127.0.0.1 explicitly, or use a separate development public key with no domain restrictions.


Secret token scopes

Limit the blast radius of a leaked token by issuing tokens with only the required scopes:

ScopePermitted operations
readList profiles, list keys, get coverage, read drafts
writeCreate/update/delete keys, create drafts
publishPublish profiles and drafts to CDN
translateRun AI translation jobs
adminAll of the above + manage team members and billing

For CI/CD, use a token with only read, write, and publish scopes — never admin.

# Create a CI token
i18n keys create --label "GitHub Actions" --scopes read,write,publish

CDN delivery security

HTTPS everywhere

All CDN endpoints are HTTPS only. The loader script (cdn.i18n.shipeasy.ai/v1/loader.js) and label files (cdn.i18n.shipeasy.ai/v1/labels/...) redirect HTTP requests to HTTPS.

Subresource Integrity

Published label files include a SHA-256 hash in their JSON body ("hash": "sha256-..."). The loader script verifies this hash before applying labels — a tampered CDN response is rejected.

Content Security Policy

The ShipEasyI18n loader needs two CSP allowances:

Content-Security-Policy:
  script-src 'self' https://cdn.i18n.shipeasy.ai;
  connect-src 'self' https://cdn.i18n.shipeasy.ai https://api.i18n.shipeasy.ai;

If you use a strict CSP with script-src 'nonce-...', add a nonce to the loader script tag and omit the domain allowance:

<script
  src="https://cdn.i18n.shipeasy.ai/v1/loader.js"
  data-key="i18n_pk_..."
  data-profile="en:prod"
  nonce="abc123"
  async
></script>

The nonce must match the script-src 'nonce-...' value in your CSP header.


Data isolation

Each ShipEasyI18n account's data is fully isolated:

  • API: every database query is scoped to account_id from the verified JWT
  • CDN: label files are stored at paths that include your public key; only the key holder can publish to that path
  • Drafts: accessible only to authenticated users of your account
  • AI Discovery manifest: public by design — contains only non-secret data (key names, coverage percentages, framework)

Secret management best practices

Environment variables

# .env.local (gitignored)
ShipEasyI18n_SECRET_TOKEN=i18n_at_your_secret_token
ShipEasyI18n_KEY=i18n_pk_your_public_key
# GitHub Actions
# Add ShipEasyI18n_SECRET_TOKEN as a repository secret (Settings → Secrets)
# Access in workflow:
env:
  ShipEasyI18n_SECRET_TOKEN: ${{ secrets.ShipEasyI18n_SECRET_TOKEN }}

Token rotation

Rotate tokens periodically or immediately if you suspect exposure:

  1. Create a new token in the dashboard
  2. Update all systems using the old token (CI secrets, server environment variables)
  3. Revoke the old token

Revoking takes effect immediately — the old token returns 401 Unauthorized on its next use.

Audit log

All management API operations are logged with the token ID, user ID, IP address, and timestamp. View the audit log at Settings → Audit Log or via API:

GET /v1/audit?limit=50
Authorization: Bearer i18n_at_...
{
  "data": [
    {
      "id": "evt_abc123",
      "action": "profile.publish",
      "actor": { "type": "token", "id": "tok_xyz", "label": "GitHub Actions" },
      "resource": { "type": "profile", "name": "en:prod" },
      "ip": "185.199.108.0",
      "createdAt": "2026-04-11T10:05:00Z"
    }
  ]
}

Responsible disclosure

Found a security vulnerability? Email security@i18n.shipeasy.ai with:

  • Description of the vulnerability
  • Steps to reproduce
  • Potential impact

We respond within 24 hours and aim to patch critical issues within 72 hours. We do not pursue legal action against good-faith security researchers.

ShipEasyI18n is hosted on Cloudflare infrastructure. Cloudflare's DDoS protection, WAF, and network-level security apply to all ShipEasyI18n endpoints.