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:
| Credential | Prefix | Where it lives | What it can do |
|---|---|---|---|
| Public key | i18n_pk_ | HTML <head>, client-side JS | Fetch label files from CDN |
| Secret token | i18n_at_ | Environment variable, CI secrets | Full 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:
| Scope | Permitted operations |
|---|---|
read | List profiles, list keys, get coverage, read drafts |
write | Create/update/delete keys, create drafts |
publish | Publish profiles and drafts to CDN |
translate | Run AI translation jobs |
admin | All 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_idfrom 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:
- Create a new token in the dashboard
- Update all systems using the old token (CI secrets, server environment variables)
- 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.