本文へ移動
cccskills
無料GitHub で公開

pci-dss-control-test-author

Build-an-X for PCI DSS v4.0 scope verification - cardholder data environment (CDE) boundary tests, segmentation tests (PCI Req 1), prohibited-data-storage assertions per Req 3 (no full track data, no CVV/CAV2/CVC2/CID, no PIN/PIN block post-authorization), key-management tests per Req 3.6, encryption-of-transmissions per Req 4; includes the scope catalog (SAQ A / A-EP / D levels, PAN-storage rules, hosted-fields / tokenization scope-reduction patterns) in references/pci-scope.md. Use when authoring PCI DSS scope-reduction + control tests for any system handling payment-card data, or when determining a payment integration's SAQ level.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qaスター 13(GitHub 13 + cccskills 0)

実行スコア 未検証

インストール方法を見る

含まれるファイル(4)

  • SKILL.md10.9 KB
  • .tessl-plugin/plugin.json785 B
  • references/pci-scope.md6.1 KB
  • references/strategies.md1.6 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

pci-dss-control-test-author

This is a build-an-X workflow for verifying CDE scope is correctly bounded and prohibited-data assertions are captured in fixtures, targeting PCI DSS v4.0 (fully required March 2025).

Helper stubs

Key interfaces used across steps (provided by the test harness):

# network / infra
def network_policy.get_allowed_connections(src: str, dst: str) -> list[str]: ...

# data-access
def export_database() -> DatabaseDump: ...
def recent_logs() -> list[LogEntry]: ...
def scan_repo_files() -> list[str]: ...
def read_file(path: str) -> str: ...

# TLS inspection - TLSInfo has: .protocol (str e.g. 'TLSv1.2'), .cipher_strength (int), .cipher (str)
def inspect_tls(endpoint: str) -> TLSInfo: ...

# crypto / format
def is_encrypted_aes_256(value: str) -> bool: ...
def is_truncated_last_4(value: str) -> bool: ...
def is_hashed_with_salt(value: str) -> bool: ...
def is_tokenized(value: str) -> bool: ...
def redact(value: str) -> str: ...

# constants
CDE_API_ENDPOINTS: list[str] = [...]   # All API endpoints inside the CDE
DEPRECATED_CIPHERS: list[str] = [...]  # e.g. ['RC4', 'DES', '3DES', 'NULL']

Step 1 - Define + assert CDE boundary

# pci_scope.py
# untested CDE/non-CDE network policy drifts into a segmentation breach
CDE_SYSTEMS = {
    'payment-service',
    'tokenization-service',
    'card-vault-db',
    'pci-zone-fw',
}
NON_CDE_SYSTEMS = {
    'web-frontend',     # tokens only; no raw PAN
    'analytics',         # never sees PAN
    'support-tickets',   # never sees PAN
}

def test_cde_systems_isolated_from_non_cde():
    for cde_system in CDE_SYSTEMS:
        for non_cde in NON_CDE_SYSTEMS:
            # Network policy MUST block direct connections from non-CDE to CDE
            allowed = network_policy.get_allowed_connections(cde_system, non_cde)
            # Only via tokenization gateway (via PCI zone FW)
            assert allowed == [] or allowed == ['via-pci-zone-fw']

Segmentation testing per PCI DSS Req 11.4.1 must be performed at least every 6 months by a qualified internal resource OR external penetration tester.

Checkpoint: If any CDE/non-CDE boundary assertion fails, halt and remediate the network policy before proceeding. A segmentation failure means downstream steps may be testing a mis-scoped environment.


Step 2 - Assert no SAD storage post-authorization (Req 3.2)

SAD may transit during auth but storage after auth completes (logs, DB, audit trails, backup) is forbidden - full track data, CVV2/CVC2/CID, and PIN/PIN block, all never post-authorization.

import re

# PAN slips into a log line if you trust developers never to log it
TRACK1_PATTERN = re.compile(r'%[A-Z]\d{12,19}\^[^\?]*\?\d*\?')   # Track 1
CVV_PATTERN    = re.compile(r'(?<!\d)\d{3,4}(?!\d)')               # naive; pair with DLP

def test_no_full_track_data_in_storage():
    """Req 3.2.1: track data must not be retained post-authorization."""
    db_dump = export_database()
    for table in db_dump.tables:
        for row in table:
            for value in row.values():
                assert not TRACK1_PATTERN.search(str(value)), \
                    f"Full track data in {table.name}"

def test_no_cvv_in_logs():
    """Req 3.2.2: CVV2/CVC2/CID must not be retained."""
    log_entries = recent_logs()
    for entry in log_entries:
        # Look for proximity of CVV-like 3-4 digit numbers near "cvv" / "card" tokens
        if 'cvv' in entry.text.lower() or 'card' in entry.text.lower():
            matches = CVV_PATTERN.findall(entry.text)
            for m in matches:
                assert m == '***' or m == '----', \
                    f"Possible CVV in log: {entry.id}"

Checkpoint: If SAD is found in storage or logs, halt and remediate before proceeding to Step 3. Continuing to test encryption-at-rest while SAD is present misrepresents compliance posture. File a severity-1 finding and trigger your incident response process before re-running.


Step 3 - Assert PAN encryption at rest (Req 3.4) + key management (Req 3.6)

# hardcoded encryption keys in the repo are a Req 3.6 violation and expose PAN

def test_pan_stored_encrypted():
    """Req 3.4: PAN unreadable wherever stored (encryption / truncation / hashing / tokenization).
    Prefer tokenization for new paths; treat the others as escape hatches for pre-existing systems.
    """
    card_record = CardVault.objects.first()
    raw_pan = card_record._raw_pan_field    # accessor for storage-format field

    # Format MUST be one of:
    #  - encrypted (AES-256 or stronger)         <- preferred for new paths
    #  - truncated (e.g., last 4 only)
    #  - hashed (with salt; one-way)
    #  - tokenized (replaced with non-sensitive token)  <- default for new systems
    valid_format = (
        is_encrypted_aes_256(raw_pan)
        or is_truncated_last_4(raw_pan)
        or is_hashed_with_salt(raw_pan)
        or is_tokenized(raw_pan)
    )
    assert valid_format, f"PAN stored unprotected: {redact(raw_pan)}"

def test_decryption_keys_not_in_app_repo():
    """Req 3.6: cryptographic keys protected against unauthorized access."""
    repo_files = scan_repo_files()
    for f in repo_files:
        content = read_file(f)
        # No hardcoded AES keys (high entropy + length 256+ bits)
        assert not re.search(r'AES_KEY\s*=\s*["\'][A-Za-z0-9+/=]{40,}', content), \
            f"Possible hardcoded AES key in {f}"
        # No KMS key file references
        assert 'kms-private-key.pem' not in f, \
            f"KMS private key file referenced in repo: {f}"

Checkpoint: If PANs are stored unprotected or keys are found in the repo, halt. Key-in-repo findings require immediate secret rotation before continuing.


Step 4 - Encryption of transmissions (Req 4)

# TLS 1.0 / 1.1 still enabled is a Req 4 violation
def test_pan_only_transmitted_via_strong_crypto():
    """Req 4.2.1: strong crypto for transmission of cardholder data over open networks."""
    for endpoint in CDE_API_ENDPOINTS:
        tls_info = inspect_tls(endpoint)
        assert tls_info.protocol >= 'TLSv1.2', \
            f"Weak TLS protocol on {endpoint}: {tls_info.protocol}"
        assert tls_info.cipher_strength >= 256, \
            f"Cipher strength too low on {endpoint}: {tls_info.cipher_strength}"
        assert tls_info.cipher not in DEPRECATED_CIPHERS, \
            f"Deprecated cipher on {endpoint}: {tls_info.cipher}"

Checkpoint: TLS failures on any CDE endpoint are blocking. Deprecated protocols (TLS 1.0 / 1.1) must be disabled before proceeding to access-control testing.


Step 5 - Access control (Req 7 + 8)

import os

# Test-account passwords come from the CI secret store via env vars, never
# literals in test code (a literal password in a CDE test is itself a Req 8 finding).

# generic shared accounts (e.g. 'admin' / 'svc-account') violate Req 8.2.1
def test_cde_access_requires_unique_id():
    """Req 8.2.1: assign all users a unique ID before access to system components."""
    # No shared / generic accounts
    response = client.post('/cde-api/login', json={
        'username': 'shared-svc',
        'password': os.environ['CDE_SHARED_SVC_PASSWORD'],
    })
    assert response.status_code == 403

def test_cde_access_requires_mfa():
    """Req 8.4: implement MFA for all access into the CDE."""
    response = client.post('/cde-api/login', json={
        'username': 'alice@example.com',
        'password': os.environ['CDE_TEST_USER_PASSWORD'],
        # No MFA token
    })
    assert response.status_code == 401
    assert response.json()['error'] == 'mfa_required'

Checkpoint: Shared-account or MFA bypass failures are blocking. Do not proceed to logging tests while unauthorized access paths remain open.


Step 6 - Logging (Req 10)

Cross-ref audit-trail-test-author:

def test_pan_access_creates_audit_record():
    """Req 10.2: audit trails to reconstruct events."""
    user.access_card(card_id=123)
    audit = AuditLog.objects.filter(
        actor=user.id,
        action='pan_access',
        subject=f'card:{card_id}',
    ).first()
    assert audit is not None
    assert audit.timestamp is not None
    # Audit log itself MUST not contain the PAN:
    assert not re.search(r'\d{13,19}', audit.full_event_text), \
        "PAN found in audit log text - log masking is broken"

Step 7 - Scope reduction strategies

PCI DSS scope reduction is the highest-leverage cost saving. Default: tokenization - replace the PAN with a non-sensitive token at the earliest possible boundary so downstream systems handle tokens only, which shrinks the CDE the most for the least integration churn. The alternatives (hosted iframe payment page, P2PE for card-present flows, network segmentation as layered defense only) and the Req 3.4 storage-format rationale are in references/strategies.md. The full scope catalog - SAQ level selection (A / A-EP / D), PAN-storage rules, per-gateway hosted-fields patterns, and the testable behaviours the scope boundary creates - is in references/pci-scope.md.

PAN-storage format default (Req 3.4): the four is_* checks in Step 3's test_pan_stored_encrypted are an OR because pre-existing systems may already use any of them; for new storage paths pick tokenization and treat encryption / truncation / hashing as escape hatches.

Limitations

  • Targets PCI DSS v4.0; v3.2.1 has subtle differences.
  • QSA audit-style validation requires a credentialed assessor; tests verify implementation only.
  • CVV regex patterns are approximate; pair with QSA-validated DLP tooling.
  • Scope-reduction strategies require organizational and technical changes beyond this skill.

References

  • PCI Security Standards Council: home, document library (PCI DSS v4.0 docs), glossary
  • Scope catalog (SAQ levels, PAN-storage rules, scope-reduction patterns): references/pci-scope.md
  • Sister catalogs: gdpr-test-patterns (CCPA/CPRA in its references/ccpa.md), hipaa-test-patterns, soc2-evidence-collector
  • audit-trail-test-author - Req 10 audit log requirements

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

Builds a CI gate that fails the build on **new** WCAG / a11y violations introduced by a PR while grandfathering pre-existing violations on a per-rule / per-page baseline. Aggregates verdicts from axe-core / pa11y / Lighthouse a11y / WAVE / IBM Equal Access scans. Use when a project has accumulated a11y debt and a strict "zero violations" gate would block every PR - the ratchet pattern lets the team ship while preventing regressions.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Workflow skill that builds an A/B-test validity checklist from an experiment proposal, walking the canonical design-correctness gates - pre-registered OEC/power/guardrails, randomization unit + SRM check, assignment integrity, telemetry, peeking discipline, novelty/primacy, post-experiment SRM re-check - into a per-experiment checklist + sign-off form. Use when launching, auditing, or governing an experiment. For pitfall mechanics (guardrails, peeking) see experiment-results-interpreter's references; to read an already-valid result use experiment-results-interpreter; for per-SDK harness tests use experiment-sdk-testing - this gates DESIGN, not SDK code.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

The single install-flow skill: the reference contract for the PWA install flow (installability gate fields, `beforeinstallprompt` handshake, per-platform paths - Android WebAPK / iOS Share menu / Firefox no-op - and the `display-mode` post-install signal, in references/install-flow-reference.md) plus the build-an-X workflow that emits the Add-to-Home-Screen suite. Walks the four-stage timeline, emitting one test per gate cell per [web.dev/articles/install-criteria][install-criteria], the deferred-prompt → `prompt()` → `userChoice` chain per [web.dev/articles/customize-install][customize-install], the iOS Safari manual-metadata branch (`apple-touch-icon`) per [web.dev/learn/pwa/installation][learn-pwa], and the post-install `(display-mode: standalone)` MQ assertion. Output: a Playwright spec with per-stage cells plus a coverage matrix. Use when a PWA's manifest, icons, or install handler change, when install conversion drops at an unknown stage, or when triaging a flaky install assertion.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Build-an-X workflow that uses an LLM to map existing tests to spec sections - given a spec doc + the test suite, the LLM identifies which tests cover which sections, surfaces uncovered sections (gap), and recommends specific tests to add. Output is a coverage matrix per spec ID. Scope is mapping tests that already exist and naming the gaps, not authoring tests for new acceptance criteria. Use when a spec doc and a test suite both exist but nobody can say which requirements are actually covered - before a release sign-off, an audit, or a decision about where to spend the next round of test effort.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Generates tests from natural-language specs (acceptance criteria, user stories, requirements) using an LLM, with confidence scoring per test case (LLM self-assessment plus heuristics: assertion quality, naming, completeness), batching uncertain cases for human review, and integration with the team's existing test framework. Use when the user asks to generate unit tests from acceptance criteria, convert user stories to test cases, automate test creation from requirements, or augment a spec-driven test suite with AI-generated stubs that are then curated before merge.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Configures Allure Report (test-runner adapter install, `allure-results` directory wiring, `categories.json` for failure classification, `history-trend.json` retention via the copy-history-between-runs pattern), runs the Allure CLI to convert `allure-results` to a static HTML site, and uploads the report as a CI artifact. Use when the team needs richer test reporting than JUnit XML - step-level attachments, per-test history, retry tracking, and severity / epic / feature labeling across framework-agnostic adapters (pytest, Jest, JUnit, TestNG, NUnit, Mocha). As a rich static HTML report generator, it is the open-source alternative to the sunset ExtentReports (JVM/.NET per-test HTML narrative); for hosted cross-run flakiness analytics rather than a static per-run report use currents-integration.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

testland のスキルをすべて見る

このスキルの問題を報告する