Why is Core Banking Security Different?

In a typical application, a security vulnerability might lead to a data breach. In Core Banking, a vulnerability leads directly to lost money — the money of millions of customers. This is why the banking sector has the strictest security standards in the world.


PCI-DSS — Payment Card Industry Data Security Standard

PCI-DSS is a mandatory set of standards for any organization that stores, processes, or transmits payment card data (Visa, Mastercard, JCB…). Violating PCI-DSS can result in millions of dollars in fines and being banned from processing card payments.

The 12 Core Requirements of PCI-DSS v4.0

#RequirementTechnical Implication
1Firewall & Network ControlNetwork segmentation, never expose Core Banking to the public internet
2No Vendor DefaultsChange all default passwords, disable unnecessary services
3Protect Stored Card DataNever store CVV/CVV2. Encrypt PAN (card number) with AES-256
4Encrypt TransmissionTLS 1.2+ mandatory for all card data transmissions
5Anti-VirusProtect all systems against malware
6Secure DevelopmentSAST, DAST, strict code reviews, OWASP Top 10
7Restrict AccessPrinciple of Least Privilege — access strictly on a need-to-know basis
8Identity & AuthMFA is mandatory for admins, no shared accounts
9Physical AccessControl physical access to datacenters
10Monitor & LogLog all access to cardholder data, retain for 12 months
11PentestRegular penetration testing at least annually
12Security PolicyMaintain an information security policy, train staff

Handling Card Data Correctly

Card Data Classification:

╔══════════════════════════════════════════════════════════╗
║  NEVER STORE UNDER ANY CIRCUMSTANCES                    ║
║  • CVV/CVV2/CVC (3-4 digits on the back)                ║
║  • PIN block                                            ║
║  • Track 1/Track 2 data (magnetic stripe data)          ║
╠══════════════════════════════════════════════════════════╣
║  STORED ONLY IF STRONGLY ENCRYPTED                      ║
║  • PAN (Primary Account Number = the 16 digits)         ║
║    → Requires Tokenization or AES-256 encryption        ║
║  • Expiration Date                                      ║
║  • Cardholder Name                                      ║
╚══════════════════════════════════════════════════════════╝

Tokenization

Instead of storing the real card number, the system generates a meaningless token. This token cannot be used to execute transactions if stolen.

Real Card Number: 4111 1111 1111 1111
Token:            8293 4721 9834 5612  (random, no mathematical relationship)

Mapping (inside an HSM or Secure Token Vault):
  8293 4721 9834 5612 → 4111 1111 1111 1111

AML & CFT — Anti-Money Laundering

AML (Anti-Money Laundering) and CFT (Countering the Financing of Terrorism) are legal obligations. Core Banking Developers must build automated detection mechanisms.

Detection Techniques

1. Transaction Monitoring Rules:

Example Rules:
- Cash transaction > $10,000 → Generate an STR (Suspicious Transaction Report)
- Single account receives > 10 transactions < $10,000 in 24h (Structuring/Smurfing)
- Transfers to FATF High-Risk countries

2. Customer Risk Scoring:

type CustomerRiskScore struct {
    CIFNumber     string
    Score         int     // 0-100
    RiskLevel     string  // "LOW", "MEDIUM", "HIGH"
    Factors       []string
    // ["PEP", "HIGH_RISK_COUNTRY", "CASH_INTENSIVE_BUSINESS"]
    LastUpdated   time.Time
}

3. Sanctions Screening: Check all transactions and customers against international watchlists:

  • OFAC (US Treasury)
  • UN Security Council
  • EU Consolidated List

Designing the Audit Trail

Every action in Core Banking must have an immutable audit trail. This is a strict legal requirement.

The Audit Log Table

CREATE TABLE audit_logs (
    id              UUID        PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_type     VARCHAR(50) NOT NULL,   -- 'ACCOUNT', 'CUSTOMER', 'TRANSACTION'
    entity_id       VARCHAR(50) NOT NULL,   -- ID of the modified entity
    action          VARCHAR(50) NOT NULL,   -- 'CREATE', 'UPDATE', 'DELETE', 'VIEW'
    actor_id        VARCHAR(50) NOT NULL,   -- ID of user/system performing action
    actor_type      VARCHAR(20) NOT NULL,   -- 'STAFF', 'CUSTOMER', 'SYSTEM', 'API'
    ip_address      INET,
    before_state    JSONB,                  -- State prior to change
    after_state     JSONB,                  -- State after change
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
    
    -- No updated_at column — audit logs are immutable
    -- NEVER UPDATE or DELETE from this table
);

-- Guarantee immutability via PostgreSQL Row Security
ALTER TABLE audit_logs ENABLE ROW LEVEL SECURITY;
CREATE POLICY audit_insert_only ON audit_logs FOR INSERT WITH CHECK (true);
-- INSERT only, no SELECT without rights, absolutely no UPDATE/DELETE

Append-Only Pattern for the Ledger

-- Trigger to prevent UPDATE/DELETE on the ledger
CREATE OR REPLACE FUNCTION prevent_ledger_modification()
RETURNS TRIGGER AS $$
BEGIN
    RAISE EXCEPTION 'Ledger entries are immutable. Use reversal entries to correct errors.';
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER ledger_immutability_guard
    BEFORE UPDATE OR DELETE ON ledger_entries
    FOR EACH ROW EXECUTE FUNCTION prevent_ledger_modification();

Hardware Security Modules (HSM)

An HSM is a dedicated physical hardware device that performs the most sensitive cryptographic operations (PIN encryption, card key generation, digital signatures). Cryptographic keys never leave the HSM in plaintext.

PIN Processing Flow (ATM Withdrawal):
1. ATM: Encrypts PIN with a PIN Encryption Key (PEK) → generates a PIN Block
2. Core Banking → forwards the PIN Block to the HSM
3. HSM: decrypts the PIN Block → verifies PIN against stored offset → returns "VALID"/"INVALID"
4. The plaintext PIN NEVER appears in the application code memory

This concludes the theoretical portion. It’s time to apply everything we’ve learned. Continue reading Part 7 — Practice: Build a Mini Core Banking System from Scratch to start coding.