Environments & AuthSensitive Data Masking

Sensitive Data Masking

ReAPI’s mask patterns feature automatically hides sensitive data in test results, request/response viewers, and execution logs. Configure once at the project level, and sensitive values are masked everywhere.

New to security features? Start with Security & Secrets for an overview. This guide assumes you understand the basics.

What Is Data Masking?

Data masking replaces sensitive values with *** or ****** in the ReAPI UI while keeping the actual data intact for test execution. This protects:

  • Authorization headers (Bearer tokens, API keys)
  • Credentials in requests (passwords, secrets)
  • Tokens in responses (access_token, refresh_token)
  • Context secrets (environment variables, secret references)

Masking vs Encryption

FeatureSecrets EncryptionData Masking
What it protectsCredentials in storageSensitive data in test results/viewers
When it appliesStorage and transmissionViewing test results
ScopeVariable Group levelProject level (all tests)
ReversibleYes (with password/biometric)Yes (toggle mask/unmask in UI)
Primary use caseProtect API keys, passwords at restPrevent leaks in screenshots, logs

Use both together: Encrypt secrets for storage security, mask patterns for viewing security.

Quick Start

Step 1: Navigate to Settings

  1. Open your project
  2. Go to Project SettingsSecurity
  3. Scroll to Sensitive Data Masking section

Step 2: Load Default Patterns

Click Load Defaults to add 33 pre-configured patterns covering common sensitive fields:

request.headers.Authorization
request.headers.X-API-Key
request.headers.Cookie
request.body.password
request.body.**.password
response.body.**.access_token
response.body.**.refresh_token
context.secrets.**
...and 25 more

Step 3: Save and Test

  1. Click Save Patterns
  2. Run any test in your project
  3. View test results → Sensitive fields will show as ***
  4. Toggle mask/unmask using the eye icon 👁️

Pattern Syntax

Path Structure

All patterns must start with one of these prefixes:

PrefixMatchesExamples
request.HTTP request datarequest.headers.Authorization
request.body.password
response.HTTP response dataresponse.headers.Set-Cookie
response.body.token
context.Test execution context/variablescontext.secrets.apiKey
context.$secrets.**

Wildcards

Single-Level Wildcard (*)

Matches exactly one level in the path:

request.body.*.password

Matches:

  • request.body.user.password
  • request.body.admin.password

Does NOT match:

  • request.body.password ❌ (too shallow)
  • request.body.user.info.password ❌ (too deep)

Deep Wildcard (**)

Matches any depth (including zero levels):

request.body.**.password

Matches:

  • request.body.password
  • request.body.user.password
  • request.body.user.profile.credentials.password

Common uses:

  • response.body.**.access_token — Find tokens at any nesting level
  • context.secrets.** — Mask ALL secrets in context

Array Wildcard ([*])

Matches all array indices:

users[*].password

Matches:

  • users[0].password
  • users[1].password
  • users[N].password

Example:

{
  "users": [
    { "name": "Alice", "password": "secret1" },
    { "name": "Bob", "password": "secret2" }
  ]
}

Pattern request.body.users[*].password will mask both secret1 and secret2.

Common Patterns

Authentication Headers

request.headers.Authorization
request.headers.X-API-Key
request.headers.X-Auth-Token
request.headers.Cookie
request.headers.Proxy-Authorization

Request Body Credentials

request.body.password
request.body.*.password
request.body.**.password
request.body.**.apiKey
request.body.**.secret
request.body.**.token
request.body.**.access_token
request.body.**.refresh_token
request.body.**.client_secret

Response Tokens

response.headers.Set-Cookie
response.headers.Authorization
response.body.**.access_token
response.body.**.refresh_token
response.body.**.id_token
response.body.**.token
response.body.**.apiKey
response.body.**.secret

Context and Secrets

context.secrets.**
context.$secrets.**
context.env.DATABASE_URL
context.env.API_KEY

Personal Information (Optional)

request.body.**.ssn
request.body.**.creditCard
request.body.**.cvv
request.body.**.email
request.body.**.phone

Practical Examples

Example 1: OAuth Flow

Scenario: Testing an OAuth authentication flow that returns tokens.

Test execution data:

{
  "request": {
    "method": "POST",
    "url": "https://auth.example.com/oauth/token",
    "headers": {
      "Authorization": "Basic dXNlcjpwYXNz",
      "Content-Type": "application/x-www-form-urlencoded"
    },
    "body": {
      "grant_type": "password",
      "username": "user@example.com",
      "password": "mySecretPassword123"
    }
  },
  "response": {
    "status": 200,
    "body": {
      "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
      "refresh_token": "def502001a3f5e8d...",
      "expires_in": 3600,
      "token_type": "Bearer"
    }
  }
}

Mask patterns:

request.headers.Authorization
request.body.password
response.body.access_token
response.body.refresh_token

Masked result in UI:

{
  "request": {
    "headers": {
      "Authorization": "***",
      "Content-Type": "application/x-www-form-urlencoded"
    },
    "body": {
      "grant_type": "password",
      "username": "user@example.com",
      "password": "***"
    }
  },
  "response": {
    "body": {
      "access_token": "***",
      "refresh_token": "***",
      "expires_in": 3600,
      "token_type": "Bearer"
    }
  }
}

Example 2: User Management API

Scenario: Creating multiple users with nested credentials.

Test data:

{
  "request": {
    "body": {
      "users": [
        {
          "email": "alice@example.com",
          "profile": { "name": "Alice", "password": "aliceSecret123" }
        },
        {
          "email": "bob@example.com",
          "profile": { "name": "Bob", "password": "bobSecret456" }
        }
      ]
    }
  }
}

Mask pattern:

request.body.users[*].profile.password

Or more flexible with deep wildcard:

request.body.users.**.password

Masked result:

{
  "request": {
    "body": {
      "users": [
        {
          "email": "alice@example.com",
          "profile": { "name": "Alice", "password": "***" }
        },
        {
          "email": "bob@example.com",
          "profile": { "name": "Bob", "password": "***" }
        }
      ]
    }
  }
}

Example 3: Payment Processing

Scenario: Testing Stripe payment API.

Mask patterns:

request.headers.Authorization
request.body.**.card_number
request.body.**.cvv
request.body.**.ssn
response.body.**.client_secret
response.body.**.api_key

This ensures:

  • ✅ API keys are hidden
  • ✅ Card numbers are masked
  • ✅ CVV codes are protected
  • ✅ Client secrets in responses are hidden

Using Masked Data

Toggle Mask/Unmask in UI

When viewing test results:

  1. Masked fields show as *** or ****** by default
  2. Click the eye icon 👁️ in the top-right corner to toggle
  3. Unmask to see actual values (useful for debugging)
  4. Re-mask before taking screenshots or sharing

Prefix Preservation

ReAPI preserves common prefixes to show token types:

Original ValueMasked ValuePrefix Preserved
Bearer sk_live_abc123Bearer ***✅ Yes
Basic dXNlcjpwYXNzBasic ***✅ Yes
eyJhbGciOiJIUz...tokeney***✅ Yes (2 chars)

Non-String Values

Numbers, booleans, and other non-string values are replaced with the mask pattern:

{
  "apiKey": 12345,        // Masked as: "apiKey": "***"
  "enabled": true,        // Masked as: "enabled": "***"
  "secret": null          // Masked as: "secret": "***"
}

Configuration Tips

Start with Defaults

The Load Defaults button provides 33 carefully selected patterns covering:

  • ✅ Common authentication headers
  • ✅ Password fields at any depth
  • ✅ OAuth tokens (access_token, refresh_token)
  • ✅ API keys and secrets
  • ✅ Context secrets (all $secrets references)

Recommendation: Load defaults first, then add project-specific patterns.

Use Deep Wildcards Wisely

Good use of **:

response.body.**.token         // Catch tokens anywhere
context.secrets.**             // Mask all secrets

Over-masking with **:

request.**.data                // TOO BROAD - masks all "data" fields
**.password                    // INVALID - must start with prefix

Balance: Use ** for fields that appear at varying depths, but be specific about the prefix.

Test Your Patterns

After adding patterns:

  1. Run a test that uses sensitive data
  2. View the test results
  3. Verify sensitive fields are masked
  4. Toggle unmask to ensure actual data is intact
  5. Adjust patterns if needed

Pattern Order Doesn’t Matter

ReAPI applies all patterns regardless of order. These are equivalent:

# Order 1
request.headers.Authorization
request.body.password

# Order 2
request.body.password
request.headers.Authorization

Duplicates Are Allowed

Duplicate patterns are harmless (just redundant):

request.body.password
request.body.**.password        # Includes the above

The field will be masked once, not multiple times.

Advanced Scenarios

Mask Specific API Responses

Use case: Third-party API returns sensitive data in varying structures.

Pattern strategy: Use deep wildcards with specific field names.

response.body.**.apiKey
response.body.**.clientSecret
response.body.**.privateKey
response.body.**.credentials

This catches sensitive fields regardless of nesting level.

Conditional Masking by Endpoint

Challenge: You want to mask data for production APIs but not mock APIs.

Solution: Mask patterns apply to all requests in the project. For endpoint-specific masking:

  1. Use separate projects for production vs. mock testing
  2. Or rely on Variable Group secrets (which are VarGroup-scoped)

Note: Mask patterns are project-level, not endpoint-level.

Mask All Fields Under a Path

Use ** at the end to mask everything under a path:

context.secrets.**              # Masks ALL secrets
response.body.user.settings.**  # Masks ALL settings

Result: Every field under that path will be masked.

Integration with Secrets

Scenario: You use {{$secrets.apiKey}} in requests and want to mask it in results.

Mask pattern:

context.$secrets.**
context.secrets.**

Result: All secret references in the execution context will be masked.

Benefit: Even if secrets are injected via CLI or plaintext mode, they’re masked in test results.

Security Best Practices

DO ✅

  • Load defaults first: Start with the 33 pre-configured patterns
  • Use deep wildcards for tokens: response.body.**.access_token catches tokens at any depth
  • Mask context secrets: Always include context.secrets.**
  • Test after changes: Run a test to verify patterns work
  • Mask before sharing: Keep masking enabled when taking screenshots or recording demos
  • Document custom patterns: Comment why you added specific patterns (in team wiki)

DON’T ❌

  • Don’t rely on masking alone: Use secrets encryption for storage security
  • Don’t over-mask: Avoid patterns like **.id that mask non-sensitive fields
  • Don’t forget response tokens: Many APIs return secrets in responses
  • Don’t share unmasked results: Always toggle mask ON before screenshots
  • Don’t use masking as access control: Mask patterns are for UI display, not permissions

Compliance Considerations

For regulated environments (HIPAA, PCI-DSS, SOC 2):

  • Use both masking + encryption: Mask patterns for viewing, secrets encryption for storage
  • Mask PII fields: Add patterns for email, phone, ssn, address
  • Regular audits: Review patterns quarterly to ensure coverage
  • Document patterns: Maintain a list of what’s masked and why
  • Test log sanitization: Verify masked data doesn’t leak in logs

Troubleshooting

Pattern Not Masking

Problem: Added a pattern but field is still visible.

Solutions:

  1. Check pattern syntax: Must start with request., response., or context.
  2. Verify path: Use browser DevTools to inspect the exact path
  3. Try deep wildcard: Use **.fieldName to catch any depth
  4. Check for typos: Pattern matching is case-sensitive
  5. Reload test results: Re-run the test after saving patterns

Example debug:

// Your data structure
{
  "response": {
    "data": {
      "user": {
        "apiKey": "secret"
      }
    }
  }
}
 
// Wrong pattern
response.body.user.apiKey     ❌ (missing "data" level)
 
// Correct pattern
response.data.user.apiKey     ✅
// Or use deep wildcard
response.**.apiKey            ✅

Too Much Masking

Problem: Non-sensitive fields are being masked.

Solution: Be more specific in your patterns.

# Too broad
request.body.**.data          # Masks ALL "data" fields

# More specific
request.body.user.**.password # Only masks passwords under user

Mask Not Appearing in UI

Problem: Pattern saved but mask toggle doesn’t appear.

Possible causes:

  1. No matching data: The test doesn’t contain fields that match patterns
  2. Empty patterns list: Verify patterns were saved (refresh settings page)
  3. Browser cache: Hard refresh (Ctrl+Shift+R / Cmd+Shift+R)

Cannot Unmask

Problem: Toggle eye icon but values stay masked.

Solution: This is expected behavior. Masking is applied during data processing, not just display. Original values are available in:

  • Raw network responses (browser DevTools)
  • Downloaded test results (if export feature available)
  • Backend logs (if you have server access)

By design: ReAPI masks data before storing test results for security.

Performance with Many Patterns

Problem: Test results load slowly with 100+ patterns.

Optimization:

  1. Remove duplicates: request.body.**.password covers request.body.password
  2. Consolidate patterns: Use deep wildcards instead of multiple specific paths
  3. Remove unused patterns: Audit patterns quarterly

Typical performance:

  • Less than 50 patterns: No noticeable impact
  • 50-100 patterns: Slight delay (less than 100ms)
  • More than 100 patterns: Consider consolidation

Pattern Library

Copy-paste these pattern collections for common scenarios:

Web Application Testing

request.headers.Authorization
request.headers.Cookie
request.body.username
request.body.password
request.body.email
response.headers.Set-Cookie
response.body.**.access_token
response.body.**.refresh_token
response.body.**.session_id
context.secrets.**

Microservices Testing

request.headers.Authorization
request.headers.X-API-Key
request.headers.X-Auth-Token
request.body.**.credentials
request.body.**.apiKey
response.body.**.token
response.body.**.secret
context.secrets.**
context.env.**

Payment APIs

request.headers.Authorization
request.body.**.card_number
request.body.**.cvv
request.body.**.exp_month
request.body.**.exp_year
request.body.**.ssn
request.body.**.account_number
request.body.**.routing_number
response.body.**.client_secret
response.body.**.publishable_key

OAuth/SSO Testing

request.headers.Authorization
request.body.client_secret
request.body.username
request.body.password
request.body.code
response.body.access_token
response.body.refresh_token
response.body.id_token
response.body.token_type
response.headers.Set-Cookie

Next Steps


Need help? Contact support@reapi.com or join our Discord community