npx skills add ...
npx skills add mapbox/mapbox-agent-skills --skill mapbox-token-security
Security best practices for Mapbox access tokens, including scope management, URL restrictions, rotation strategies, and protecting sensitive data. Use when creating, managing, or advising on Mapbox token security.
npx skills add mapbox/mapbox-agent-skills --skill mapbox-token-security
This skill provides security expertise for managing Mapbox access tokens safely and effectively.
Characteristics:
When to use:
Allowed scopes:
styles:tiles - Display style tiles (raster)styles:read - Read style specificationsfonts:read - Access Mapbox fontsdatasets:read - Read dataset datavision:read - Vision API accessCharacteristics:
When to use:
Common scopes:
styles:write - Create/modify stylesstyles:list - List all stylestokens:read - View token informationtokens:write - Create/modify tokensCharacteristics:
When to use:
Always grant the minimum scopes needed:
❌ Bad:
✅ Good:
Public Map Display (client-side):
Style Management (server-side):
Token Administration (server-side):
Read-Only Access:
URL restrictions limit where a public token can be used, preventing unauthorized usage if the token is exposed.
✅ Recommended patterns:
❌ Avoid these:
Create separate tokens for each environment:
✅ DO:
❌ DON'T:
Example: Secure Environment Variable:
✅ DO:
❌ DON'T:
Example: Safe Client Usage (Vite):
Note: This example uses Vite. For Next.js, CRA, Angular, or a plain
window.MAPBOX_ACCESS_TOKEN/ CDN setup, see Token Management. Do not chainimport.meta.envandprocess.envin one expression — the unused path throwsReferenceErrorin the browser.
Agents often assign mapboxgl.accessToken and call new mapboxgl.Map(...) with no check. That fails closed as a blank canvas with no UI error.
Always:
pk. in source)accessToken and construct the mapToken Creation:
Token Management:
new mapboxgl.MapMonitoring:
Incident Response:
For detailed guidance on specific topics, load these references as needed:
references/token-management.md — Bundler-specific env var names and access patterns (Vite / Next / CRA / Angular / CDN). Load when: wiring tokens in a different framework than the Vite example above.references/rotation-monitoring.md — Token rotation strategies (zero-downtime + emergency), monitoring metrics, alerting rules, and monthly/quarterly audit checklists. Load when: implementing rotation, setting up monitoring, or conducting audits.references/incident-response.md — Step-by-step incident response plan and common security mistakes with code examples. Load when: responding to a token compromise, reviewing code for security issues, or training on anti-patterns.Invoke this skill when:
// Only what's needed for displaying a map
{
scopes: ['styles:read', 'fonts:read'];
}
// Add 'styles:tiles' if your map uses raster tile sources
{
scopes: ['styles:read', 'fonts:read', 'styles:tiles'];
}{
"scopes": ["styles:read", "fonts:read", "styles:tiles"],
"note": "Public token for map display",
"allowedUrls": ["https://myapp.com/*"]
}{
"scopes": ["styles:read", "styles:write", "styles:list"],
"note": "Backend style management - SECRET TOKEN"
}{
"scopes": ["tokens:read", "tokens:write"],
"note": "Token management only - SECRET TOKEN"
}{
"scopes": ["styles:list", "styles:read", "tokens:read"],
"note": "Auditing/monitoring - SECRET TOKEN"
}https://myapp.com/* # Production domain
https://*.myapp.com/* # All subdomains
https://staging.myapp.com/* # Staging environment
http://localhost:* # Local development* # No restriction (insecure)
http://* # Any HTTP site (insecure)
*.com/* # Too broad// Production
{
note: "Production - myapp.com",
scopes: ["styles:read", "fonts:read"],
allowedUrls: ["https://myapp.com/*", "https://www.myapp.com/*"]
}
// Staging
{
note: "Staging - staging.myapp.com",
scopes: ["styles:read", "fonts:read"],
allowedUrls: ["https://staging.myapp.com/*"]
}
// Development
{
note: "Development - localhost",
scopes: ["styles:read", "fonts:read"],
allowedUrls: ["http://localhost:*", "http://127.0.0.1:*"]
}# .env (NEVER commit this file)
MAPBOX_SECRET_TOKEN=sk.ey...
# .gitignore (ALWAYS include .env)
.env
.env.local
.env.*.local// Public token with URL restrictions - SAFE (Vite)
const mapboxToken = import.meta.env.VITE_MAPBOX_ACCESS_TOKEN;
// Guard BEFORE constructing the map — missing tokens otherwise yield a silent blank map
if (!mapboxToken || mapboxToken === 'YOUR_MAPBOX_ACCESS_TOKEN') {
throw new Error('Missing VITE_MAPBOX_ACCESS_TOKEN — set it in env before creating the map');
}
mapboxgl.accessToken = mapboxToken;