Skip to content

Conversation

@sydseter
Copy link
Collaborator

In this pull-request:

Additional Utility Scripts

Converting CAPEC Data

The scripts/convertCAPEC.py script converts CAPEC (Common Attack Pattern Enumeration and Classification) JSON data into Markdown format for the Cornucopia website taxonomy.

python ./scripts/convertCAPEC.py --help
usage: convertCAPEC.py [-h] [-o OUTPUT_PATH] [-i INPUT_PATH] [-d]

Convert CAPEC JSON to Cornucopia format

options:
  -h, --help            show this help message and exit
  -o OUTPUT_PATH, --output-path OUTPUT_PATH
                        Path to store converted CAPEC files
  -i INPUT_PATH, --input-path INPUT_PATH
                        Path to read CAPEC JSON files from
  -d, --debug           Output additional information to debug script

Example usage:

# Convert CAPEC data using default paths
python scripts/convertCAPEC.py

# Convert with custom input and output paths
python scripts/convertCAPEC.py -i data/capec-3.9/3000.json -o cornucopia.owasp.org/data/taxonomy/en/CAPEC-3.9

# Enable debug logging
python scripts/convertCAPEC.py -d

Default paths:

  • Input: cornucopia.owasp.org/data/capec-3.9/3000.json
  • Output: cornucopia.owasp.org/data/taxonomy/en/CAPEC-3.9/
    The script creates individual Markdown files for each CAPEC attack pattern with descriptions and links to the official CAPEC database.

Converting CAPEC Mappings to ASVS Format

The scripts/convertCAPECMapToASVSMap.py script processes webapp-mappings YAML files and generates a consolidated CAPEC-to-ASVS (Application Security Verification Standard) mapping file.

python ./scripts/convertCAPECMapToASVSMap.py --help
usage: convertCAPECMapToASVSMap.py [-h] [-i INPUT_PATH] [-o OUTPUT_PATH] [-d]

Convert webapp-mappings YAML to CAPEC-to-ASVS mapping format

options:
  -h, --help            show this help message and exit
  -i INPUT_PATH, --input-path INPUT_PATH
                        Path to input webapp-mappings YAML file
  -o OUTPUT_PATH, --output-path OUTPUT_PATH
                        Path to save converted CAPEC-to-ASVS mapping YAML file
  -d, --debug           Output additional information to debug script

Example usage:

# Convert mappings using default paths
python scripts/convertCAPECMapToASVSMap.py

# Convert with custom input and output paths
python scripts/convertCAPECMapToASVSMap.py -i source/webapp-mappings-3.0.yaml -o source/webapp-capec-3.0.yaml

# Enable debug logging
python scripts/convertCAPECMapToASVSMap.py -d

Default paths:

  • Input: source/webapp-mappings-3.0.yaml
  • Output: source/webapp-capec-3.0.yaml
    The script:
  1. Reads CAPEC mappings from the suits -> cards -> capec_map structure
  2. Merges all OWASP ASVS requirements for each unique CAPEC code
  3. Outputs a unified YAML file mapping CAPEC codes to their associated ASVS requirements
    Output format:
54:
  owasp_asvs: [4.3.2, 13.2.2, 13.4.1, ...]
116:
  owasp_asvs: [13.2.2, 15.2.3, ...]

@qltysh
Copy link

qltysh bot commented Jan 21, 2026

❌ 9 blocking issues (39 total)

Tool Category Rule Count
ruff Lint sys imported but unused 6
mypy Lint Library stubs not installed for "yaml" 2
ruff Lint Module level import not at top of file 1
markdownlint Style Unordered list style 4
radarlint-python Lint Change this argument; Function "parse_description" expects a different type 3
qlty Duplication Found 153 lines of identical code in 2 locations (mass = 834) 2
radarlint-python Lint Define a constant instead of duplicating this literal "output.yaml" 8 times. 13
markdownlint Style Lists should be surrounded by blank lines 1
markdownlint Style Fenced code blocks should be surrounded by blank lines 1
radarlint-python Lint Rename function "createCAPECPages" to match the regular expression ^[a-z_][a-z0-9_]*$. 1
radarlint-python Lint Rename this local variable "capecPath" to match the regular expression ^[_a-z][a-z0-9_]*$. 1
qlty Structure Function with many returns (count = 8): validate_json_data 1
radarlint-python Lint Remove this commented out code. 1
qlty Structure Function with high complexity (count = 26): extract_capec_mappings 1
radarlint-python Lint Refactor this function to reduce its Cognitive Complexity from 23 to the 15 allowed. 1

```
**Example usage:**
```bash
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenced code blocks should be surrounded by blank lines [markdownlint:MD031]

```
**Default paths:**
- Input: `cornucopia.owasp.org/data/capec-3.9/3000.json`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 issues:

1. Lists should be surrounded by blank lines [markdownlint:MD032]


2. Unordered list style [markdownlint:MD004]

**Default paths:**
- Input: `cornucopia.owasp.org/data/capec-3.9/3000.json`
- Output: `cornucopia.owasp.org/data/taxonomy/en/CAPEC-3.9/`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unordered list style [markdownlint:MD004]

```
**Example usage:**
```bash
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenced code blocks should be surrounded by blank lines [markdownlint:MD031]

```
**Default paths:**
- Input: `source/webapp-mappings-3.0.yaml`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 issues:

1. Lists should be surrounded by blank lines [markdownlint:MD032]


2. Unordered list style [markdownlint:MD004]


def test_parse_all_arguments(self):
"""Test parsing with all arguments"""
args = capec_map.parse_arguments(["-i", "input.yaml", "-o", "output.yaml", "-d"])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a constant instead of duplicating this literal "input.yaml" 7 times. [radarlint-python:python:S1192]

class TestParseDescription(unittest.TestCase):
def test_parse_description_with_dict_and_text(self):
"""Test parsing description with __text field in dict"""
description = {"Description": {"p": {"__text": "This is a test description"}}}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a constant instead of duplicating this literal "This is a test description" 4 times. [radarlint-python:python:S1192]

test_data = {"test": "data"}
mock_file = mock_open(read_data=json.dumps(test_data))

with patch("builtins.open", mock_file):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a constant instead of duplicating this literal "builtins.open" 3 times. [radarlint-python:python:S1192]

# Setup
test_output_path = Path("/test/output")
capec.convert_vars.args = argparse.Namespace(
output_path=test_output_path, input_path=Path("dummy.json"), debug=False
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a constant instead of duplicating this literal "dummy.json" 3 times. [radarlint-python:python:S1192]

"owasp_asvs": ["1.6.4", "2.10.4", "4.3.2", "7.1.1", "10.2.3", "14.1.1", "14.2.2", "14.3.3"],
"owasp_appsensor": ["HT1", "HT2", "HT3"],
"capec": [54, 541],
"url": "https://cornucopia.owasp.org/cards/VE2",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a constant instead of duplicating this literal "https://cornucopia\.owasp\.org/cards/VE2" 3 times. [radarlint-python:python:S1192]

**Default paths:**
- Input: `cornucopia.owasp.org/data/capec-3.9/3000.json`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unordered list style [markdownlint:MD004]

**Default paths:**
- Input: `cornucopia.owasp.org/data/capec-3.9/3000.json`
- Output: `cornucopia.owasp.org/data/taxonomy/en/CAPEC-3.9/`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unordered list style [markdownlint:MD004]

**Default paths:**
- Input: `source/webapp-mappings-3.0.yaml`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unordered list style [markdownlint:MD004]

#!/usr/bin/env python3
import unittest
import os
import sys
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sys imported but unused [ruff:F401]

import unittest
import os
import sys
import logging
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logging imported but unused [ruff:F401]

import tempfile
import shutil
from pathlib import Path
import yaml
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Library stubs not installed for "yaml" [mypy:import-untyped]

"""Test saving a valid YAML file"""
data = {"key": "value"}

result = capec_map.save_yaml_file(Path("output.yaml"), data)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a constant instead of duplicating this literal "output.yaml" 8 times. [radarlint-python:python:S1192]

@@ -0,0 +1,352 @@
#!/usr/bin/env python3
import unittest
from unittest.mock import patch, mock_open, MagicMock, call
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 issues:

1. unittest.mock.call imported but unused [ruff:F401]


2. unittest.mock.MagicMock imported but unused [ruff:F401]

Suggested change
from unittest.mock import patch, mock_open, MagicMock, call
from unittest.mock import patch, mock_open

#!/usr/bin/env python3
import unittest
import os
import sys
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sys imported but unused [ruff:F401]

import unittest
import os
import sys
import json
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

json imported but unused [ruff:F401]

first_name = first_pattern["_Name"]

pattern_dir = self.test_output_path / first_id
index_file = pattern_dir / "index.md"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a constant instead of duplicating this literal "index.md" 5 times. [radarlint-python:python:S1192]



# Import argparse for the integration tests
import argparse
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Module level import not at top of file [ruff:E402]

@patch("os.makedirs")
def test_create_folder_new(self, mock_makedirs):
"""Test creating a new folder"""
test_path = Path("/test/folder")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a constant instead of duplicating this literal "/test/folder" 5 times. [radarlint-python:python:S1192]

def test_create_capec_pages_single_pattern(self, mock_create_folder, mock_file):
"""Test creating CAPEC pages for a single attack pattern"""
# Setup
test_output_path = Path("/test/output")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a constant instead of duplicating this literal "/test/output" 3 times. [radarlint-python:python:S1192]

}

with patch.object(Path, "parent") as mock_parent:
mock_parent.resolve.return_value = Path("/mock/directory")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define a constant instead of duplicating this literal "/mock/directory" 3 times. [radarlint-python:python:S1192]

"safecode": [4, 23],
"owasp_cre": {
"owasp_asvs": ["232-325", "774-888", "615-744", "067-050", "838-636", "253-452", "462-245", "743-110"]
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 153 lines of identical code in 2 locations (mass = 834) [qlty:identical-code]

"safecode": [4, 23],
"owasp_cre": {
"owasp_asvs": ["232-325", "774-888", "615-744", "067-050", "838-636", "253-452", "462-245", "743-110"]
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 153 lines of identical code in 2 locations (mass = 834) [qlty:identical-code]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants