Implement PCI DSS compliance requirements for secure handling of payment card data and payment systems. Use when securing payment processing, achieving PCI compliance, or implementing payment card security measures.
Add this skill
npx mdskills install sickn33/pci-complianceComprehensive PCI DSS compliance guidance with strong security examples and code
1---2name: pci-compliance3description: Implement PCI DSS compliance requirements for secure handling of payment card data and payment systems. Use when securing payment processing, achieving PCI compliance, or implementing payment card security measures.4---56# PCI Compliance78Master PCI DSS (Payment Card Industry Data Security Standard) compliance for secure payment processing and handling of cardholder data.910## Do not use this skill when1112- The task is unrelated to pci compliance13- You need a different domain or tool outside this scope1415## Instructions1617- Clarify goals, constraints, and required inputs.18- Apply relevant best practices and validate outcomes.19- Provide actionable steps and verification.20- If detailed examples are required, open `resources/implementation-playbook.md`.2122## Use this skill when2324- Building payment processing systems25- Handling credit card information26- Implementing secure payment flows27- Conducting PCI compliance audits28- Reducing PCI compliance scope29- Implementing tokenization and encryption30- Preparing for PCI DSS assessments3132## PCI DSS Requirements (12 Core Requirements)3334### Build and Maintain Secure Network351. Install and maintain firewall configuration362. Don't use vendor-supplied defaults for passwords3738### Protect Cardholder Data393. Protect stored cardholder data404. Encrypt transmission of cardholder data across public networks4142### Maintain Vulnerability Management435. Protect systems against malware446. Develop and maintain secure systems and applications4546### Implement Strong Access Control477. Restrict access to cardholder data by business need-to-know488. Identify and authenticate access to system components499. Restrict physical access to cardholder data5051### Monitor and Test Networks5210. Track and monitor all access to network resources and cardholder data5311. Regularly test security systems and processes5455### Maintain Information Security Policy5612. Maintain a policy that addresses information security5758## Compliance Levels5960**Level 1**: > 6 million transactions/year (annual ROC required)61**Level 2**: 1-6 million transactions/year (annual SAQ)62**Level 3**: 20,000-1 million e-commerce transactions/year63**Level 4**: < 20,000 e-commerce or < 1 million total transactions6465## Data Minimization (Never Store)6667```python68# NEVER STORE THESE69PROHIBITED_DATA = {70 'full_track_data': 'Magnetic stripe data',71 'cvv': 'Card verification code/value',72 'pin': 'PIN or PIN block'73}7475# CAN STORE (if encrypted)76ALLOWED_DATA = {77 'pan': 'Primary Account Number (card number)',78 'cardholder_name': 'Name on card',79 'expiration_date': 'Card expiration',80 'service_code': 'Service code'81}8283class PaymentData:84 """Safe payment data handling."""8586 def __init__(self):87 self.prohibited_fields = ['cvv', 'cvv2', 'cvc', 'pin']8889 def sanitize_log(self, data):90 """Remove sensitive data from logs."""91 sanitized = data.copy()9293 # Mask PAN94 if 'card_number' in sanitized:95 card = sanitized['card_number']96 sanitized['card_number'] = f"{card[:6]}{'*' * (len(card) - 10)}{card[-4:]}"9798 # Remove prohibited data99 for field in self.prohibited_fields:100 sanitized.pop(field, None)101102 return sanitized103104 def validate_no_prohibited_storage(self, data):105 """Ensure no prohibited data is being stored."""106 for field in self.prohibited_fields:107 if field in data:108 raise SecurityError(f"Attempting to store prohibited field: {field}")109```110111## Tokenization112113### Using Payment Processor Tokens114```python115import stripe116117class TokenizedPayment:118 """Handle payments using tokens (no card data on server)."""119120 @staticmethod121 def create_payment_method_token(card_details):122 """Create token from card details (client-side only)."""123 # THIS SHOULD ONLY BE DONE CLIENT-SIDE WITH STRIPE.JS124 # NEVER send card details to your server125126 """127 // Frontend JavaScript128 const stripe = Stripe('pk_...');129130 const {token, error} = await stripe.createToken({131 card: {132 number: '4242424242424242',133 exp_month: 12,134 exp_year: 2024,135 cvc: '123'136 }137 });138139 // Send token.id to server (NOT card details)140 """141 pass142143 @staticmethod144 def charge_with_token(token_id, amount):145 """Charge using token (server-side)."""146 # Your server only sees the token, never the card number147 stripe.api_key = "sk_..."148149 charge = stripe.Charge.create(150 amount=amount,151 currency="usd",152 source=token_id, # Token instead of card details153 description="Payment"154 )155156 return charge157158 @staticmethod159 def store_payment_method(customer_id, payment_method_token):160 """Store payment method as token for future use."""161 stripe.Customer.modify(162 customer_id,163 source=payment_method_token164 )165166 # Store only customer_id and payment_method_id in your database167 # NEVER store actual card details168 return {169 'customer_id': customer_id,170 'has_payment_method': True171 # DO NOT store: card number, CVV, etc.172 }173```174175### Custom Tokenization (Advanced)176```python177import secrets178from cryptography.fernet import Fernet179180class TokenVault:181 """Secure token vault for card data (if you must store it)."""182183 def __init__(self, encryption_key):184 self.cipher = Fernet(encryption_key)185 self.vault = {} # In production: use encrypted database186187 def tokenize(self, card_data):188 """Convert card data to token."""189 # Generate secure random token190 token = secrets.token_urlsafe(32)191192 # Encrypt card data193 encrypted = self.cipher.encrypt(json.dumps(card_data).encode())194195 # Store token -> encrypted data mapping196 self.vault[token] = encrypted197198 return token199200 def detokenize(self, token):201 """Retrieve card data from token."""202 encrypted = self.vault.get(token)203 if not encrypted:204 raise ValueError("Token not found")205206 # Decrypt207 decrypted = self.cipher.decrypt(encrypted)208 return json.loads(decrypted.decode())209210 def delete_token(self, token):211 """Remove token from vault."""212 self.vault.pop(token, None)213```214215## Encryption216217### Data at Rest218```python219from cryptography.hazmat.primitives.ciphers.aead import AESGCM220import os221222class EncryptedStorage:223 """Encrypt data at rest using AES-256-GCM."""224225 def __init__(self, encryption_key):226 """Initialize with 256-bit key."""227 self.key = encryption_key # Must be 32 bytes228229 def encrypt(self, plaintext):230 """Encrypt data."""231 # Generate random nonce232 nonce = os.urandom(12)233234 # Encrypt235 aesgcm = AESGCM(self.key)236 ciphertext = aesgcm.encrypt(nonce, plaintext.encode(), None)237238 # Return nonce + ciphertext239 return nonce + ciphertext240241 def decrypt(self, encrypted_data):242 """Decrypt data."""243 # Extract nonce and ciphertext244 nonce = encrypted_data[:12]245 ciphertext = encrypted_data[12:]246247 # Decrypt248 aesgcm = AESGCM(self.key)249 plaintext = aesgcm.decrypt(nonce, ciphertext, None)250251 return plaintext.decode()252253# Usage254storage = EncryptedStorage(os.urandom(32))255encrypted_pan = storage.encrypt("4242424242424242")256# Store encrypted_pan in database257```258259### Data in Transit260```python261# Always use TLS 1.2 or higher262# Flask/Django example263app.config['SESSION_COOKIE_SECURE'] = True # HTTPS only264app.config['SESSION_COOKIE_HTTPONLY'] = True265app.config['SESSION_COOKIE_SAMESITE'] = 'Strict'266267# Enforce HTTPS268from flask_talisman import Talisman269Talisman(app, force_https=True)270```271272## Access Control273274```python275from functools import wraps276from flask import session277278def require_pci_access(f):279 """Decorator to restrict access to cardholder data."""280 @wraps(f)281 def decorated_function(*args, **kwargs):282 user = session.get('user')283284 # Check if user has PCI access role285 if not user or 'pci_access' not in user.get('roles', []):286 return {'error': 'Unauthorized access to cardholder data'}, 403287288 # Log access attempt289 audit_log(290 user=user['id'],291 action='access_cardholder_data',292 resource=f.__name__293 )294295 return f(*args, **kwargs)296297 return decorated_function298299@app.route('/api/payment-methods')300@require_pci_access301def get_payment_methods():302 """Retrieve payment methods (restricted access)."""303 # Only accessible to users with pci_access role304 pass305```306307## Audit Logging308309```python310import logging311from datetime import datetime312313class PCIAuditLogger:314 """PCI-compliant audit logging."""315316 def __init__(self):317 self.logger = logging.getLogger('pci_audit')318 # Configure to write to secure, append-only log319320 def log_access(self, user_id, resource, action, result):321 """Log access to cardholder data."""322 entry = {323 'timestamp': datetime.utcnow().isoformat(),324 'user_id': user_id,325 'resource': resource,326 'action': action,327 'result': result,328 'ip_address': request.remote_addr329 }330331 self.logger.info(json.dumps(entry))332333 def log_authentication(self, user_id, success, method):334 """Log authentication attempt."""335 entry = {336 'timestamp': datetime.utcnow().isoformat(),337 'user_id': user_id,338 'event': 'authentication',339 'success': success,340 'method': method,341 'ip_address': request.remote_addr342 }343344 self.logger.info(json.dumps(entry))345346# Usage347audit = PCIAuditLogger()348audit.log_access(user_id=123, resource='payment_methods', action='read', result='success')349```350351## Security Best Practices352353### Input Validation354```python355import re356357def validate_card_number(card_number):358 """Validate card number format (Luhn algorithm)."""359 # Remove spaces and dashes360 card_number = re.sub(r'[\s-]', '', card_number)361362 # Check if all digits363 if not card_number.isdigit():364 return False365366 # Luhn algorithm367 def luhn_checksum(card_num):368 def digits_of(n):369 return [int(d) for d in str(n)]370371 digits = digits_of(card_num)372 odd_digits = digits[-1::-2]373 even_digits = digits[-2::-2]374 checksum = sum(odd_digits)375 for d in even_digits:376 checksum += sum(digits_of(d * 2))377 return checksum % 10378379 return luhn_checksum(card_number) == 0380381def sanitize_input(user_input):382 """Sanitize user input to prevent injection."""383 # Remove special characters384 # Validate against expected format385 # Escape for database queries386 pass387```388389## PCI DSS SAQ (Self-Assessment Questionnaire)390391### SAQ A (Least Requirements)392- E-commerce using hosted payment page393- No card data on your systems394- ~20 questions395396### SAQ A-EP397- E-commerce with embedded payment form398- Uses JavaScript to handle card data399- ~180 questions400401### SAQ D (Most Requirements)402- Store, process, or transmit card data403- Full PCI DSS requirements404- ~300 questions405406## Compliance Checklist407408```python409PCI_COMPLIANCE_CHECKLIST = {410 'network_security': [411 'Firewall configured and maintained',412 'No vendor default passwords',413 'Network segmentation implemented'414 ],415 'data_protection': [416 'No storage of CVV, track data, or PIN',417 'PAN encrypted when stored',418 'PAN masked when displayed',419 'Encryption keys properly managed'420 ],421 'vulnerability_management': [422 'Anti-virus installed and updated',423 'Secure development practices',424 'Regular security patches',425 'Vulnerability scanning performed'426 ],427 'access_control': [428 'Access restricted by role',429 'Unique IDs for all users',430 'Multi-factor authentication',431 'Physical security measures'432 ],433 'monitoring': [434 'Audit logs enabled',435 'Log review process',436 'File integrity monitoring',437 'Regular security testing'438 ],439 'policy': [440 'Security policy documented',441 'Risk assessment performed',442 'Security awareness training',443 'Incident response plan'444 ]445}446```447448## Resources449450- **references/data-minimization.md**: Never store prohibited data451- **references/tokenization.md**: Tokenization strategies452- **references/encryption.md**: Encryption requirements453- **references/access-control.md**: Role-based access454- **references/audit-logging.md**: Comprehensive logging455- **assets/pci-compliance-checklist.md**: Complete checklist456- **assets/encrypted-storage.py**: Encryption utilities457- **scripts/audit-payment-system.sh**: Compliance audit script458459## Common Violations4604611. **Storing CVV**: Never store card verification codes4622. **Unencrypted PAN**: Card numbers must be encrypted at rest4633. **Weak Encryption**: Use AES-256 or equivalent4644. **No Access Controls**: Restrict who can access cardholder data4655. **Missing Audit Logs**: Must log all access to payment data4666. **Insecure Transmission**: Always use TLS 1.2+4677. **Default Passwords**: Change all default credentials4688. **No Security Testing**: Regular penetration testing required469470## Reducing PCI Scope4714721. **Use Hosted Payments**: Stripe Checkout, PayPal, etc.4732. **Tokenization**: Replace card data with tokens4743. **Network Segmentation**: Isolate cardholder data environment4754. **Outsource**: Use PCI-compliant payment processors4765. **No Storage**: Never store full card details477478By minimizing systems that touch card data, you reduce compliance burden significantly.479
Full transparency — inspect the skill content before installing.