Examples
Ownership scorecardโ
The following example demonstrates an ownership scorecard.
It has one filter defined:
- Only evaluate entities that are related to production (indicated by checking that the
is_production
property is set totrue
).
It has two rules:
- Check that a defined on-call exists and that the number of
open_incidents
is lower than 5; - Check if a team exists.
[
{
"title": "Ownership",
"identifier": "ownership",
"filter": {
"combinator": "and",
"conditions": [
{
"property": "is_production",
"operator": "=",
"value": true
}
]
},
"rules": [
{
"title": "Has on call?",
"identifier": "has_on_call",
"level": "Gold",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "isNotEmpty",
"property": "on_call"
},
{
"operator": "<",
"property": "open_incidents",
"value": 5
}
]
}
},
{
"title": "Has a team?",
"identifier": "has_team",
"level": "Silver",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "isNotEmpty",
"property": "$team"
}
]
}
}
]
}
]
Ensure relation existenceโ
Say we have a service
blueprint that has a relation to another blueprint named domain
.
We can define a scorecard that checks that all of our services have a related domain. Services with empty domain
relations will fail this check:
{
"title": "Domain definition",
"identifier": "domain_definition",
"rules": [
{
"identifier": "hasDomain",
"title": "Has domain",
"level": "Bronze",
"query": {
"combinator": "and",
"conditions": [
{
"operator": "isNotEmpty",
"relation": "domain"
}
]
}
}
]
}
DORA metrics based on number of deploymentsโ
To assess the deployment frequency of a service
, simply checking the deployment
relation is not enough โ we need to know the exact number of deployments. To achieve this, we can:
- Add an aggregation property to the
service
blueprint that counts the number of relateddeployment
entities. - Add a scorecard with a rule based on the new aggregation property:
{
"title": "DORA Metrics",
"identifier": "dora_metrics",
"rules": [
{
"identifier": "deployFreqBronze",
"title": "Deployment frequency > 2",
"level": "Bronze",
"query": {
"combinator": "and",
"conditions": [
{
"operator": ">",
"property": "deployment_frequency",
"value": 3
}
]
}
},
{
"identifier": "deployFreqSilver",
"title": "Deployment frequency > 4",
"level": "Silver",
"query": {
"combinator": "and",
"conditions": [
{
"operator": ">",
"property": "deployment_frequency",
"value": 4
}
]
}
}
]
}
OWASP top 10 scorecardโ

This section explains how to build an OWASP Top 10 security scorecard in Port using vulnerability data from Snyk.
The scorecard resides on the Repository
blueprint and evaluates data sourced from the Snyk Target
and Snyk Vulnerability
blueprints to measure each repositoryโs security posture against the latest OWASP Top 10 categories.
Snyk Vulnerability
โ Represents individual vulnerabilities of various types.Snyk Target
โ Evaluated against 10 rules, each corresponding to an OWASP Top 10 category.Repository
โ The primary entity where the scorecard resides.
Prerequisites
- This example assumes you have a Port account and that you have finished the onboarding process.
- Install Port's GitHub app.
- Install Port's Snyk integration.
Set up data model
Snyk Vulnerability
To accurately benchmark against the OWASP Top 10 for code, most static analysis tools support generating Common Weakness Enumeration
(CWE) IDs. We will store the CWE
value in a property called category
.
If the property is not yet included in your Snyk Vulnerability
blueprint, follow these steps:
Update the Snyk Vulnerability
blueprint:
-
Navigate to the Data model page of your portal.
-
Click on the
Snyk Vulnerability
blueprint. -
Click on the
...
button in the top right corner, then click on the{...} Edit JSON
button. -
Update the existing JSON by incorporating the following data in it, then click
Save
.Snyk Vulnerability blueprint (click to expand)
{
"properties": {
"category": {
"type": "string",
"title": "Category"
}
}
Update the mapping configuration:
-
Head over to your Data sources page.
-
Under
Exporters
, click on your Snyk integration. -
In the Mapping tab, edit the YAML in the bottom-left panel and add the following entry under the
vulnerability
kind:Mapping configuration (click to expand)
resources:
- kind: vulnerability
port:
entity:
mappings:
cwe: .attributes.classes[0].id -
Click on the
Save & Resync
button to save the changes and resync the integration.
Snyk Target
With the addition of the CWE
property to the Snyk Vulnerability
blueprint, you can now classify vulnerabilities by CWE and align them with the OWASP Top 10 categories.
Update the Snyk Target
blueprint to include 10 dedicated properties, one for each OWASP Top 10 code category, so issues can be grouped and reported by category.
To update the Snyk Target
blueprint:
-
Navigate to the Data model page of your portal.
-
Click on the
Snyk Target
blueprint. -
Click on the
...
button in the top right corner, then click on the{...} Edit JSON
button. -
Update the aggregation properties to include the snippet JSON snippet below:
Snyk Target blueprint (click to expand)
{
"aggregationProperties": {
"a1_access_control_flaws": {
"title": "A1 Access Control Flaws",
"icon": "Shield",
"type": "number",
"description": "Check if repo is free of OWASP Top 10 A1 - Access Control Flaws",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "code"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "category",
"operator": "in",
"value": [
"CWE-22",
"CWE-23",
"CWE-35",
"CWE-59",
"CWE-200",
"CWE-201",
"CWE-219",
"CWE-264",
"CWE-275",
"CWE-276",
"CWE-284",
"CWE-352",
"CWE-359"
]
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
}
},
"a2_cryptographic_failures": {
"title": "A2 Cryptographic Failures",
"icon": "Shield",
"type": "number",
"description": "OWASP Top 10 A2 Cryptographic Failures",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "code"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "category",
"operator": "in",
"value": [
"CWE-259",
"CWE-261",
"CWE-296",
"CWE-310",
"CWE-319",
"CWE-321",
"CWE-322",
"CWE-323",
"CWE-324",
"CWE-325",
"CWE-326",
"CWE-327",
"CWE-328",
"CWE-329",
"CWE-330",
"CWE-331",
"CWE-335",
"CWE-336",
"CWE-337",
"CWE-338",
"CWE-340",
"CWE-347",
"CWE-523",
"CWE-720",
"CWE-757",
"CWE-759",
"CWE-760",
"CWE-780",
"CWE-818",
"CWE-916"
]
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
}
},
"a3_injection": {
"title": "A3 Injection",
"icon": "Shield",
"type": "number",
"description": "Check if repo is free of OWASP Top 10 A3 - Injection flaws",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "code"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "category",
"operator": "in",
"value": [
"CWE-20",
"CWE-74",
"CWE-75",
"CWE-77",
"CWE-78",
"CWE-79",
"CWE-80",
"CWE-83",
"CWE-87",
"CWE-88",
"CWE-89",
"CWE-90",
"CWE-91",
"CWE-93",
"CWE-94",
"CWE-95",
"CWE-96",
"CWE-97",
"CWE-98",
"CWE-99",
"CWE-100",
"CWE-113",
"CWE-116",
"CWE-138",
"CWE-184",
"CWE-470",
"CWE-471",
"CWE-564",
"CWE-610",
"CWE-643",
"CWE-644",
"CWE-652",
"CWE-917"
]
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
}
},
"a4_insecure_design": {
"title": "A4 Insecure Design",
"icon": "Shield",
"type": "number",
"description": "OWASP top 10 A4 - Insecure design security weakness",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "code"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "category",
"operator": "in",
"value": [
"CWE-73",
"CWE-183",
"CWE-209",
"CWE-213",
"CWE-235",
"CWE-256",
"CWE-257",
"CWE-266",
"CWE-269",
"CWE-280",
"CWE-311",
"CWE-312",
"CWE-313",
"CWE-316",
"CWE-419",
"CWE-430",
"CWE-434",
"CWE-444",
"CWE-451",
"CWE-472",
"CWE-501",
"CWE-522",
"CWE-525",
"CWE-539",
"CWE-579",
"CWE-598",
"CWE-602",
"CWE-642",
"CWE-646",
"CWE-650",
"CWE-653",
"CWE-656",
"CWE-657",
"CWE-799",
"CWE-807",
"CWE-840",
"CWE-841",
"CWE-927",
"CWE-1021",
"CWE-1173"
]
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
}
},
"a5_security_misconfigurations": {
"title": "A5 Security Misconfigurations",
"icon": "Shield",
"type": "number",
"description": "OWASP Top 10 - A5 Security misconfigurations",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "code"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "category",
"operator": "in",
"value": [
"CWE-2",
"CWE-11",
"CWE-13",
"CWE-15",
"CWE-16",
"CWE-260",
"CWE-315",
"CWE-520",
"CWE-526",
"CWE-537",
"CWE-541",
"CWE-547",
"CWE-611",
"CWE-614",
"CWE-756",
"CWE-776",
"CWE-942",
"CWE-1004",
"CWE-1032",
"CWE-1174"
]
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
}
},
"a6_vulnerable_components": {
"title": "A6 Vulnerable components",
"icon": "Shield",
"type": "number",
"description": "OWASP A6 - Vulnerable and outdated components in use.",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "code"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "category",
"operator": "in",
"value": [
"CWE-937",
"CWE-1035",
"CWE-1104"
]
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
}
},
"a7_authentication_failures": {
"title": "A7 Authentication Failures",
"icon": "Shield",
"type": "number",
"description": "OWASP Top 10 - Identification & Authentication Failures",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "code"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "category",
"operator": "in",
"value": [
"CWE-255",
"CWE-259",
"CWE-287",
"CWE-288",
"CWE-290",
"CWE-294",
"CWE-295",
"CWE-297",
"CWE-300",
"CWE-302",
"CWE-304",
"CWE-306",
"CWE-307",
"CWE-346",
"CWE-384",
"CWE-521",
"CWE-613",
"CWE-620",
"CWE-640",
"CWE-798",
"CWE-940",
"CWE-1216"
]
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
}
},
"a8_integrity_failures": {
"title": "A8 Integrity Failures",
"icon": "Shield",
"type": "number",
"description": "OWASP Top 10 - A8 - Software & Integrity failures",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "code"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "category",
"operator": "in",
"value": [
"CWE-345",
"CWE-353",
"CWE-426",
"CWE-494",
"CWE-502",
"CWE-565",
"CWE-784",
"CWE-829",
"CWE-830",
"CWE-915"
]
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
}
},
"a9_logging": {
"title": "A9 Logging",
"icon": "Shield",
"type": "number",
"description": "OWASP Top 10 - A9 Security logging & Monitoring",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "code"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "category",
"operator": "in",
"value": [
"CWE-117",
"CWE-223",
"CWE-532",
"CWE-778"
]
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
}
},
"a10_ssrf": {
"title": "A10 SSRF",
"icon": "Shield",
"type": "number",
"description": "OWASP Top 10 - A10 Server side request forgery",
"target": "snykVulnerability",
"query": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "=",
"value": "code"
},
{
"property": "status",
"operator": "=",
"value": "open"
},
{
"property": "category",
"operator": "in",
"value": [
"CWE-918"
]
}
]
},
"calculationSpec": {
"func": "count",
"calculationBy": "entities"
}
}
}
} -
Click on
Save
to update the blueprint.
Repository
The Snyk Target
blueprint should have a defined relation with the GitHub Repository
blueprint.
If your current model does not include a relation from the Repository
blueprint to the Snyk Target
blueprint, add it.
The next step is to add the OWASP identifiers as mirrored properties to the GitHub Repository
blueprint, and update the mapping configuration so that each GitHub Repository
is automatically linked to its corresponding Snyk Target
.
This link is what allows the mirrored OWASP properties to pull their values from the related Snyk data.
Update the GitHub Repository
blueprint:
-
Navigate to the Data model page of your portal.
-
Click on the
GitHub Repository
blueprint. -
Click on the
...
button in the top right corner, then click on the{...} Edit JSON
button. -
Update the mirrorProperties to include the snippet below:
GitHub Repository Blueprint (click to expand)
{
"mirrorProperties": {
"a1_access_control_flaws": {
"title": "A1 Access Control Flaws",
"path": "snyk_target.a1_access_control_flaws"
},
"a2_cryptographic_failures": {
"title": "A2 Cryptographic Failures",
"path": "snyk_target.a2_cryptographic_failures"
},
"a3_injection": {
"title": "A3 Injection",
"path": "snyk_target.a3_injection"
},
"a4_insecure_design": {
"title": "A4 Insecure Design",
"path": "snyk_target.a4_insecure_design"
},
"a5_security_misconfigurations": {
"title": "A5 Security Misconfigurations",
"path": "snyk_target.a5_security_misconfigurations"
},
"a6_vulnerable_components": {
"title": "A6 Vulnerable Components",
"path": "snyk_target.a6_vulnerable_components"
},
"a7_authentication_failures": {
"title": "A7 Authentication Failures",
"path": "snyk_target.a7_authentication_failures"
},
"a8_integrity_failures": {
"title": "A8 Integrity Failures",
"path": "snyk_target.a8_integrity_failures"
},
"a9_logging": {
"title": "A9 Logging",
"path": "snyk_target.a9_logging"
},
"a10_ssrf": {
"title": "A10 SSRF",
"path": "snyk_target.a10_ssrf"
}
}
} -
Click on
Save
to update the blueprint.
Update the mapping configuration:
-
Head over to your Data sources page.
-
Under
Exporters
, click on your desired GitHub organization. -
In the Mapping tab, edit the YAML in the bottom-left panel and add the following entry under the
repository
kind:Mapping configuration (click to expand)
- kind: repository
port:
entity:
mappings:
relations:
snyk_target:
combinator: '"and"'
rules:
- property: '"$title"'
operator: '"="'
value: .full_name -
Click on the
Save & Resync
button to save the changes and resync the integration.
Set up the scorecard
The final step is to create a scorecard that reflects the security maturity of a Respository
against the OWASP Top 10 categories.

To create an OWASP Top 10 Scorecard:
-
Go to your Data model page.
-
Search for the GitHub Repository blueprint and select it.
-
Click on the
Scorecards
tab. -
Click on
+ New Scorecard
to create a new scorecard. -
Add this JSON configuration and click
Save
.OWASP Top 10 Scorecard (click to expand)
{
"identifier": "OWASPScoreCard",
"title": "OWASP Top 10",
"levels": [
{
"color": "paleBlue",
"title": "Basic"
},
{
"color": "bronze",
"title": "Bronze"
},
{
"color": "silver",
"title": "Silver"
},
{
"color": "gold",
"title": "Gold"
}
],
"rules": [
{
"identifier": "has_owasp_a6",
"title": "A06 Vulnerable Components",
"level": "Gold",
"query": {
"combinator": "and",
"conditions": [
{
"value": 0,
"operator": "=",
"property": "a6_vulnerable_components"
}
]
}
},
{
"identifier": "has_owasp_a1",
"title": "A01 Broken Access Control",
"level": "Bronze",
"query": {
"combinator": "and",
"conditions": [
{
"value": 0,
"operator": "=",
"property": "a1_access_control_flaws"
}
]
}
},
{
"identifier": "has_owasp_a4",
"title": "A04 Insecure Design",
"level": "Gold",
"query": {
"combinator": "and",
"conditions": [
{
"value": 0,
"operator": "=",
"property": "a4_insecure_design"
}
]
}
},
{
"identifier": "has_owasp_a8",
"title": "A08 Integrity Failures",
"level": "Silver",
"query": {
"combinator": "and",
"conditions": [
{
"value": 0,
"operator": "=",
"property": "a8_integrity_failures"
}
]
}
},
{
"identifier": "has_owasp_a7",
"title": "A07 Authentication Failures",
"level": "Bronze",
"query": {
"combinator": "and",
"conditions": [
{
"value": 0,
"operator": "=",
"property": "a7_authentication_failures"
}
]
}
},
{
"identifier": "has_owasp_a3",
"title": "A03 Injection",
"level": "Bronze",
"query": {
"combinator": "and",
"conditions": [
{
"value": 0,
"operator": "=",
"property": "a3_injection"
}
]
}
},
{
"identifier": "has_owasp_a5",
"title": "A05 Security Misconfigurations",
"level": "Gold",
"query": {
"combinator": "and",
"conditions": [
{
"value": 0,
"operator": "=",
"property": "a5_security_misconfigurations"
}
]
}
},
{
"identifier": "has_owasp_a2",
"title": "A02 Cryptographic Failures",
"level": "Silver",
"query": {
"combinator": "and",
"conditions": [
{
"value": 0,
"operator": "=",
"property": "a2_cryptographic_failures"
}
]
}
},
{
"identifier": "has_owasp_a9",
"title": "A09 Logging ",
"level": "Silver",
"query": {
"combinator": "and",
"conditions": [
{
"value": 0,
"operator": "=",
"property": "a9_logging"
}
]
}
},
{
"identifier": "has_owasp_a10",
"title": "A10 SSRF",
"level": "Bronze",
"query": {
"combinator": "and",
"conditions": [
{
"value": 0,
"operator": "=",
"property": "a10_ssrf"
}
]
}
}
]
}
Troubleshooting
Some common issues you may encounter during the implementation:
- Invalid token: The
SNYK_TOKEN
does not have privileges or otherwise has been revoked. Ensure that the token is valid and has required permissions so that issues and targets across the Snyk Group can be queried for. - OWASP Top 10 2021:
CWE
field is key to accurately measuring and benchmarking against OWASP Top 10. The current measurement rules are based on the latest OWASP Top 10 i.e. OWASP Top 10 2021 as of this write-up. Discrepancy may arise if following this example without consideration for reviewing against latest OWASP Top 10 issues and the associated CWEs. - Missing property data: This can happen when
CWE
property has been defined on theSnyk Vulnerability
blueprint, however a sync has not yet occurred.
Next steps
Consider the following as next steps:
- Quality standards:
- Eliminate chaos and promote
minimum viable security product
with tiering. - Establish a customized standard that best meets your organization's culture by classifying the OWASP Top 10.
- Eliminate chaos and promote
- Self-service actions:
- Automatically assign Owners and create a self-service action that triggers an alert to repository owners when tier standards are unmet.
- Portal Initiative:
- Self-service action: Create a self-service action to improve OWASP Tiers for specific repositories.
- Create an initiative within Port to reduce a specific security weakness or promote a specific tier as a standard operating procedure.