| name | customerio-security-basics |
| description | Apply Customer.io security best practices.
Use when implementing secure integrations, handling PII,
or setting up proper access controls.
Trigger with phrases like "customer.io security", "customer.io pii",
"secure customer.io", "customer.io gdpr".
|
| allowed-tools | Read, Grep, Bash(curl:*) |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Customer.io Security Basics
Overview
Implement security best practices for Customer.io integrations including credential management, PII handling, and access controls.
Prerequisites
- Customer.io account with admin access
- Understanding of your data classification
- Environment variable management
Instructions
Step 1: Secure Credential Management
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
async function getCustomerIOCredentials(): Promise<{
siteId: string;
apiKey: string;
}> {
const client = new SecretManagerServiceClient();
const [siteIdVersion] = await client.accessSecretVersion({
name: 'projects/PROJECT_ID/secrets/customerio-site-id/versions/latest'
});
const [apiKeyVersion] = await client.accessSecretVersion({
name: 'projects/PROJECT_ID/secrets/customerio-api-key/versions/latest'
});
return {
siteId: siteIdVersion.payload?.data?.toString() || '',
apiKey: apiKeyVersion.payload?.data?.toString() || ''
};
}
import { SecretsManager } from '@aws-sdk/client-secrets-manager';
async function getCredentialsFromAWS() {
const client = new SecretsManager({ region: 'us-east-1' });
const response = await client.getSecretValue({
SecretId: 'customerio-credentials'
});
return JSON.parse(response.SecretString || '{}');
}
Step 2: PII Data Handling
import crypto from 'crypto';
function hashPII(value: string): string {
return crypto
.createHash('sha256')
.update(value + process.env.PII_SALT)
.digest('hex');
}
function sanitizeUserAttributes(attributes: Record<string, any>): Record<string, any> {
const sensitiveFields = ['ssn', 'credit_card', 'password', 'bank_account'];
const piiFields = ['phone', 'address', 'date_of_birth'];
const sanitized = { ...attributes };
for (const field of sensitiveFields) {
delete sanitized[field];
}
for (const field of piiFields) {
(sanitized[field]) {
sanitized[] = (sanitized[field]);
}
}
sanitized;
}
safeAttributes = ({
: ,
: ,
: ,
:
});
Step 3: API Key Rotation
async function rotateAPIKey(): Promise<void> {
console.log('API Key Rotation Checklist:');
console.log('1. Generate new API key in Customer.io dashboard');
console.log('2. Update secrets manager with new key');
console.log('3. Deploy application with new key');
console.log('4. Verify integration works with new key');
console.log('5. Revoke old API key in dashboard');
console.log('6. Update documentation');
}
Step 4: Webhook Security
import crypto from 'crypto';
import { Request, Response, NextFunction } from 'express';
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
export function webhookAuthMiddleware(webhookSecret: string) {
return (req: Request, res: Response, next: NextFunction) => {
const signature = req.headers[] ;
(!signature) {
res.().({ : });
}
payload = .(req.);
(!(payload, signature, webhookSecret)) {
res.().({ : });
}
();
};
}
app.(,
(process..!),
{
}
);
Step 5: Access Control
interface TeamMember {
email: string;
role: 'admin' | 'editor' | 'viewer';
permissions: string[];
}
const rolePermissions = {
admin: [
'manage_api_keys',
'manage_team',
'manage_integrations',
'view_all_data',
'send_campaigns'
],
editor: [
'create_campaigns',
'edit_campaigns',
'view_analytics',
'manage_segments'
],
viewer: [
'view_campaigns',
'view_analytics'
]
};
function logSecurityEvent(event: {
action: string;
actor: string;
resource: string;
details?: Record<string, any>;
}) {
console.log(JSON.stringify({
type: 'security_audit',
timestamp: new Date().toISOString(),
...event
}));
}
Step 6: Data Retention
import { APIClient } from '@customerio/track';
async function deleteUserData(client: APIClient, userId: string) {
await client.suppress(userId);
console.log(`User ${userId} suppressed and deletion requested`);
}
function anonymizeForAnalytics(userData: Record<string, any>) {
return {
...userData,
email: undefined,
phone: undefined,
first_name: undefined,
last_name: undefined,
plan: userData.plan,
signup_date: userData.created_at,
total_events: userData.event_count
};
}
Security Checklist
Error Handling
| Issue | Solution |
|---|
| Exposed credentials | Rotate immediately, audit access |
| PII leak | Delete from Customer.io, notify DPO |
| Unauthorized access | Review access logs, revoke access |
Resources
Next Steps
After implementing security, proceed to customerio-prod-checklist for production readiness.