Guide
API Key Rotation, Audit Logging, and Credential Management
Automated email workflows handle sensitive data. This guide covers the operational security practices needed to run Nylas CLI in production: API key rotation without downtime, audit logging that satisfies SOC 2, credential storage best practices, data handling policies, and permission scoping. Works with Gmail, Outlook, Exchange, Yahoo, iCloud, and IMAP.
By Prem Keshari
Where Nylas CLI stores credentials
Nylas CLI stores API keys and OAuth grant tokens in ~/.nylas/config.json. The file is created with 0600 permissions (read/write for the current user only). Verify:
# Check config file permissions
ls -la ~/.nylas/config.json
# Expected: -rw------- 1 youruser yourgroup ... config.json
# Fix permissions if needed
chmod 600 ~/.nylas/config.json
# View current auth (never displays full key)
nylas auth whoamiIn CI/CD environments, always use environment variables instead of config files:
# CI/CD: pass API key via environment variable
export NYLAS_API_KEY="$NYLAS_API_KEY_SECRET"
nylas auth config --api-key "$NYLAS_API_KEY"
nylas auth whoamiRotate API keys without downtime
According to NIST SP 800-57, cryptographic keys should be rotated at least every 90 days. Nylas supports concurrent active keys during the rotation window:
#!/bin/bash
# rotate-key.sh — zero-downtime API key rotation
# Step 1: Generate new key in Nylas dashboard
# Step 2: Update CLI config
nylas auth config --api-key "$NEW_API_KEY"
# Step 3: Verify
if nylas auth whoami > /dev/null 2>&1; then
echo "New key verified"
else
echo "ERROR: rolling back"
nylas auth config --api-key "$OLD_API_KEY"
exit 1
fi
# Step 4: Test read operation
if nylas email list --limit 1 --json > /dev/null 2>&1; then
echo "Read confirmed with new key"
else
echo "ERROR: rolling back"
nylas auth config --api-key "$OLD_API_KEY"
exit 1
fi
echo "Rotation complete. Revoke old key in dashboard."Build an audit trail for SOC 2
SOC 2 Type II requires an audit trail of all access to sensitive data. Log every operation with metadata but never log email content or PII:
#!/usr/bin/env python3
"""Audit-logged Nylas CLI wrapper."""
import json, subprocess, os, datetime
AUDIT_LOG = os.path.expanduser("~/.nylas/audit.log")
def nylas_audited(args: list[str]) -> subprocess.CompletedProcess:
result = subprocess.run(["nylas"] + args, capture_output=True, text=True)
# Log metadata only — no email content or PII
entry = {
"timestamp": datetime.datetime.utcnow().isoformat() + "Z",
"user": os.getenv("USER", "unknown"),
"command": " ".join(args),
"exit_code": result.returncode,
"hostname": os.uname().nodename,
}
with open(AUDIT_LOG, "a") as f:
f.write(json.dumps(entry) + "\n")
return result
result = nylas_audited(["email", "list", "--limit", "10", "--json"])
messages = json.loads(result.stdout)
print(f"Read {len(messages)} messages (logged to audit trail)")Scope permissions with minimum-privilege grants
Create separate grants for different use cases. A monitoring script shouldn’t have send permissions:
# List active grants
nylas auth list
# Check scopes for current grant
nylas auth whoami --json | jq '.scopes'
# Revoke a grant when no longer needed
nylas auth logout --grant-id <grant-id>Data handling policies
- Never log email bodies, subjects, or sender addresses. Log message IDs and counts only.
- Sanitize before piping to external services. Strip PII before sending to LLMs, analytics, or logging.
- Use temporary files with restricted permissions.
mktemp+chmod 600+ delete after processing. - Don’t store email content in version control. Add output files to
.gitignore.
# Safe: process without persisting
EMAILS=$(nylas email list --json --limit 10)
echo "Processed $(echo "$EMAILS" | jq 'length') messages"
# If temp files needed, use restrictive permissions
TMPFILE=$(mktemp /tmp/nylas-XXXXXX.json)
chmod 600 "$TMPFILE"
nylas email list --json --limit 10 > "$TMPFILE"
# ... process ...
rm -f "$TMPFILE"CI/CD security patterns
# GitHub Actions example
name: Email Report
on:
schedule:
- cron: '0 9 * * 1'
jobs:
report:
runs-on: ubuntu-latest
steps:
- name: Install Nylas CLI
run: curl -fsSL https://cli.nylas.com/install.sh | bash
- name: Configure auth
run: nylas auth config --api-key "$NYLAS_API_KEY"
env:
NYLAS_API_KEY: ${{ secrets.NYLAS_API_KEY }}
- name: Generate report (no email content in logs)
run: |
COUNT=$(nylas email list --json --limit 100 | jq 'length')
echo "Inbox: $COUNT recent messages"SOC 2 compliance checklist
| Requirement | Implementation |
|---|---|
| Access control | Per-user API keys, minimum-privilege scopes |
| Audit trail | Log all operations to tamper-evident file |
| Key rotation | Every 90 days with zero-downtime overlap |
| Credential storage | Config at 0600 permissions, env vars in CI/CD |
| Data minimization | Never log email content or PII |
| Encryption in transit | All API calls use TLS 1.2+ |
| Incident response | Revoke grants immediately on breach |
Next steps
- Email deliverability from the CLI — verify SPF, DKIM, DMARC for your sending domain
- Debug invisible characters — find hidden Unicode that can bypass security filters
- Agent-first email design — secure patterns for AI agents accessing email
- Full command reference