Stripe Hardening Guide
Payment platform hardening for Stripe including SSO configuration, team permissions, and API key security
Overview
Stripe is a leading payment processing platform serving millions of businesses for online transactions. As a platform handling sensitive payment data, Stripe security configurations directly impact PCI compliance and financial data protection.
Intended Audience
- Security engineers managing payment platforms
- IT administrators configuring Stripe
- Finance teams managing payment processing
- GRC professionals assessing payment security
How to Use This Guide
- L1 (Baseline): Essential controls for all organizations
- L2 (Hardened): Enhanced controls for security-sensitive environments
- L3 (Maximum Security): Strictest controls for regulated industries
Scope
This guide covers Stripe Dashboard security including SSO, team permissions, API key management, and webhook security.
Table of Contents
1. Authentication & SSO
1.1 Configure SAML Single Sign-On
Profile Level: L1 (Baseline)
| Framework | Control |
|---|---|
| CIS Controls | 6.3, 12.5 |
| NIST 800-53 | IA-2, IA-8 |
Description
Configure SAML SSO for Stripe Dashboard access.
Prerequisites
- Stripe account with SSO support
- Account owner access
- SAML 2.0 compatible IdP
ClickOps Implementation
Step 1: Access SSO Settings
- Navigate to: Dashboard → Settings → Team and security
- Find Single Sign-On section
Step 2: Configure SAML
- Enable SAML SSO
- Configure IdP settings:
- SSO URL
- Entity ID
- Certificate
- Download Stripe metadata for IdP
Step 3: Test and Enforce
- Test SSO authentication
- Enable SSO enforcement
- Configure admin fallback
Time to Complete: ~1-2 hours
1.2 Enforce Two-Factor Authentication
Profile Level: L1 (Baseline)
| Framework | Control |
|---|---|
| CIS Controls | 6.5 |
| NIST 800-53 | IA-2(1) |
Description
Require 2FA for all Stripe team members.
ClickOps Implementation
Step 1: Enable 2FA Requirement
- Navigate to: Settings → Team and security
- Enable Require two-step authentication
- All team members must configure 2FA
Step 2: Configure Methods
- Support authenticator apps
- Support SMS (backup)
- Use hardware keys for admins
1.3 Configure Session Security
Profile Level: L1 (Baseline)
| Framework | Control |
|---|---|
| CIS Controls | 6.2 |
| NIST 800-53 | AC-12 |
Description
Configure session timeout settings.
ClickOps Implementation
Step 1: Configure Timeout
- Navigate to: Settings → Team and security
- Configure session timeout
- Enable automatic logout
2. Access Controls
2.1 Configure Team Roles
Profile Level: L1 (Baseline)
| Framework | Control |
|---|---|
| CIS Controls | 5.4 |
| NIST 800-53 | AC-6 |
Description
Implement least privilege using Stripe roles.
ClickOps Implementation
Step 1: Review Roles
- Navigate to: Settings → Team
- Review available roles:
- Administrator
- Developer
- Analyst
- Support specialist
- View only
- Assign minimum necessary role
Step 2: Apply Least Privilege
- Use View only for read access
- Limit Administrator access
- Regular access reviews
2.2 Limit Admin Access
Profile Level: L1 (Baseline)
| Framework | Control |
|---|---|
| CIS Controls | 5.4 |
| NIST 800-53 | AC-6(1) |
Description
Minimize and protect administrator accounts.
ClickOps Implementation
Step 1: Inventory Admins
- Review administrator accounts
- Document admin access
- Identify unnecessary privileges
Step 2: Apply Restrictions
- Limit admins to 2-3 users
- Require 2FA for admins
- Monitor admin activity
3. API Security
3.1 Configure API Key Security
Profile Level: L1 (Baseline)
| Framework | Control |
|---|---|
| CIS Controls | 3.11 |
| NIST 800-53 | SC-12 |
Description
Secure Stripe API keys.
ClickOps Implementation
Step 1: Review API Keys
- Navigate to: Developers → API keys
- Review all API keys
- Document key purposes
Step 2: Apply Best Practices
- Use restricted keys with minimum permissions
- Never expose secret keys
- Use test keys for development
Step 3: Key Rotation
- Rotate keys regularly
- Roll keys if compromised
- Update integrations
Code Pack: API Script
# Monitor for account changes that may indicate key-related activity
# NOTE: Stripe has NO api_key.* event types — use account.updated instead
EVENTS=$(stripe_get "/events?type=account.updated&limit=10") || {
fail "3.1 Unable to retrieve account events"
increment_failed; summary; exit 0
}
EVENT_COUNT=$(echo "${EVENTS}" | jq '.data | length')
info "3.1 Recent account update events: ${EVENT_COUNT}"
if [ "${EVENT_COUNT}" -gt 0 ]; then
info "3.1 Most recent account changes:"
echo "${EVENTS}" | jq -r '.data[:5][] | " - \(.created | todate): \(.type)"'
fi
pass "3.1 Account events audit complete — review API keys in Dashboard"
increment_applied
Code Pack: Sigma Detection Rule
detection:
selection:
type: 'account.updated'
condition: selection
fields:
- id
- created
- type
- data.object.id
- data.previous_attributes
3.2 Configure Webhook Security
Profile Level: L2 (Hardened)
| Framework | Control |
|---|---|
| CIS Controls | 3.11 |
| NIST 800-53 | SC-8 |
Description
Secure webhook endpoints.
ClickOps Implementation
Step 1: Configure Webhooks
- Navigate to: Developers → Webhooks
- Review webhook endpoints
- Verify endpoint security
Step 2: Verify Signatures
- Always verify webhook signatures
- Use webhook secrets securely
- Reject unverified events
Code Pack: API Script
# List existing webhooks and check for unsigned endpoints
WEBHOOKS=$(stripe_get "/webhook_endpoints?limit=100") || {
fail "3.2 Unable to retrieve webhook endpoints"
increment_failed; summary; exit 0
}
TOTAL=$(echo "${WEBHOOKS}" | jq '.data | length')
DISABLED=$(echo "${WEBHOOKS}" | jq '[.data[] | select(.status == "disabled")] | length')
info "3.2 Total webhook endpoints: ${TOTAL}"
info "3.2 Disabled endpoints: ${DISABLED}"
if [ "${DISABLED}" -gt 0 ]; then
warn "3.2 Disabled webhook endpoints found — review and remove unused:"
echo "${WEBHOOKS}" | jq -r '.data[] | select(.status == "disabled") | " - \(.url) (id: \(.id))"'
fi
# Create a SIEM webhook for security events if URL is provided
if [ -n "${STRIPE_SIEM_WEBHOOK_URL:-}" ]; then
EXISTING=$(echo "${WEBHOOKS}" | jq -r ".data[] | select(.url == \"${STRIPE_SIEM_WEBHOOK_URL}\") | .id")
if [ -n "${EXISTING}" ]; then
info "3.2 SIEM webhook already exists (id: ${EXISTING})"
else
info "3.2 Creating SIEM webhook for security events..."
RESPONSE=$(stripe_post "/webhook_endpoints" "$(cat <<'PARAMS'
url=${STRIPE_SIEM_WEBHOOK_URL}&\
enabled_events[]=account.updated&\
enabled_events[]=account.application.authorized&\
enabled_events[]=account.application.deauthorized&\
enabled_events[]=account.external_account.created&\
enabled_events[]=account.external_account.deleted&\
enabled_events[]=person.created&\
enabled_events[]=person.updated&\
enabled_events[]=person.deleted&\
enabled_events[]=payment_method.attached&\
enabled_events[]=payment_method.detached&\
enabled_events[]=identity.verification_session.created&\
enabled_events[]=identity.verification_session.verified&\
enabled_events[]=capability.updated&\
description=HTH Security Events SIEM Webhook
PARAMS
)") || {
fail "3.2 Failed to create SIEM webhook"
increment_failed; summary; exit 0
}
WEBHOOK_ID=$(echo "${RESPONSE}" | jq -r '.id')
WEBHOOK_SECRET=$(echo "${RESPONSE}" | jq -r '.secret')
pass "3.2 SIEM webhook created (id: ${WEBHOOK_ID})"
info "3.2 Webhook signing secret: ${WEBHOOK_SECRET}"
info "3.2 IMPORTANT: Store this secret securely for signature verification"
fi
fi
pass "3.2 Webhook security audit complete"
increment_applied
Code Pack: Sigma Detection Rule
detection:
selection:
request_method: 'DELETE'
request_path|startswith: '/v1/webhook_endpoints/'
condition: selection
fields:
- timestamp
- request_method
- request_path
- source_ip
- api_key_id
3.3 Configure Restricted Keys
Profile Level: L2 (Hardened)
| Framework | Control |
|---|---|
| CIS Controls | 5.4 |
| NIST 800-53 | AC-6 |
Description
Use restricted API keys for specific functions.
ClickOps Implementation
Step 1: Create Restricted Keys
- Navigate to: Developers → API keys
- Create restricted key
- Select minimum permissions
Step 2: Apply Per-Integration
- Use separate keys per integration
- Document key purposes
- Audit key usage
Code Pack: API Script
# Test if the current key has overly broad permissions
# A restricted key should fail on resources it doesn't need
info "3.3 Testing key permissions scope..."
# Try to list customers (should fail if key is properly restricted)
if stripe_get "/customers?limit=1" > /dev/null 2>&1; then
warn "3.3 Current key can list customers — may be overly permissive"
else
pass "3.3 Current key cannot list customers — properly scoped"
fi
# Try to list payment intents
if stripe_get "/payment_intents?limit=1" > /dev/null 2>&1; then
warn "3.3 Current key can list payment intents — review if needed"
else
pass "3.3 Current key cannot list payment intents — properly scoped"
fi
# Try to list webhook endpoints (meta-permission check)
if stripe_get "/webhook_endpoints?limit=1" > /dev/null 2>&1; then
info "3.3 Current key has webhook read access"
else
info "3.3 Current key cannot list webhooks"
fi
pass "3.3 Key scope validation complete"
increment_applied
4. Compliance Quick Reference
SOC 2 Trust Services Criteria Mapping
| Control ID | Stripe Control | Guide Section |
|---|---|---|
| CC6.1 | SSO/2FA | 1.1 |
| CC6.2 | Team roles | 2.1 |
| CC6.7 | API key security | 3.1 |
PCI DSS v4.0 Mapping
| Requirement | Stripe Control | Guide Section |
|---|---|---|
| 7 | Team roles | 2.1 |
| 8 | Authentication | 1.1 |
Appendix A: References
Official Stripe Documentation:
API & Developer Tools:
Compliance Frameworks:
- PCI DSS Level 1 (Service Provider – most stringent level), SOC 1 Type II, SOC 2 Type II, SOC 3 – via Security at Stripe
- EMVCo Level 1 & 2 (Stripe Terminal), PCI PA-DSS (Terminal)
- Payments Security and Compliance Guide
Security Incidents:
- (2024) Evolve Bank & Trust (a Stripe banking partner) was breached by LockBit ransomware. Customer data from Stripe and other fintechs may have been exposed, including names, SSNs, and bank account numbers. This was not a direct Stripe platform breach.
- (2024-2025) Web skimming campaign exploited legacy Stripe API endpoints to validate stolen credit card data across approximately 49 merchant sites. Stripe infrastructure was not compromised.
Changelog
| Date | Version | Maturity | Changes | Author |
|---|---|---|---|---|
| 2025-02-05 | 0.1.0 | draft | Initial guide with SSO and API security | Claude Code (Opus 4.5) |
Contributing
Found an issue or want to improve this guide?
- Report outdated information: Open an issue with tag
content-outdated - Propose new controls: Open an issue with tag
new-control - Submit improvements: See Contributing Guide