Payment Card Industry Data Security Standard (PCI DSS) compliance is often treated as a checklist exercise. But the difference between "technically compliant" and "actually secure" is where most teams stumble. Here are the eight areas where engineering teams consistently struggle.
1. Encryption Key Management
The obvious part: encrypt cardholder data. The part teams miss: key management.
Common mistakes: - Keys stored in the same database as encrypted data - Hardcoded keys in application code - No key rotation procedures - Developers with production key access for "debugging"
What good looks like: - Hardware Security Modules (HSMs) for key storage - Split-knowledge key management (no single person has full keys) - Automated key rotation schedules - Separate key management systems from data systems
The standard requires unique cryptographic keys per merchant and regular rotation. But the spirit goes deeper: if an attacker gets your database, they shouldn't automatically get the keys too.
2. Network Segmentation Reality
Requirement 1 talks about network security. Most teams build a firewall and call it done.
The real requirement: Your cardholder data environment (CDE) should be completely isolated. An attacker who compromises a non-payment system shouldn't be able to reach your payment systems at all.
What teams miss: - Development environments connected to production networks - Shared jump boxes between CDE and corporate networks - Cloud VPCs that aren't actually isolated - Container networks that span security boundaries
Better approach: - Dedicated VPCs/VNets for payment processing - Zero-trust architecture (verify every connection, even internal) - Explicit allow-lists for CDE network traffic - Regular penetration testing of segmentation controls
3. Logging What Matters
Requirement 10 mandates logging. But logging everything creates noise that hides attacks.
What to actually log in payment systems: - All access to cardholder data (who, when, what) - All actions by administrators - All authentication attempts (success and failure) - All changes to audit logs themselves - All changes to security configurations
What teams get wrong: - Logging to the same system being monitored - No log integrity verification (attackers modify logs) - Logs without timestamps or inconsistent timezones - No correlation across systems - Retention periods that don't meet requirements (1 year, 3 months immediately available)
Better approach: - Centralized logging to separate systems - Cryptographic log signing for integrity - UTC timestamps everywhere - Automated alerting on security events - Regular log review (not just during incidents)
4. The Testing Requirement Nobody Follows
Requirement 11 requires regular testing. This isn't optional, but teams treat it as annual checkbox work.
What's actually required: - Quarterly external vulnerability scans (by Approved Scanning Vendor) - Annual penetration testing - Testing after significant changes - Internal vulnerability scans quarterly
The part teams skip: Testing after "significant changes." That new payment feature you launched? That counts. Upgrading your payment processing library? That counts too.
Better approach: - Integrate security scanning into CI/CD pipelines - Define "significant change" criteria in advance - Budget for penetration testing after major releases - Treat failed scans as deployment blockers
5. Third-Party Risk Is Your Risk
Using Stripe? Square? A white-label payment processor? Great. But their compliance doesn't cover your integration.
Your responsibilities still include: - Secure API key management - Secure webhook handling - Any cardholder data that touches your systems (even briefly) - Your frontend code that collects card data
The tokenization trap: Many teams think "we use tokenization so we're out of scope." Not quite. If your JavaScript ever touches a card number (even to send it to Stripe) your frontend is in scope.
Better approach: - Use iframe-based card collection (Stripe Elements, etc.) - Never let card numbers touch your JavaScript - Review third-party security assessments annually - Map exactly where data flows between you and providers
6. Default Credentials and Unnecessary Services
Requirement 2: Don't use vendor-supplied defaults. Sounds obvious. It isn't.
Where defaults hide: - Database admin passwords from install scripts - Default SSH keys in container images - Cloud service default configurations - Network equipment (routers, firewalls) - Monitoring and logging tools
Unnecessary services are the other half: That MySQL installation includes features you don't need. That base OS image has services you'll never use. Each is an attack surface.
Better approach: - Automated configuration management (Terraform, Ansible) - Base images that are minimal by design - Regular audits of running services - Infrastructure-as-code with compliance checks
7. Documentation That Actually Helps
Every PCI DSS requirement includes documentation. Most teams create documents once and never update them.
Documents you need: - Network diagrams (actual current state, not original design) - Data flow diagrams (where cardholder data moves) - Policies and procedures for each requirement - Incident response plans - Vendor management procedures
The real problem: These documents often describe how things "should" work, not how they actually work. When the auditor asks to see your network diagram, does it match reality?
Better approach: - Generate diagrams from infrastructure-as-code - Version control all documentation - Review documentation with each significant change - Annual documentation audit against actual systems
8. Access Control Gaps
Requirement 7 (restrict access by business need) and Requirement 8 (unique IDs) sound simple. Implementation is harder.
Where teams fail: - Shared accounts "for deployment" - Overly broad admin access because it's easier - Stale accounts after employees leave - No regular access reviews - Password policies that don't match requirements
PCI DSS 4.0 changes: The latest version requires multi-factor authentication for all access to the CDE, not just remote access. If your developers SSH into payment servers with just a password, that's a finding.
Better approach: - Role-based access control with minimal permissions - Automated access provisioning/deprovisioning - Quarterly access reviews with manager approval - MFA everywhere (including local console access) - Service accounts with restricted, audited permissions
Beyond Compliance
Here's the uncomfortable truth: passing your PCI assessment doesn't mean you're secure. It means you've met a minimum bar that was designed years ago.
The gap between compliance and security: - Compliance is point-in-time; security is continuous - Compliance checks for controls; security measures effectiveness - Compliance is often prescriptive; security requires judgment
What actually secure payment systems have: - Security team involvement from design through deployment - Automated security testing in every pipeline - Incident response plans that get practiced, not just written - Culture where engineers raise security concerns - Regular third-party security assessments beyond PCI
The teams that struggle most are those who treat PCI as a checkbox exercise. The ones who succeed treat compliance as the floor, not the ceiling.
Building a payment system and want to get security right from the start? [Let's architect it together](/contact).