Skip to main content

Check out Port for yourself ➜ 

PCI DSS code security scorecard

The PCI DSS code security scorecard is designed to continuously track compliance with PCI DSS requirements by leveraging static application security testing (SAST) and software composition analysis (SCA) data from Snyk.
It helps development teams enforce secure coding practices, identify security weaknesses early in the development lifecycle, and measure progress towards PCI DSS compliance maturity.

This comprehensive security scorecard evaluates repositories and services based on:

  • Scan recency - Ensures regular vulnerability scanning (PCI DSS 6.3.1).
  • Severity of open vulnerabilities - Tracks critical and high-severity issues.
  • Cryptographic hygiene - Validates secure crypto implementation (PCI DSS 6.5.3).
  • Exposure of public-facing assets - ASV compliance for external scans (PCI DSS 11.2.2).
  • Secure dependency management - Monitors open-source component security.

Dependencies

Depends on OWASP Top 10 Scorecard to make use of some of the aggregation properties generated previously.
By organizing into levels, all teams can progressively improve security posture and demonstrate compliance readiness.

Scorecard configuration​

The scorecard evaluates repositories and services against security rules organized into five maturity levels: Basic, Bronze, Silver, Gold, and Platinum. Each level builds on the previous one, requiring increasingly strict compliance standards.

To implement this scorecard, you will need to create new properties on your Snyk Target blueprint (detailed below). The scorecard is then created on the Repository blueprint, using mirrored properties from Snyk Target.

PCI DSS Scorecard configuration (click to expand)
{
"identifier": "pci_dss_code_security",
"title": "PCI DSS Code Security",
"rules": [
{
"identifier": "sast_recent",
"level": "Bronze",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "<=",
"property": "sast_last_scan_days",
"value": 30
}
]
},
"description": "PCI 6.3.1β€”continuous vulnerability identification",
"title": "Detected ≀ 30 days ago"
},
{
"identifier": "open_critical_thresh",
"level": "Bronze",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "=",
"property": "open_critical",
"value": 0
}
]
},
"description": "No Critical SAST findings",
"title": "Open Critical Threshold"
},
{
"identifier": "class_no_inj_auth",
"level": "Silver",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "=",
"property": "a3_injection",
"value": 0
},
{
"operator": "=",
"property": "a1_access_control_flaws",
"value": 0
}
]
},
"description": "Injection, AuthN AuthZ, Hardcoded secrets",
"title": "Class Absence - Injection, Auth"
},
{
"identifier": "hardcoded_secrets",
"level": "Silver",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "=",
"property": "hardcoded_secrets",
"value": 0
}
]
},
"description": "No leaked/open secrets",
"title": "Hardcoded Secrets"
},
{
"identifier": "insecure_crypto",
"level": "Gold",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "=",
"property": "a2_cryptographic_failures",
"value": 0
}
]
},
"description": "No insecure crypto",
"title": "Insecure Crypto"
},
{
"identifier": "asv_pass_parity",
"level": "Gold",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "<",
"property": "max_risk_score_replacing_asv",
"value": 400
}
]
},
"description": "ASV pass/fail parity for public-facing assets.",
"title": "ASV Pass Parity"
},
{
"identifier": "max_risk_score",
"level": "Platinum",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "containsAny",
"property": "$team",
"value": [
"example_team"
]
}
]
},
"description": "Max Risk Score (Alternate to CVSS Scoring)",
"title": "Max Risk Score"
},
{
"identifier": "no_high_open_source",
"level": "Platinum",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "=",
"property": "open_sca_high",
"value": 0
}
]
},
"description": "No High severity open source vulnerabilities",
"title": "No High Open Source"
},
{
"identifier": "no_high_code_issues",
"level": "Platinum",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "=",
"property": "open_sast_high",
"value": 0
}
]
},
"description": "No High severity code issues",
"title": "No High Code Issues"
}
],
"levels": [
{
"color": "paleBlue",
"title": "Basic"
},
{
"color": "bronze",
"title": "Bronze"
},
{
"color": "silver",
"title": "Silver"
},
{
"color": "gold",
"title": "Gold"
},
{
"color": "lime",
"title": "Platinum"
}
]
}

New properties​

Create the following new properties on your Snyk Target blueprint, then mirror them to your Repository blueprint. You can also attach these properties to a Service blueprint if that's where the data is most relevant for your use case.

Hardcoded secrets property (click to expand)
{
"hardcoded_secrets": {
"title": "Hardcoded Secrets",
"icon": "Bug",
"type": "number",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "category",
"operator": "in",
"value": [
"CWE-798",
"CWE-259",
"CWE-321",
"CWE-547",
"CWE-260"
]
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
}
},
ASV pass parity property (click to expand)
{
"asv_pass_parity": {
"title": "ASV Pass Parity",
"icon": "Bug",
"type": "number",
"description": "Risk Scoring",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "package_vulnerability"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "score",
"operator": ">=",
"value": 500
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
},
"pathFilter": [
{
"fromBlueprint": "snykVulnerability",
"path": [
"project",
"snyk_target"
]
}
]
},
Maximum risk score aggregation property (click to expand)
{
"max_risk_score": {
"title": "Max Risk Score",
"icon": "Bug",
"type": "number",
"description": "Alternate to ASV Pass Parity CVSS > 4",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "package_vulnerability"
},
{
"property": "status",
"operator": "=",
"value": "open"
}
]
},
"calculationSpec": {
"func": "max",
"property": "score",
"calculationBy": "property"
},
"pathFilter": [
{
"fromBlueprint": "snykVulnerability",
"path": [
"project",
"snyk_target"
]
}
]
},
Critical severity package vulnerabilities property (click to expand)
{
"open_sca_critical": {
"title": "Open SCA Critical",
"icon": "Bug",
"type": "number",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "package_vulnerability"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "severity",
"operator": "=",
"value": "critical"
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
},
"pathFilter": [
{
"fromBlueprint": "snykVulnerability",
"path": [
"project",
"snyk_target"
]
}
]
},
High severity package vulnerabilities property (click to expand)
{
"open_sca_high": {
"title": "Open SCA High",
"icon": "Bug",
"type": "number",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "severity",
"operator": "=",
"value": "high"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "type",
"operator": "=",
"value": "package_vulnerability"
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
},
"pathFilter": [
{
"fromBlueprint": "snykVulnerability",
"path": [
"project",
"snyk_target"
]
}
]
},
High severity code vulnerabilities property (click to expand)
{
"open_sast_high": {
"title": "Open SAST High",
"icon": "Bug",
"type": "number",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "type",
"operator": "=",
"value": "code"
},
{
"property": "severity",
"operator": "=",
"value": "high"
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
},
"pathFilter": [
{
"fromBlueprint": "snykVulnerability",
"path": [
"project",
"snyk_target"
]
}
]
}
SAST last scan days property (click to expand)
{
"sast_last_scan_days": {
"title": "SAST Last Scan Days",
"icon": "Calendar",
"type": "number",
"description": "Number of days since the last SAST scan",
"target": "snykTarget",
"query": {
"combinator": "and",
"rules": [
{
"property": "lastScanDate",
"operator": "exists"
}
]
},
"calculationSpec": {
"func": "daysSince",
"property": "lastScanDate",
"calculationBy": "property"
}
}
}
Open critical vulnerabilities property (click to expand)
{
"open_critical": {
"title": "Open Critical",
"icon": "Bug",
"type": "number",
"description": "Number of open critical severity vulnerabilities",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "severity",
"operator": "=",
"value": "critical"
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
},
"pathFilter": [
{
"fromBlueprint": "snykVulnerability",
"path": [
"project",
"snyk_target"
]
}
]
}
}

Scorecard levels​

The scorecard uses five maturity levels, with each level building on the rules from the previous one.

LevelDescription
BasicDefault level. Indicates that the entity is in PCI scope but has not yet met Bronze criteria.
BronzeEnsures regular scanning and that no critical vulnerabilities remain open.
SilverEnforces strong secure coding practices, eliminating injection flaws, access control issues, and secrets exposure.
GoldFocuses on cryptographic security and external vulnerability exposure management.
PlatinumRepresents the highest standard, requiring zero high-risk issues and strict dependency security.

How levels work:

  • To reach a higher level, all rules in that level and all lower levels must pass.
  • This creates a clear maturity path from basic hygiene to advanced compliance.

Rules by level​

Below are all rules organized by the level at which they apply.

Bronze level​

SAST scan recency

  • Identifier: sast_recent
  • Goal: Ensure regular static application security testing (SAST).
  • Rule: sast_last_scan_days <= 30
  • Description:
    PCI DSS 6.3.1 requires continuous vulnerability identification.
    This rule ensures a SAST scan has been run within the last 30 days.

No open critical issues

  • Identifier: open_critical_thresh
  • Goal: Prevent critical vulnerabilities from remaining unresolved.
  • Rule: open_critical = 0
  • Description:
    There must be zero open critical vulnerabilities in the codebase.

Silver level​

No injection or access control issues

  • Identifier: class_no_inj_auth

  • Goal: Eliminate high-severity vulnerabilities in input validation and access control.

  • Rule:

    a3_injection = 0
    a1_access_control_flaws = 0
  • Description: Addresses critical categories such as:

    • Injection flaws (e.g., SQL injection, XSS)
    • Broken authentication and authorization logic

No hardcoded secrets

  • Identifier: hardcoded_secrets
  • Goal: Prevent sensitive credentials from being exposed in code.
  • Rule: hardcoded_secrets = 0
  • Description: Detects and blocks hardcoded passwords, API keys, and other secrets.

Gold level​

Secure cryptography

  • Identifier: insecure_crypto
  • Goal: Ensure proper use of secure algorithms and key management practices.
  • Rule: a2_cryptographic_failures = 0
  • Description: Detects use of weak cryptographic algorithms or incorrect implementation of crypto operations.

ASV parity for public-facing assets

  • Identifier: asv_pass_parity
  • Goal: Align with PCI DSS Approved Scanning Vendor (ASV) pass/fail standards.
  • Rule: asv_pass_parity = 0 (or use max_risk_score < 400 if using the max-risk aggregation)
  • Description: Ensures public-facing services do not have vulnerabilities equivalent to CVSS β‰₯ 4.0.

Key Note:

  • CVSS data is not directly available in this system.
  • Instead, we use Snyk Risk Score as a proxy, with a threshold of 400 chosen to approximate the CVSS 4.0 boundary required by PCI DSS for external scans.

Platinum level​

Max risk score validation

  • Identifier: max_risk_score

  • Goal: Apply alternate or stricter risk scoring models for specific teams or services.

  • Rule:

    $team containsAny ["example_team"]
  • Description: Allows team-specific compliance requirements to be enforced at the highest level.

Note: Replace "example_team" with your actual team name or remove this rule if not needed.

No high-risk open source vulnerabilities

  • Identifier: no_high_open_source
  • Goal: Maintain a secure open-source dependency posture.
  • Rule: open_sca_high = 0
  • Description: Requires zero high-severity vulnerabilities in all open-source components.

No high-risk code issues

  • Identifier: no_high_code_issues
  • Goal: Ensure all high-risk static analysis findings are remediated.
  • Rule: open_sast_high = 0
  • Description: There must be no high-severity SAST issues remaining unresolved.

PCI DSS requirements alignment​

This scorecard addresses key PCI DSS requirements for secure development:

PCI DSS RequirementScorecard RuleLevelDescription
6.3.1 - Continuous vulnerability identificationsast_recentBronzeEnsures SAST scans run within 30 days
6.5.1 - Injection flawsa3_injection = 0SilverPrevents SQL injection, XSS, etc.
6.5.2 - Broken authenticationa1_access_control_flaws = 0SilverAddresses authentication/authorization issues
6.5.3 - Cryptographic failuresa2_cryptographic_failures = 0GoldEnsures secure crypto implementation
6.5.4 - Insecure communicationshardcoded_secrets = 0SilverPrevents credential exposure
11.2.2 - External vulnerability scansasv_pass_parityGoldASV compliance for public-facing assets
6.2 - Secure development practicesAll levelsBronze+Comprehensive secure coding standards

Note: This scorecard focuses on code security aspects of PCI DSS. Additional requirements for network security, access controls, and data protection should be implemented separately.

Summary of rule coverage​

LevelPCI Focus AreaKey Rules
BronzeScan frequency & critical issuesSAST recency, No open critical issues
SilverSecure coding & secrets hygieneInjection/Auth flaws, No hardcoded secrets
GoldCryptography & external exposureSecure crypto, ASV parity
PlatinumZero-tolerance for high risksNo high SAST, No high SCA, Max risk scoring

Implementation steps​

1. Ingest scan data​

Ensure outputs from scanning tools are mapped to Port properties:

  • sast_last_scan_days.
  • open_critical.
  • a3_injection.
  • a1_access_control_flaws.
  • hardcoded_secrets.
  • open_sca_high.
  • open_sast_high.
  • max_risk_score_replacing_asv.

2. Deploy via Port or Pulumi​

  • Direct JSON upload: Use the JSON configuration directly in the Port UI.

  • Infrastructure-as-code approach: Convert the JSON to TypeScript and deploy using the Port Pulumi provider.

3. Monitor compliance progress​

  • View real-time compliance status directly within Port.
  • Use levels as milestones to measure progression toward PCI DSS compliance.
  • Generate reports for PCI DSS audits using scorecard data as automated evidence.

Benefits of this scorecard​

  • Automated Compliance Tracking Continuously validates PCI DSS compliance without manual intervention.

  • Actionable Insights Highlights specific areas needing remediation at both code and dependency levels.

  • Maturity Measurement Provides a clear path for teams to progress from basic hygiene to advanced compliance.

  • Audit Readiness Simplifies PCI audits by providing up-to-date evidence of secure development practices.

This visual shows how code scan results flow through the system, get evaluated, and determine compliance level progression.

Key takeaways​

  • Bronze β†’ Platinum represents progressive enforcement of PCI DSS secure coding requirements.
  • Using Snyk Risk Score as a proxy ensures external exposure checks align with ASV expectations even without direct CVSS data. In the future iterations, the intent will be to ingest CVSS Score detail for all package vulnerabilities.
  • This scorecard provides a practical, automated way to track and improve compliance continuously.
  • This scorecard can serve as a starting point.