Pipe MCP Server implements multiple layers of security to protect user data and maintain system integrity. This guide covers security measures, best practices, and compliance considerations.
The system uses JWT tokens for stateless authentication:
- Access Token: Short-lived (15 minutes)
- Refresh Token: Long-lived (7 days) with rotation
- Token Storage: HttpOnly cookies or Authorization header
// Token structure
{
userId: string;
teamId: string;
email: string;
iat: number;
exp: number;
}- Hashing: bcrypt with 10+ rounds
- Requirements: Minimum 8 characters
- Storage: Only hashed passwords stored
All sensitive data is encrypted using AES-256-GCM:
// Encrypted data structure
{
encrypted: string; // Base64 encoded
iv: string; // Initialization vector
authTag: string; // Authentication tag
}- OAuth access tokens
- OAuth refresh tokens
- Webhook secrets
- API credentials
- Store
ENCRYPTION_KEYsecurely (e.g., AWS KMS, HashiCorp Vault) - Rotate encryption keys periodically
- Never commit keys to version control
-
State Parameter: CSRF protection
const state = crypto.randomUUID(); // Store state in Redis with expiry
-
PKCE Support: For public clients (planned)
-
Token Storage: Encrypted in database
Each platform uses different verification methods:
const signature = crypto
.createHmac('sha256', webhookSecret)
.update(payload)
.digest('hex');
const expected = `sha256=${signature}`;const signature = crypto
.createHmac('sha256', signingSecret)
.update(`v0:${timestamp}:${body}`)
.digest('hex');
const expected = `v0=${signature}`;Implement rate limiting to prevent abuse:
const rateLimiter = {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP'
};const corsOptions = {
origin: process.env.FRONTEND_URL,
credentials: true,
optionsSuccessStatus: 200
};Essential security headers:
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));- Use SSL/TLS for all database connections
- Implement connection pooling with limits
- Use least-privilege database users
- Use parameterized queries (Prisma ORM)
- Validate all user inputs
- Implement query timeouts
// Prisma automatically prevents SQL injection
const user = await prisma.user.findUnique({
where: { email: userInput } // Safe
});const sessionConfig = {
secret: process.env.SESSION_SECRET!,
resave: false,
saveUninitialized: false,
store: new RedisStore({ client: redisClient }),
cookie: {
secure: true, // HTTPS only
httpOnly: true,
maxAge: 1000 * 60 * 60 * 24 * 7, // 7 days
sameSite: 'strict'
}
};- Regenerate session ID on login
- Implement session timeout
- Clear sessions on logout
const LoginSchema = z.object({
email: z.string().email(),
password: z.string().min(8)
});
// Validate request
const validated = LoginSchema.parse(req.body);- Strip HTML from user inputs
- Validate file uploads
- Limit request body size
Log security-relevant events:
logger.info('auth.login.success', { userId, ip: req.ip });
logger.warn('auth.login.failed', { email, ip: req.ip });
logger.error('auth.token.invalid', { token: tokenId, ip: req.ip });Track sensitive operations:
await prisma.auditLog.create({
data: {
userId,
action: 'platform.connected',
resourceType: 'platform_connection',
resourceId: platform,
metadata: { ip: req.ip },
timestamp: new Date()
}
});# Regular security audits
npm audit
# Fix vulnerabilities
npm audit fix
# Check for outdated packages
npm outdated-
Static Analysis
# ESLint security plugin npm install --save-dev eslint-plugin-security -
Dynamic Analysis
- OWASP ZAP for API testing
- Burp Suite for security scanning
- Right to access data
- Right to deletion
- Data portability
- Privacy by design
// Implement data retention policies
const RETENTION_DAYS = 365;
// Cleanup job
async function cleanupOldData() {
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - RETENTION_DAYS);
await prisma.auditLog.deleteMany({
where: { createdAt: { lt: cutoffDate } }
});
}- Environment variables properly configured
- No secrets in code or logs
- Input validation on all endpoints
- Error messages don't leak sensitive info
- HTTPS enabled with valid certificate
- Security headers configured
- Rate limiting enabled
- Firewall rules configured
- Database connections use SSL
- Logs don't contain sensitive data
- Regular dependency updates
- Security audit schedule
- Incident response plan
- Backup encryption verified
- Access logs reviewed
- Detection: Monitor logs and alerts
- Containment: Isolate affected systems
- Investigation: Determine scope and cause
- Remediation: Fix vulnerabilities
- Recovery: Restore normal operations
- Lessons Learned: Update procedures
- Security Team: security@example.com
- On-call: +1-XXX-XXX-XXXX
- Incident tracking: JIRA/PagerDuty