Skip to content

Security: adaptyvbio/snaplet

SECURITY.md

Security Policy

Table of Contents

Overview

Snaplet takes security seriously. This document outlines our security policies, best practices for using Snaplet securely, and how to report security vulnerabilities.

Reporting Security Vulnerabilities

If you discover a security vulnerability in Snaplet, please report it responsibly:

  1. DO NOT create a public GitHub issue
  2. Email us at security@snaplet.dev with:
    • Description of the vulnerability
    • Steps to reproduce
    • Potential impact
    • Any suggested fixes

We aim to respond within 48 hours and will keep you updated on our progress.

Security Response Timeline

  • 0-48 hours: Initial response and assessment
  • 7 days: Fix development and testing
  • 30 days: Patch release and disclosure

Security Best Practices

1. Environment Configuration

# Good: Use environment variables for sensitive data
export DATABASE_URL="postgresql://user:pass@host:5432/db"
export SNAPLET_PRIVATE_KEY="$(cat private.key)"

# Bad: Hardcode credentials
snaplet capture --db-url "postgresql://admin:password123@prod.example.com/db"

2. Configuration Files

// snaplet.config.ts

// Good: Reference environment variables
export default defineConfig({
  privateKey: process.env.SNAPLET_PRIVATE_KEY,
  // ...
})

// Bad: Hardcode sensitive data
export default defineConfig({
  privateKey: 'actual-private-key-content', // Never do this!
  // ...
})

3. Git Security

Add to .gitignore:

# Snaplet
.snaplet/
snapshots/
*.snapshot
private.key
public.key
.env
.env.*

Data Privacy

Automatic PII Detection

Snaplet automatically detects and suggests transformations for common PII:

// Detected patterns:
- Email addresses
- Phone numbers
- Social Security Numbers
- Credit card numbers
- IP addresses
- Physical addresses

Transformation Best Practices

// snaplet.config.ts
import { copycat } from '@snaplet/copycat'

export default defineConfig({
  transform: {
    // Good: Use deterministic transformations
    public: {
      users: ({ row }) => ({
        email: copycat.email(row.email), // Deterministic
        name: copycat.fullName(row.name),
        ssn: copycat.ssn(row.ssn),
        created_at: row.created_at, // Keep non-sensitive data
      }),
      
      // Transform all columns by default
      $default: ({ row }) => 
        Object.fromEntries(
          Object.entries(row).map(([key, value]) => [
            key,
            typeof value === 'string' ? copycat.scramble(value) : value
          ])
        )
    }
  }
})

Complete Data Removal

For highly sensitive data, exclude it entirely:

export default defineConfig({
  select: {
    public: {
      // Exclude sensitive tables
      audit_logs: false,
      payment_methods: false,
      
      // Or exclude specific columns
      users: {
        columns: {
          password_hash: false,
          two_factor_secret: false,
        }
      }
    }
  }
})

Connection Security

1. SSL/TLS Connections

Always use SSL for database connections:

# Good: SSL enabled
postgresql://user:pass@host:5432/db?sslmode=require

# Better: Full verification
postgresql://user:pass@host:5432/db?sslmode=verify-full&sslcert=client.crt&sslkey=client.key

# Bad: No SSL
postgresql://user:pass@host:5432/db?sslmode=disable

2. Connection String Security

// Good: Parse and validate connection strings
import { parseConnectionString } from '@snaplet/sdk'

const config = parseConnectionString(process.env.DATABASE_URL)
if (!config.ssl) {
  throw new Error('SSL required for production databases')
}

// Bad: Direct usage without validation
const db = new Client(process.env.DATABASE_URL)

3. SSH Tunneling

For additional security, use SSH tunnels:

# Create SSH tunnel
ssh -L 5433:localhost:5432 user@database-host

# Connect through tunnel
snaplet capture --db-url postgresql://user:pass@localhost:5433/db

Snapshot Security

1. Encryption at Rest

Enable snapshot encryption:

// snaplet.config.ts
export default defineConfig({
  publicKey: process.env.SNAPLET_PUBLIC_KEY,
  // Snapshots will be encrypted automatically
})

2. Storage Security

# Set restrictive permissions
chmod 600 snapshots/*
chmod 700 snapshots/

# Good: Store in secure location
~/secure-snapshots/

# Bad: Store in public directories
/tmp/snapshots/
~/Downloads/

3. Snapshot Sharing

When sharing snapshots:

# Good: Encrypted transfer
gpg --encrypt --recipient team@example.com snapshot.tar.gz

# Good: Secure transfer protocols
scp snapshot.tar.gz user@secure-host:/secure/location/
aws s3 cp snapshot.tar.gz s3://secure-bucket/ --sse

# Bad: Unencrypted sharing
email snapshot without encryption
upload to public file sharing

Transformation Guidelines

1. Deterministic Transformations

Use seeded transformations for consistency:

import { copycat } from '@snaplet/copycat'

// Good: Deterministic (same input = same output)
copycat.email('john@example.com') // Always returns same fake email

// Bad: Random transformations
Math.random().toString() + '@example.com' // Different each time

2. Format Preservation

Maintain data format for application compatibility:

transform: {
  public: {
    users: ({ row }) => ({
      // Preserve format
      phone: copycat.phoneNumber(row.phone, { 
        format: '+1 (###) ###-####' 
      }),
      
      // Preserve domain for emails
      email: row.email.replace(/^[^@]+/, copycat.username(row.email)),
      
      // Preserve length
      api_key: copycat.scramble(row.api_key).substring(0, row.api_key.length),
    })
  }
}

3. Referential Integrity

Maintain relationships in transformed data:

transform: {
  public: {
    // Transform consistently across tables
    users: ({ row }) => ({
      id: row.id, // Keep IDs unchanged
      email: copycat.email(row.email),
    }),
    
    posts: ({ row }) => ({
      user_id: row.user_id, // Maintain foreign key
      content: copycat.paragraph(row.content),
    })
  }
}

Access Control

1. Database Permissions

Create read-only users for capture:

-- Create read-only role
CREATE ROLE snaplet_reader WITH LOGIN PASSWORD 'secure_password';
GRANT CONNECT ON DATABASE production TO snaplet_reader;
GRANT USAGE ON SCHEMA public TO snaplet_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO snaplet_reader;

-- Revoke unnecessary permissions
REVOKE CREATE ON SCHEMA public FROM snaplet_reader;

2. API Key Management

For Snaplet Cloud features:

# Good: Use environment variables
export SNAPLET_ACCESS_TOKEN="snap_token_xxx"

# Good: Use secure key storage
snaplet auth login # Stores securely in OS keychain

# Bad: Hardcode in scripts
TOKEN="snap_token_xxx" # Don't do this

3. Team Access

Implement access controls:

// Good: Role-based access
const canCapture = user.role === 'admin' || user.role === 'developer'
const canRestore = user.role !== 'viewer'

// Good: Audit logging
logger.info('Snapshot captured', { 
  user: user.id, 
  timestamp: Date.now(),
  snapshot: snapshot.id 
})

Compliance Considerations

GDPR Compliance

  1. Right to Erasure: Exclude deleted users from snapshots
  2. Data Minimization: Only capture necessary data
  3. Purpose Limitation: Use snapshots only for development
export default defineConfig({
  subset: {
    targets: [{
      table: 'public.users',
      // Exclude deleted users (GDPR compliance)
      where: 'deleted_at IS NULL',
    }]
  }
})

HIPAA Compliance

For healthcare data:

export default defineConfig({
  transform: {
    public: {
      patients: ({ row }) => ({
        // De-identify all PHI
        name: copycat.fullName(row.name),
        ssn: copycat.ssn(row.ssn),
        dob: copycat.dateString(row.dob),
        // Remove direct identifiers
        medical_record_number: copycat.uuid(row.medical_record_number),
      })
    }
  }
})

PCI DSS Compliance

For payment data:

export default defineConfig({
  select: {
    public: {
      // Never include payment data
      credit_cards: false,
      payment_tokens: false,
      transaction_logs: false,
    }
  }
})

Security Checklist

Before using Snaplet in production:

Configuration

  • Database connections use SSL/TLS
  • Credentials stored in environment variables
  • Configuration files don't contain secrets
  • .gitignore includes sensitive files

Data Protection

  • PII transformation rules configured
  • Sensitive tables excluded
  • Transformation functions are deterministic
  • Referential integrity maintained

Access Control

  • Database user has minimal permissions
  • API keys stored securely
  • Team access controls implemented
  • Audit logging enabled

Snapshot Handling

  • Snapshots encrypted at rest
  • Storage permissions restricted
  • Transfer methods secure
  • Retention policies defined

Compliance

  • GDPR requirements met
  • Industry-specific compliance verified
  • Data retention policies followed
  • Right to erasure implemented

Monitoring

  • Security alerts configured
  • Access logs reviewed regularly
  • Transformation effectiveness verified
  • Compliance audits scheduled

Additional Resources

Questions?

For security-related questions:

There aren’t any published security advisories