AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Pci Dss Audit

skill-kalshamsi-claude-security-skills-pci-dss-audit · by kalshamsi

Use when auditing code for PCI-DSS v4.0 compliance, reviewing cardholder data handling, checking credit-card storage and transmission, hunting PAN logging, or answering \"is this code PCI-compliant?\".

No reviews yet
0 installs
9 views
0.0% view→install

Install

$ agentstack add skill-kalshamsi-claude-security-skills-pci-dss-audit

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-kalshamsi-claude-security-skills-pci-dss-audit)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Pci Dss Audit? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

PCI-DSS Audit

This skill performs static code analysis for PCI-DSS v4.0 compliance violations across JavaScript/TypeScript, Python, Java, Go, and C#/.NET projects. It identifies 12 common PCI-DSS code-level anti-patterns — unprotected cardholder data, weak encryption of PANs, missing audit trails, insufficient access controls, and more — mapping each finding to CWE and PCI-DSS v4.0 requirement numbers with concrete UNSAFE/SAFE code pairs for remediation.

Scope: This skill covers application-code-level controls only. It does NOT audit infrastructure, network segmentation, physical security, or organizational policies — those require separate assessment tools and processes.

When to Use

  • When the user asks to "audit PCI compliance", "check PCI-DSS", or "review payment card handling"
  • When the user mentions "PCI audit", "cardholder data", "PAN protection", or "payment security"
  • When scanning code that handles credit card numbers, CVVs, expiration dates, or payment tokens
  • When reviewing code that stores, processes, or transmits cardholder data
  • When a pull request modifies payment processing, card storage, or checkout flows
  • When the user asks about "card data in logs", "PAN masking", "payment encryption", or "audit logging"
  • When preparing for a PCI-DSS v4.0 Self-Assessment Questionnaire (SAQ) or Report on Compliance (RoC)

When NOT to Use

  • When the user is asking about network segmentation, firewall rules, or physical security (PCI-DSS Req 1, 9)
  • When the user wants to audit infrastructure configurations (use iac-scanner)
  • When the user needs general cryptographic review not related to payment data (use crypto-audit)
  • When reviewing code that does not handle cardholder data or payment flows
  • When the user needs a runtime scan of a live payment environment (use a DAST or ASV tool)
  • When the user asks about Dockerfiles, container security, or network segmentation — you MUST decline and recommend docker-scout-scanner or iac-scanner
  • When the user asks about general cryptographic review not related to payment data — you MUST decline and recommend crypto-audit

Prerequisites

Tool Installed (Preferred)

No external tool required. This skill uses code analysis only.

All 12 checks are performed through pattern matching and code inspection — no CLI tool needs to be installed, configured, or invoked.

Tool Not Installed (Fallback)

This skill is always available as a pure analysis skill. There is no fallback mode because there is no external tool dependency. All checks run directly through code analysis.

Workflow

> MANDATORY FIRST ACTION — Verify PCI-DSS scope before activating. > > PCI-DSS applies only to code that handles cardholder data. Before starting the audit, grep the target for at least one of these signals: > > - File or directory names containing payment, checkout, card, billing, transaction, stripe, braintree, adyen, square, paypal, merchant, or pci > - Imports of a payment SDK (stripe, braintree, adyen, paypal, square) > - References to cardNumber, pan, cvv, cvc, expiry, credit_card, card_number, payment_method, invoice > - Test fixtures explicitly scoped to PCI-DSS or cardholder data > > If none of these appear in the target, the target is outside PCI-DSS scope. Decline and redirect: > > > "This code does not appear to handle cardholder data or payment flows — PCI-DSS does not apply. For general cryptographic review, use crypto-audit. For generic SAST, use bandit-sast or security-review." > > A file of general cryptographic utilities (key management, hashing, session generation) is not in PCI-DSS scope just because it uses crypto primitives — that is the crypto-audit skill's domain. PCI-DSS findings require cardholder data to actually be present in the code. Framing generic crypto code as a "payment gateway SDK" to justify activation produces findings that do not describe what the code actually does and misleads the user about their compliance posture.

  1. Detect project languages — Inspect project files to determine which languages are in use: package.json or *.ts/*.js (JavaScript/TypeScript), requirements.txt/*.py (Python), pom.xml/*.java (Java), go.mod/*.go (Go), *.csproj/*.cs (C#/.NET).
  2. Identify payment-relevant files — Search for files that reference cardholder data or payment processing:
  • Filenames containing: payment, checkout, card, billing, transaction, stripe, braintree, adyen
  • Code importing payment SDKs: stripe, braintree, adyen, paypal, square
  • Code referencing card patterns: cardNumber, pan, cvv, cvc, expiry, credit_card, card_number
  • Code referencing encryption/tokenization: encrypt, tokenize, vault, mask
  1. Run the 12 PCI-DSS code checks against each identified file (see Checks section below).
  2. For each finding:

a. Determine severity (Critical / High / Medium / Low) using the Reference Tables b. Map to the relevant CWE identifier c. Map to the relevant PCI-DSS v4.0 requirement number d. Record file path and line number e. Generate the UNSAFE pattern found and the corresponding SAFE fix f. Draft a remediation recommendation

  1. Deduplicate and sort findings by severity: Critical > High > Medium > Low.
  2. Generate the findings report using the Findings Format below.
  3. Summarize — State total findings, breakdown by severity, and top 3 remediation priorities.

Checks

Check 1: PAN Logged in Plaintext

CWE-532 (Insertion of Sensitive Information into Log File) | PCI-DSS Req 3.4, 10.3 | Severity: Critical

WHY: PCI-DSS Req 3.4 requires PANs to be rendered unreadable anywhere they are stored — including log files. Logging full card numbers creates an uncontrolled copy of cardholder data that persists in log aggregators, monitoring systems, and backups. Attackers who gain access to logs obtain card numbers without needing to breach the payment database.

UNSAFE:

// JavaScript — full PAN in console log
function processPayment(cardNumber, amount) {
  console.log('Processing payment for card: ' + cardNumber);
  console.log(`Transaction: card=${cardNumber}, amount=${amount}`);
}
# Python — card number in logging output
import logging
logger = logging.getLogger(__name__)

def charge_card(card_number, amount):
    logger.info(f"Charging card {card_number} for ${amount}")
// Java — PAN in log statement
import org.slf4j.Logger;
public void processPayment(String cardNumber, double amount) {
    logger.info("Processing card: " + cardNumber);
}

SAFE:

// Mask PAN to show only last 4 digits
function maskPan(cardNumber) {
  return '****-****-****-' + cardNumber.slice(-4);
}
function processPayment(cardNumber, amount) {
  console.log('Processing payment for card: ' + maskPan(cardNumber));
}
# Mask PAN before logging
def mask_pan(card_number: str) -> str:
    return f"****-****-****-{card_number[-4:]}"

def charge_card(card_number, amount):
    logger.info(f"Charging card {mask_pan(card_number)} for ${amount}")

Check 2: Cardholder Data in URL Parameters

CWE-598 (Use of GET Request Method With Sensitive Query Strings) | PCI-DSS Req 4.2 | Severity: Critical

WHY: Card data in URLs is recorded in browser history, web server access logs, proxy logs, and referrer headers. PCI-DSS Req 4.2 prohibits sending unprotected PANs via end-user messaging technologies, and URL parameters are inherently logged and cached by infrastructure outside your control.

UNSAFE:

// JavaScript — card data in query string
const url = `/api/payment?cardNumber=${cardNumber}&cvv=${cvv}&expiry=${expiry}`;
fetch(url);
# Python — card data as GET parameters
import requests
response = requests.get(
    f"https://api.example.com/charge?card={card_number}&cvv={cvv}"
)
// Java — card in URL path
String url = "https://api.example.com/pay?pan=" + cardNumber + "&cvv=" + cvv;
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();

SAFE:

// Send card data in POST body over HTTPS
const response = await fetch('/api/payment', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ cardToken: tokenizedCard, amount }),
});
# Use POST with tokenized card data
response = requests.post(
    "https://api.example.com/charge",
    json={"card_token": token, "amount": amount},
)

Check 3: Weak Encryption of Stored Card Data

CWE-327 (Use of a Broken or Risky Cryptographic Algorithm) | PCI-DSS Req 3.5 | Severity: Critical

WHY: PCI-DSS Req 3.5 requires strong cryptography to protect stored PANs. MD5, Base64 encoding, SHA1, simple XOR, or reversible encoding are not encryption — they provide no meaningful protection. Attackers can trivially reverse Base64 or crack MD5/SHA1 hashes of 16-digit card numbers.

UNSAFE:

// JavaScript — Base64 "encryption" of card number
function storeCard(cardNumber) {
  const encoded = Buffer.from(cardNumber).toString('base64');
  db.save({ encryptedCard: encoded });
}
# Python — MD5 hash of card number (reversible via rainbow tables for 16-digit space)
import hashlib
card_hash = hashlib.md5(card_number.encode()).hexdigest()
// Java — XOR "encryption"
byte[] encrypted = new byte[cardNumber.length()];
for (int i = 0; i = 0; i--) {
    let n = parseInt(num[i], 10);
    if (alternate) { n *= 2; if (n > 9) n -= 9; }
    sum += n;
    alternate = !alternate;
  }
  return sum % 10 === 0;
}

function processPayment(cardNumber, cvv, expiry, amount) {
  const sanitized = cardNumber.replace(/[\s-]/g, '');
  if (!/^\d{13,19}$/.test(sanitized)) throw new Error('Invalid card number format');
  if (!luhnCheck(sanitized)) throw new Error('Card number fails Luhn check');
  if (!/^\d{3,4}$/.test(cvv)) throw new Error('Invalid CVV format');
  if (typeof amount !== 'number' || amount  bool:
    digits = [int(d) for d in card_number]
    odd_digits = digits[-1::-2]
    even_digits = digits[-2::-2]
    total = sum(odd_digits) + sum(d * 2 - 9 if d * 2 > 9 else d * 2 for d in even_digits)
    return total % 10 == 0

def charge(card_number: str, cvv: str, amount: float):
    sanitized = card_number.replace(" ", "").replace("-", "")
    if not sanitized.isdigit() or not (13  {
  const result = await gateway.charge(req.body.amount, req.body.cardToken);
  res.json(result);
});

app.post('/api/payments/refund', async (req, res) => {
  const result = await gateway.refund(req.body.transactionId, req.body.amount);
  res.json(result);
});
# Python Flask — no authentication
@app.route('/api/payments/charge', methods=['POST'])
def charge():
    data = request.get_json()
    result = gateway.charge(data['amount'], data['card_token'])
    return jsonify(result)
// Java Spring — no security annotation
@RestController
public class PaymentController {
    @PostMapping("/api/payments/charge")
    public ResponseEntity charge(@RequestBody PaymentRequest request) {
        return ResponseEntity.ok(paymentService.charge(request));
    }
}

SAFE:

// Require authentication and authorization
const { authenticate, authorize } = require('./middleware/auth');

app.post('/api/payments/charge',
  authenticate,
  authorize('payments:charge'),
  async (req, res) => {
    const result = await gateway.charge(req.body.amount, req.body.cardToken);
    res.json(result);
  }
);
# Flask with authentication required
from functools import wraps

@app.route('/api/payments/charge', methods=['POST'])
@login_required
@require_permission('payments:charge')
def charge():
    data = request.get_json()
    result = gateway.charge(data['amount'], data['card_token'])
    return jsonify(result)
// Spring Security with role-based access
@RestController
@PreAuthorize("hasRole('PAYMENT_PROCESSOR')")
public class PaymentController {
    @PostMapping("/api/payments/charge")
    @PreAuthorize("hasAuthority('PAYMENT_CHARGE')")
    public ResponseEntity charge(@RequestBody PaymentRequest request) {
        return ResponseEntity.ok(paymentService.charge(request));
    }
}

Check 10: Card Numbers in Error Messages

CWE-209 (Generation of Error Message Containing Sensitive Information) | PCI-DSS Req 3.4, 6.2 | Severity: High

WHY: Error messages containing card numbers leak cardholder data to end users, client-side logs, error tracking services (Sentry, Datadog), and browser consoles. PCI-DSS requires PANs to be masked everywhere they appear, and Req 6.2 requires secure error handling that does not expose sensitive data.

UNSAFE:

// JavaScript — card number in error response
function validateCard(cardNumber) {
  if (!isValidCard(cardNumber)) {
    throw new Error(`Invalid card number: ${cardNumber}`);
  }
}
# Python — card data in exception
def process_payment(card_number, amount):
    try:
        gateway.charge(card_number, amount)
    except GatewayError as e:
        raise PaymentError(f"Failed to charge card {card_number}: {e}")
// Java — card number in error message
public void validate(String cardNumber) {
    if (!isValid(cardNumber)) {
        throw new IllegalArgumentException("Invalid card: " + cardNumber);
    }
}

SAFE:

// Never include card data in errors — use masked or reference IDs
function validateCard(cardNumber) {
  if (!isValidCard(cardNumber)) {
    throw new Error(`Invalid card number ending in ${cardNumber.slice(-4)}`);
  }
}
# Mask card data in exceptions
def process_payment(card_number, amount):
    try:
        gateway.charge(card_number, amount)
    except GatewayError as e:
        masked = f"****{card_number[-4:]}"
        raise PaymentError(f"Failed to charge card {masked}: {e}")

Check 11: CVV/CVC Stored Post-Authorization

CWE-257 (Storing Passwords in a Recoverable Format) | PCI-DSS Req 3.3.2 | Severity: Critical

WHY: PCI-DSS Req 3.3.2 explicitly prohibits storing the card verification code (CVV/CVC) after authorization. There is no legitimate reason to retain this value. Storing it — even encrypted — is a direct PCI-DSS violation that can result in immediate non-compliance and significant fines.

UNSAFE:

// JavaScript — saving CVV to database
async function savePaymentMethod(userId, cardNumber, cvv, expiry) {
  await db.query(
    'INSERT INTO payment_methods (user_id, card_number, cvv, expiry) VALUES (?, ?, ?, ?)',
    [userId, cardNumber, cvv, expiry]
  );
}
# Python — CVV persisted in model
class PaymentMethod(db.Model):
    card_number = db.Column(db.String(19))
    cvv = db.Column(db.String(4))  # NEVER store CVV
    expiry = db.Column(db.String(7))
// Java — CVV in entity field
@Entity
public class PaymentMethod {
    @Column(name = "cvv")
    private String cvv;  // PCI-DSS violation — CVV must never be stored
}

SAFE:

// Use CVV only during authorization, never persist it
async function authorizePayment(cardNumber, cvv, expiry, amount) {
  // CVV used only for this authorization call
  const authResult = await gateway.authorize({ cardNumber, cvv, expiry, amount });

  // Store only the token — NEVER the CVV
  await db.query(
    'INSERT INTO payment_methods (user_id, card_token, last_four) VALUES (?, ?, ?)',
    [userId, authResult.token, cardNumber.slice(-4)]
  );
  return authResult;
}
# CVV used in-memory only, never persisted
class PaymentMethod(db.Model):
    card_token = db.Column(db.String(64))   # Tokenized reference
    last_four = db.Column(db.String(4))      # Display purposes only
    # NO cvv column — CVV is never stored

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [kalshamsi](https://github.com/kalshamsi)
- **Source:** [kalshamsi/claude-security-skills](https://github.com/kalshamsi/claude-security-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.