Documentation

Data Masking

Mask sensitive production data with the GoMask CLI

Data Masking Guide

Learn how to mask sensitive production data for safe use in testing environments.

Overview

Data masking transforms sensitive data (PII, financial data, etc.) into realistic but anonymized values, enabling you to:

  • Use production-like data in test environments
  • Comply with GDPR, HIPAA, and other regulations
  • Protect customer privacy
  • Maintain data relationships and formats

Quick Start

Using the Setup Wizard

gomask setup

Select masking when prompted for routine type. The wizard uses AI to:

  1. Detect sensitive columns (emails, SSNs, names, etc.)
  2. Suggest appropriate masking functions
  3. Generate a ready-to-run configuration

Manual Configuration

routine:
  name: "Mask Customer PII"
  type: masking
  connector_id: 1  # Your connector ID

tables:
  - table_name: customers
    schema_name: public
    columns:
      - column_name: email
        masking_function: mask_email_domain
      - column_name: ssn
        masking_function: mask_ssn
      - column_name: phone
        masking_function: mask_phone_partial

Run it:

gomask run mask-customer-pii.yaml --watch

Masking Strategies

Partial Masking

Show some characters, hide others:

columns:
  # SSN: 123-45-6789 → ***-**-6789
  - column_name: ssn
    masking_function: mask_ssn

  # Credit card: 4111-1111-1111-1111 → ****-****-****-1111
  - column_name: credit_card
    masking_function: mask_credit_card

  # Phone: (555) 123-4567 → (555) ***-4567
  - column_name: phone
    masking_function: mask_phone_partial

  # Generic: show last 4 characters
  - column_name: account_number
    masking_function: mask_partial
    masking_config:
      - name: visible_chars
        value: 4
      - name: mask_char
        value: "*"

Replacement Masking

Replace with realistic fake data:

columns:
  # Replace with fake email (same format)
  - column_name: email
    masking_function: mask_email_domain

  # Replace first name with initial
  - column_name: full_name
    masking_function: initial_last_name

  # Scramble name characters
  - column_name: first_name
    masking_function: scramble_name

  # Replace city with region
  - column_name: city
    masking_function: city_to_region

Date Masking

Preserve patterns while obscuring exact dates:

columns:
  # Shift by random days (within ±30 days)
  - column_name: birthdate
    masking_function: shift_date_random
    masking_config:
      - name: days_range
        value: 30

  # Keep month/year, randomize day
  - column_name: transaction_date
    masking_function: preserve_month_year

Numeric Masking

Add noise or round to ranges:

columns:
  # Add ±10% noise
  - column_name: salary
    masking_function: add_noise_percentage
    masking_config:
      - name: noise_percent
        value: 10

  # Round to ranges: 47 → "40-50"
  - column_name: age
    masking_function: round_to_range
    masking_config:
      - name: range_size
        value: 10

Complete Anonymization

Remove data entirely:

columns:
  # Set to NULL
  - column_name: notes
    masking_function: nullify

  # Hash (irreversible)
  - column_name: customer_id
    masking_function: hash_sha256
    masking_config:
      - name: salt
        value: "my-secret-salt"

  # Generic anonymization
  - column_name: sensitive_field
    masking_function: anonymize
    masking_config:
      - name: strategy
        value: hash    # hash, random, mask, null
      - name: preserve_type
        value: true

Common Masking Patterns

Customer Table

tables:
  - table_name: customers
    schema_name: public
    columns:
      - column_name: first_name
        masking_function: scramble_name
      - column_name: last_name
        masking_function: scramble_name
      - column_name: email
        masking_function: mask_email_domain
      - column_name: phone
        masking_function: mask_phone_partial
      - column_name: ssn
        masking_function: mask_ssn
      - column_name: birthdate
        masking_function: shift_date_random
        masking_config:
          - name: days_range
            value: 30
      - column_name: address
        masking_function: mask_street_number

Financial Records

tables:
  - table_name: transactions
    schema_name: public
    columns:
      - column_name: account_number
        masking_function: mask_partial
        masking_config:
          - name: visible_chars
            value: 4
      - column_name: card_number
        masking_function: mask_credit_card
      - column_name: amount
        masking_function: add_noise_percentage
        masking_config:
          - name: noise_percent
            value: 5
      - column_name: description
        masking_function: nullify

Healthcare Data

tables:
  - table_name: patients
    schema_name: public
    columns:
      - column_name: mrn
        masking_function: hash_consistent
        masking_config:
          - name: salt
            value: "patient-salt"
      - column_name: name
        masking_function: scramble_name
      - column_name: ssn
        masking_function: mask_ssn
      - column_name: dob
        masking_function: preserve_month_year
      - column_name: diagnosis
        masking_function: nullify

Deterministic Masking

For consistent masking across runs (same input = same output):

columns:
  - column_name: customer_id
    masking_function: hash_consistent
    masking_config:
      - name: salt
        value: "my-secret-salt"

This ensures:

  • Same customer ID always maps to same masked value
  • Relationships between tables are preserved
  • Different environments get consistent data

Preserving Format

Keep original format structure:

columns:
  # Preserves format: ABC-123 → XXX-999
  - column_name: reference_number
    masking_function: preserve_format
    masking_config:
      - name: replacement_char
        value: "X"

YAML Configuration

Full Structure

routine:
  name: "Display Name"
  description: "Optional description"
  type: masking
  connector_id: 1  # Your connector ID

settings:
  batch_size: 1000
  parallel_workers: 4
  audit_reporting_enabled: true

tables:
  - table_name: table_name
    schema_name: public
    columns:
      - column_name: column_name
        masking_function: masking_function
        masking_config:
          - name: key
            value: value

Multiple Tables

tables:
  - table_name: customers
    schema_name: public
    columns:
      - column_name: email
        masking_function: mask_email_domain

  - table_name: orders
    schema_name: public
    columns:
      - column_name: customer_email
        masking_function: mask_email_domain
      - column_name: shipping_address
        masking_function: mask_street_number

Validation

# Validate configuration
gomask validate masking-routine.yaml --detailed

# Preview what will be masked
gomask run masking-routine.yaml --dry-run

Available Masking Functions

Contact Data

FunctionDescription
mask_email_domainMask email, replace domain
mask_phone_partialShow first 3, last 4 digits

Identity Data

FunctionDescription
mask_ssnShow only last 4 digits
mask_credit_cardShow only last 4 digits
scramble_nameRandomize characters
initial_last_nameFirst initial + last name

Location Data

FunctionDescription
mask_street_numberReplace street numbers
city_to_regionReplace city with state

Date/Time

FunctionDescription
shift_date_randomShift by random days
preserve_month_yearKeep month/year only

Numeric

FunctionDescription
add_noise_percentageAdd random ±%
round_to_rangeRound to ranges

Generic

FunctionDescription
mask_partialShow last N chars
nullifySet to NULL
hash_sha256Irreversible hash
hash_consistentDeterministic hash
anonymizeMultiple strategies

Full function reference →


Compliance Considerations

GDPR

  • Use irreversible functions (hash_sha256, nullify) for right-to-erasure compliance
  • Document masking applied for accountability
  • Consider pseudonymization vs anonymization requirements

HIPAA

  • Protected Health Information (PHI) requires de-identification
  • 18 HIPAA identifiers must be addressed
  • Use nullify or strong masking for direct identifiers

PCI-DSS

  • Credit card numbers must be masked showing only last 4 digits
  • Use mask_credit_card for compliant masking
  • Consider tokenization for production systems

Best Practices

  1. Map sensitive columns - Identify all PII before starting
  2. Use consistent salt - Same salt = same masked values
  3. Test thoroughly - Validate masked data meets requirements
  4. Document approach - Record masking decisions for compliance
  5. Preserve relationships - Use deterministic masking for foreign keys
  6. Validate output - Check masked data works for testing

Next Steps