[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7BXGPZXZT7PWCSDSCHSWP6Y":3,"skill-same:01M7BXGPZXZT7PWCSDSCHSWP6Y":45},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":6,"ownerHtmlUrl":29,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":30,"install":31,"resources":44},"01M7BXGPZXZT7PWCSDSCHSWP6Y","vulnerability-csv-reporting",null,"Generate structured CSV security audit reports from vulnerability data with proper filtering and formatting. This skill covers CSV schema design for security reports, using Python csv.DictWriter, severity-based filtering, and field mapping from JSON to tabular format.","linyouxue\u002Fskill-repair-benchmark","linyouxue","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F216151464?v=4","01M7BJEVCXKD74KH6FG9CBVSQB","林宥学","01M7BJEVE02NP217V93BKZFC0J",0,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fevaluation\u002Fresults\u002FOpus47-OriginalSkill-79Tasks-20260920\u002Fruns\u002Fopus47-original-skill\u002Fsoftware-dependency-audit-opus47-original-skill-r001\u002Finputs\u002Fskills\u002Fvulnerability-csv-reporting\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: vulnerability-csv-reporting\ndescription: Generate structured CSV security audit reports from vulnerability data with proper filtering and formatting. This skill covers CSV schema design for security reports, using Python csv.DictWriter, severity-based filtering, and field mapping from JSON to tabular format.\n---\n\n# Vulnerability CSV Report Generation\n\nThis skill provides guidance on generating structured CSV reports from vulnerability scan data—a common format for security audits and compliance reporting.\n\n## Overview\n\nCSV (Comma-Separated Values) is a widely-used format for security reports because it's:\n- **Human-readable**: Can be opened in Excel, Google Sheets\n- **Machine-parseable**: Easy to process programmatically\n- **Universal**: Supported by all data analysis tools\n- **Lightweight**: Smaller than JSON\u002FXML formats\n\n## When to Use CSV Reports\n\n### Ideal Use Cases\n- Compliance audits requiring tabular data\n- Executive summaries for non-technical stakeholders\n- Integration with ticketing systems (Jira, ServiceNow)\n- Automated vulnerability tracking pipelines\n- Data analysis in spreadsheet tools\n\n### Limitations\n- No hierarchical data (flat structure only)\n- Limited support for nested information\n- No standard for binary data\n\n**Alternative formats**: JSON (for APIs), PDF (for formal reports), HTML (for dashboards)\n\n## CSV Schema Design for Security Reports\n\n### Essential Fields\n\nA well-designed vulnerability report CSV should include:\n\n| Field | Type | Description | Example |\n|-------|------|-------------|---------|\n| **Package** | String | Vulnerable package name | `express` |\n| **Version** | String | Installed version | `4.17.1` |\n| **CVE_ID** | String | Vulnerability identifier | `CVE-2022-24999` |\n| **Severity** | Enum | Risk level | `CRITICAL`, `HIGH` |\n| **CVSS_Score** | Float\u002FString | Numeric severity score | `9.8` or `N\u002FA` |\n| **Fixed_Version** | String | Patched version | `4.18.0` or `N\u002FA` |\n| **Title** | String | Brief description | `XSS in Express.js` |\n| **Url** | String | Reference link | `https:\u002F\u002Fnvd.nist.gov\u002F...` |\n\n### Design Principles\n\n1. **Use descriptive column names**: `Package` not `pkg`, `CVE_ID` not `id`\n2. **Handle missing data**: Use `N\u002FA` for unavailable fields, not empty strings\n3. **Consistent data types**: Ensure all rows have same format\n4. **Include metadata**: Consider adding scan date, target, tool version\n\n## Python CSV Generation with DictWriter\n\n### Why DictWriter?\n\nPython's `csv.DictWriter` is ideal for structured reports:\n- **Type-safe**: Column names defined upfront\n- **Readable**: Use dictionary keys instead of indices\n- **Maintainable**: Easy to add\u002Fremove columns\n- **Automatic header generation**: No manual header writing\n\n### Basic Usage\n\n```python\nimport csv\n\n# Define schema\nheaders = [\"Package\", \"Version\", \"CVE_ID\", \"Severity\", \"CVSS_Score\", \n           \"Fixed_Version\", \"Title\", \"Url\"]\n\n# Prepare data\nvulnerabilities = [\n    {\n        \"Package\": \"minimist\",\n        \"Version\": \"1.2.5\",\n        \"CVE_ID\": \"CVE-2021-44906\",\n        \"Severity\": \"CRITICAL\",\n        \"CVSS_Score\": 9.8,\n        \"Fixed_Version\": \"1.2.6\",\n        \"Title\": \"Prototype Pollution\",\n        \"Url\": \"https:\u002F\u002Favd.aquasec.com\u002Fnvd\u002Fcve-2021-44906\"\n    }\n]\n\n# Write CSV\nwith open('security_audit.csv', 'w', newline='', encoding='utf-8') as f:\n    writer = csv.DictWriter(f, fieldnames=headers)\n    writer.writeheader()  # Write column names\n    writer.writerows(vulnerabilities)  # Write all rows\n```\n\n**Important parameters**:\n- `newline=''`: Prevents extra blank lines on Windows\n- `encoding='utf-8'`: Handles special characters in descriptions\n\n## Severity-Based Filtering\n\n### Why Filter by Severity?\n\nSecurity teams prioritize based on risk. Filtering ensures reports focus on critical issues:\n\n| Severity | Action Required | Typical SLA |\n|----------|----------------|-------------|\n| **CRITICAL** | Immediate patch | 24 hours |\n| **HIGH** | Urgent patch | 7 days |\n| **MEDIUM** | Scheduled patch | 30 days |\n| **LOW** | Optional patch | 90 days |\n\n### Implementation\n\n```python\ndef filter_high_severity(vulnerabilities, min_severity=['HIGH', 'CRITICAL']):\n    \"\"\"\n    Filter vulnerabilities by severity level.\n    \n    Args:\n        vulnerabilities: List of vulnerability dictionaries\n        min_severity: List of severity levels to include\n        \n    Returns:\n        Filtered list containing only specified severity levels\n    \"\"\"\n    filtered = []\n    for vuln in vulnerabilities:\n        if vuln.get('Severity') in min_severity:\n            filtered.append(vuln)\n    return filtered\n\n# Usage\nall_vulns = [...]  # From scanner\ncritical_vulns = filter_high_severity(all_vulns, ['CRITICAL', 'HIGH'])\n```\n\n## Field Mapping from JSON to CSV\n\n### Extracting Fields from Scanner Output\n\n```python\nimport json\n\ndef parse_trivy_json_to_csv_records(json_file):\n    \"\"\"\n    Parse Trivy JSON output and extract CSV-ready records.\n    \n    Returns list of dictionaries, one per vulnerability.\n    \"\"\"\n    with open(json_file, 'r', encoding='utf-8') as f:\n        data = json.load(f)\n    \n    records = []\n    \n    if 'Results' in data:\n        for result in data['Results']:\n            target = result.get('Target', 'Unknown')\n            \n            for vuln in result.get('Vulnerabilities', []):\n                # Map JSON fields to CSV fields\n                record = {\n                    \"Package\": vuln.get('PkgName'),\n                    \"Version\": vuln.get('InstalledVersion'),\n                    \"CVE_ID\": vuln.get('VulnerabilityID'),\n                    \"Severity\": vuln.get('Severity', 'UNKNOWN'),\n                    \"CVSS_Score\": extract_cvss_score(vuln),\n                    \"Fixed_Version\": vuln.get('FixedVersion', 'N\u002FA'),\n                    \"Title\": vuln.get('Title', 'No description'),\n                    \"Url\": vuln.get('PrimaryURL', '')\n                }\n                records.append(record)\n    \n    return records\n\ndef extract_cvss_score(vuln):\n    \"\"\"Extract CVSS score (from cvss-score-extraction skill).\"\"\"\n    cvss = vuln.get('CVSS', {})\n    for source in ['nvd', 'ghsa', 'redhat']:\n        if source in cvss:\n            score = cvss[source].get('V3Score')\n            if score is not None:\n                return score\n    return 'N\u002FA'\n```\n\n## Complete Vulnerability CSV Report Generator\n\n```python\nimport json\nimport csv\nimport sys\n\ndef generate_vulnerability_csv_report(\n    json_input, \n    csv_output, \n    severity_filter=['HIGH', 'CRITICAL']\n):\n    \"\"\"\n    Generate filtered CSV security report from Trivy JSON output.\n    \n    Args:\n        json_input: Path to Trivy JSON report\n        csv_output: Path for output CSV file\n        severity_filter: List of severity levels to include\n    \"\"\"\n    # Read JSON\n    try:\n        with open(json_input, 'r', encoding='utf-8') as f:\n            data = json.load(f)\n    except FileNotFoundError:\n        print(f\"[!] Error: Could not find {json_input}\")\n        sys.exit(1)\n    \n    # Extract and filter vulnerabilities\n    vulnerabilities = []\n    \n    if 'Results' in data:\n        for result in data['Results']:\n            for vuln in result.get('Vulnerabilities', []):\n                severity = vuln.get('Severity', 'UNKNOWN')\n                \n                # Apply severity filter\n                if severity in severity_filter:\n                    vulnerabilities.append({\n                        \"Package\": vuln.get('PkgName'),\n                        \"Version\": vuln.get('InstalledVersion'),\n                        \"CVE_ID\": vuln.get('VulnerabilityID'),\n                        \"Severity\": severity,\n                        \"CVSS_Score\": get_cvss_score(vuln),\n                        \"Fixed_Version\": vuln.get('FixedVersion', 'N\u002FA'),\n                        \"Title\": vuln.get('Title', 'No description'),\n                        \"Url\": vuln.get('PrimaryURL', '')\n                    })\n    \n    # Write CSV\n    if vulnerabilities:\n        headers = [\"Package\", \"Version\", \"CVE_ID\", \"Severity\", \n                   \"CVSS_Score\", \"Fixed_Version\", \"Title\", \"Url\"]\n        \n        with open(csv_output, 'w', newline='', encoding='utf-8') as f:\n            writer = csv.DictWriter(f, fieldnames=headers)\n            writer.writeheader()\n            writer.writerows(vulnerabilities)\n        \n        print(f\"\\n[SUCCESS] Found {len(vulnerabilities)} \"\n              f\"{'\u002F'.join(severity_filter)} vulnerabilities\")\n        print(f\"[SUCCESS] Report saved to: {csv_output}\")\n    else:\n        print(f\"\\n[SUCCESS] No {'\u002F'.join(severity_filter)} vulnerabilities found\")\n\ndef get_cvss_score(vuln_data):\n    \"\"\"Extract CVSS score with source priority.\"\"\"\n    cvss = vuln_data.get('CVSS', {})\n    for source in ['nvd', 'ghsa', 'redhat']:\n        if source in cvss:\n            score = cvss[source].get('V3Score')\n            if score is not None:\n                return score\n    return 'N\u002FA'\n\n# Usage\nif __name__ == \"__main__\":\n    generate_vulnerability_csv_report(\n        json_input='trivy_report.json',\n        csv_output='security_audit.csv',\n        severity_filter=['CRITICAL', 'HIGH']\n    )\n```\n\n## Advanced Patterns\n\n### Pattern 1: Adding Metadata Row\n\n```python\nimport csv\nfrom datetime import datetime\n\n# Add metadata as first row\nmetadata = {\n    \"Package\": f\"Scan Date: {datetime.now().isoformat()}\",\n    \"Version\": \"Tool: Trivy v0.40.0\",\n    \"CVE_ID\": \"Target: package-lock.json\",\n    \"Severity\": \"\", \"CVSS_Score\": \"\", \"Fixed_Version\": \"\", \n    \"Title\": \"\", \"Url\": \"\"\n}\n\nwith open('report.csv', 'w', newline='') as f:\n    writer = csv.DictWriter(f, fieldnames=headers)\n    writer.writeheader()\n    writer.writerow(metadata)  # Metadata row\n    writer.writerow({})  # Blank separator\n    writer.writerows(vulnerabilities)  # Actual data\n```\n\n### Pattern 2: Multi-Target Reports\n\n```python\ndef generate_multi_target_report(json_input, csv_output):\n    \"\"\"Include target\u002Ffile name in each row.\"\"\"\n    with open(json_input, 'r') as f:\n        data = json.load(f)\n    \n    vulnerabilities = []\n    \n    for result in data.get('Results', []):\n        target = result.get('Target', 'Unknown')\n        \n        for vuln in result.get('Vulnerabilities', []):\n            record = {\n                \"Target\": target,  # Add target column\n                \"Package\": vuln.get('PkgName'),\n                # ... other fields\n            }\n            vulnerabilities.append(record)\n    \n    headers = [\"Target\", \"Package\", \"Version\", ...]  # Target first\n    # Write CSV as before\n```\n\n### Pattern 3: Summary Statistics\n\n```python\ndef print_report_summary(vulnerabilities):\n    \"\"\"Print summary before writing CSV.\"\"\"\n    from collections import Counter\n    \n    severity_counts = Counter(v['Severity'] for v in vulnerabilities)\n    \n    print(\"\\nVulnerability Summary:\")\n    print(f\"  CRITICAL: {severity_counts.get('CRITICAL', 0)}\")\n    print(f\"  HIGH:     {severity_counts.get('HIGH', 0)}\")\n    print(f\"  Total:    {len(vulnerabilities)}\")\n```\n\n## Error Handling\n\n### Handling Missing or Malformed Data\n\n```python\ndef safe_get_field(vuln, field, default='N\u002FA'):\n    \"\"\"Safely extract field with default fallback.\"\"\"\n    value = vuln.get(field, default)\n    # Ensure value is not None\n    return value if value is not None else default\n\n# Usage in field mapping\nrecord = {\n    \"Package\": safe_get_field(vuln, 'PkgName', 'Unknown'),\n    \"Fixed_Version\": safe_get_field(vuln, 'FixedVersion', 'N\u002FA'),\n    # ...\n}\n```\n\n## Best Practices\n\n1. **Always write headers**: Makes CSV self-documenting\n2. **Use UTF-8 encoding**: Handles international characters\n3. **Set newline=''**: Prevents blank lines on Windows\n4. **Validate data**: Check for None\u002Fnull values before writing\n5. **Add timestamp**: Include scan date for tracking\n6. **Document schema**: Maintain a data dictionary\n7. **Test with edge cases**: Empty results, missing fields\n\n## Dependencies\n\n### Python Modules\n- `csv` (standard library)\n- `json` (standard library)\n\n### Input Format\n- Requires structured vulnerability data (typically JSON from scanners)\n\n## References\n\n- [Python CSV Documentation](https:\u002F\u002Fdocs.python.org\u002F3\u002Flibrary\u002Fcsv.html)\n- [RFC 4180 - CSV Format Specification](https:\u002F\u002Ftools.ietf.org\u002Fhtml\u002Frfc4180)\n- [NIST Vulnerability Database](https:\u002F\u002Fnvd.nist.gov\u002F)\n","# Vulnerability CSV Report Generation\n\nThis skill provides guidance on generating structured CSV reports from vulnerability scan data—a common format for security audits and compliance reporting.\n\n## Overview\n\nCSV (Comma-Separated Values) is a widely-used format for security reports because it's:\n- **Human-readable**: Can be opened in Excel, Google Sheets\n- **Machine-parseable**: Easy to process programmatically\n- **Universal**: Supported by all data analysis tools\n- **Lightweight**: Smaller than JSON\u002FXML formats\n\n## When to Use CSV Reports\n\n### Ideal Use Cases\n- Compliance audits requiring tabular data\n- Executive summaries for non-technical stakeholders\n- Integration with ticketing systems (Jira, ServiceNow)\n- Automated vulnerability tracking pipelines\n- Data analysis in spreadsheet tools\n\n### Limitations\n- No hierarchical data (flat structure only)\n- Limited support for nested information\n- No standard for binary data\n\n**Alternative formats**: JSON (for APIs), PDF (for formal reports), HTML (for dashboards)\n\n## CSV Schema Design for Security Reports\n\n### Essential Fields\n\nA well-designed vulnerability report CSV should include:\n\n| Field | Type | Description | Example |\n|-------|------|-------------|---------|\n| **Package** | String | Vulnerable package name | `express` |\n| **Version** | String | Installed version | `4.17.1` |\n| **CVE_ID** | String | Vulnerability identifier | `CVE-2022-24999` |\n| **Severity** | Enum | Risk level | `CRITICAL`, `HIGH` |\n| **CVSS_Score** | Float\u002FString | Numeric severity score | `9.8` or `N\u002FA` |\n| **Fixed_Version** | String | Patched version | `4.18.0` or `N\u002FA` |\n| **Title** | String | Brief description | `XSS in Express.js` |\n| **Url** | String | Reference link | `https:\u002F\u002Fnvd.nist.gov\u002F...` |\n\n### Design Principles\n\n1. **Use descriptive column names**: `Package` not `pkg`, `CVE_ID` not `id`\n2. **Handle missing data**: Use `N\u002FA` for unavailable fields, not empty strings\n3. **Consistent data types**: Ensure all rows have same format\n4. **Include metadata**: Consider adding scan date, target, tool version\n\n## Python CSV Generation with DictWriter\n\n### Why DictWriter?\n\nPython's `csv.DictWriter` is ideal for structured reports:\n- **Type-safe**: Column names defined upfront\n- **Readable**: Use dictionary keys instead of indices\n- **Maintainable**: Easy to add\u002Fremove columns\n- **Automatic header generation**: No manual header writing\n\n### Basic Usage\n\n```python\nimport csv\n\n# Define schema\nheaders = [\"Package\", \"Version\", \"CVE_ID\", \"Severity\", \"CVSS_Score\", \n           \"Fixed_Version\", \"Title\", \"Url\"]\n\n# Prepare data\nvulnerabilities = [\n    {\n        \"Package\": \"minimist\",\n        \"Version\": \"1.2.5\",\n        \"CVE_ID\": \"CVE-2021-44906\",\n        \"Severity\": \"CRITICAL\",\n        \"CVSS_Score\": 9.8,\n        \"Fixed_Version\": \"1.2.6\",\n        \"Title\": \"Prototype Pollution\",\n        \"Url\": \"https:\u002F\u002Favd.aquasec.com\u002Fnvd\u002Fcve-2021-44906\"\n    }\n]\n\n# Write CSV\nwith open('security_audit.csv', 'w', newline='', encoding='utf-8') as f:\n    writer = csv.DictWriter(f, fieldnames=headers)\n    writer.writeheader()  # Write column names\n    writer.writerows(vulnerabilities)  # Write all rows\n```\n\n**Important parameters**:\n- `newline=''`: Prevents extra blank lines on Windows\n- `encoding='utf-8'`: Handles special characters in descriptions\n\n## Severity-Based Filtering\n\n### Why Filter by Severity?\n\nSecurity teams prioritize based on risk. Filtering ensures reports focus on critical issues:\n\n| Severity | Action Required | Typical SLA |\n|----------|----------------|-------------|\n| **CRITICAL** | Immediate patch | 24 hours |\n| **HIGH** | Urgent patch | 7 days |\n| **MEDIUM** | Scheduled patch | 30 days |\n| **LOW** | Optional patch | 90 days |\n\n### Implementation\n\n```python\ndef filter_high_severity(vulnerabilities, min_severity=['HIGH', 'CRITICAL']):\n    \"\"\"\n    Filter vulnerabilities by severity level.\n    \n    Args:\n        vulnerabilities: List of vulnerability dictionaries\n        min_severity: List of severity levels to include\n        \n    Returns:\n        Filtered list containing only specified severity levels\n    \"\"\"\n    filtered = []\n    for vuln in vulnerabilities:\n        if vuln.get('Severity') in min_severity:\n            filtered.append(vuln)\n    return filtered\n\n# Usage\nall_vulns = [...]  # From scanner\ncritical_vulns = filter_high_severity(all_vulns, ['CRITICAL', 'HIGH'])\n```\n\n## Field Mapping from JSON to CSV\n\n### Extracting Fields from Scanner Output\n\n```python\nimport json\n\ndef parse_trivy_json_to_csv_records(json_file):\n    \"\"\"\n    Parse Trivy JSON output and extract CSV-ready records.\n    \n    Returns list of dictionaries, one per vulnerability.\n    \"\"\"\n    with open(json_file, 'r', encoding='utf-8') as f:\n        data = json.load(f)\n    \n    records = []\n    \n    if 'Results' in data:\n        for result in data['Results']:\n            target = result.get('Target', 'Unknown')\n            \n            for vuln in result.get('Vulnerabilities', []):\n                # Map JSON fields to CSV fields\n                record = {\n                    \"Package\": vuln.get('PkgName'),\n                    \"Version\": vuln.get('InstalledVersion'),\n                    \"CVE_ID\": vuln.get('VulnerabilityID'),\n                    \"Severity\": vuln.get('Severity', 'UNKNOWN'),\n                    \"CVSS_Score\": extract_cvss_score(vuln),\n                    \"Fixed_Version\": vuln.get('FixedVersion', 'N\u002FA'),\n                    \"Title\": vuln.get('Title', 'No description'),\n                    \"Url\": vuln.get('PrimaryURL', '')\n                }\n                records.append(record)\n    \n    return records\n\ndef extract_cvss_score(vuln):\n    \"\"\"Extract CVSS score (from cvss-score-extraction skill).\"\"\"\n    cvss = vuln.get('CVSS', {})\n    for source in ['nvd', 'ghsa', 'redhat']:\n        if source in cvss:\n            score = cvss[source].get('V3Score')\n            if score is not None:\n                return score\n    return 'N\u002FA'\n```\n\n## Complete Vulnerability CSV Report Generator\n\n```python\nimport json\nimport csv\nimport sys\n\ndef generate_vulnerability_csv_report(\n    json_input, \n    csv_output, \n    severity_filter=['HIGH', 'CRITICAL']\n):\n    \"\"\"\n    Generate filtered CSV security report from Trivy JSON output.\n    \n    Args:\n        json_input: Path to Trivy JSON report\n        csv_output: Path for output CSV file\n        severity_filter: List of severity levels to include\n    \"\"\"\n    # Read JSON\n    try:\n        with open(json_input, 'r', encoding='utf-8') as f:\n            data = json.load(f)\n    except FileNotFoundError:\n        print(f\"[!] Error: Could not find {json_input}\")\n        sys.exit(1)\n    \n    # Extract and filter vulnerabilities\n    vulnerabilities = []\n    \n    if 'Results' in data:\n        for result in data['Results']:\n            for vuln in result.get('Vulnerabilities', []):\n                severity = vuln.get('Severity', 'UNKNOWN')\n                \n                # Apply severity filter\n                if severity in severity_filter:\n                    vulnerabilities.append({\n                        \"Package\": vuln.get('PkgName'),\n                        \"Version\": vuln.get('InstalledVersion'),\n                        \"CVE_ID\": vuln.get('VulnerabilityID'),\n                        \"Severity\": severity,\n                        \"CVSS_Score\": get_cvss_score(vuln),\n                        \"Fixed_Version\": vuln.get('FixedVersion', 'N\u002FA'),\n                        \"Title\": vuln.get('Title', 'No description'),\n                        \"Url\": vuln.get('PrimaryURL', '')\n                    })\n    \n    # Write CSV\n    if vulnerabilities:\n        headers = [\"Package\", \"Version\", \"CVE_ID\", \"Severity\", \n                   \"CVSS_Score\", \"Fixed_Version\", \"Title\", \"Url\"]\n        \n        with open(csv_output, 'w', newline='', encoding='utf-8') as f:\n            writer = csv.DictWriter(f, fieldnames=headers)\n            writer.writeheader()\n            writer.writerows(vulnerabilities)\n        \n        print(f\"\\n[SUCCESS] Found {len(vulnerabilities)} \"\n              f\"{'\u002F'.join(severity_filter)} vulnerabilities\")\n        print(f\"[SUCCESS] Report saved to: {csv_output}\")\n    else:\n        print(f\"\\n[SUCCESS] No {'\u002F'.join(severity_filter)} vulnerabilities found\")\n\ndef get_cvss_score(vuln_data):\n    \"\"\"Extract CVSS score with source priority.\"\"\"\n    cvss = vuln_data.get('CVSS', {})\n    for source in ['nvd', 'ghsa', 'redhat']:\n        if source in cvss:\n            score = cvss[source].get('V3Score')\n            if score is not None:\n                return score\n    return 'N\u002FA'\n\n# Usage\nif __name__ == \"__main__\":\n    generate_vulnerability_csv_report(\n        json_input='trivy_report.json',\n        csv_output='security_audit.csv',\n        severity_filter=['CRITICAL', 'HIGH']\n    )\n```\n\n## Advanced Patterns\n\n### Pattern 1: Adding Metadata Row\n\n```python\nimport csv\nfrom datetime import datetime\n\n# Add metadata as first row\nmetadata = {\n    \"Package\": f\"Scan Date: {datetime.now().isoformat()}\",\n    \"Version\": \"Tool: Trivy v0.40.0\",\n    \"CVE_ID\": \"Target: package-lock.json\",\n    \"Severity\": \"\", \"CVSS_Score\": \"\", \"Fixed_Version\": \"\", \n    \"Title\": \"\", \"Url\": \"\"\n}\n\nwith open('report.csv', 'w', newline='') as f:\n    writer = csv.DictWriter(f, fieldnames=headers)\n    writer.writeheader()\n    writer.writerow(metadata)  # Metadata row\n    writer.writerow({})  # Blank separator\n    writer.writerows(vulnerabilities)  # Actual data\n```\n\n### Pattern 2: Multi-Target Reports\n\n```python\ndef generate_multi_target_report(json_input, csv_output):\n    \"\"\"Include target\u002Ffile name in each row.\"\"\"\n    with open(json_input, 'r') as f:\n        data = json.load(f)\n    \n    vulnerabilities = []\n    \n    for result in data.get('Results', []):\n        target = result.get('Target', 'Unknown')\n        \n        for vuln in result.get('Vulnerabilities', []):\n            record = {\n                \"Target\": target,  # Add target column\n                \"Package\": vuln.get('PkgName'),\n                # ... other fields\n            }\n            vulnerabilities.append(record)\n    \n    headers = [\"Target\", \"Package\", \"Version\", ...]  # Target first\n    # Write CSV as before\n```\n\n### Pattern 3: Summary Statistics\n\n```python\ndef print_report_summary(vulnerabilities):\n    \"\"\"Print summary before writing CSV.\"\"\"\n    from collections import Counter\n    \n    severity_counts = Counter(v['Severity'] for v in vulnerabilities)\n    \n    print(\"\\nVulnerability Summary:\")\n    print(f\"  CRITICAL: {severity_counts.get('CRITICAL', 0)}\")\n    print(f\"  HIGH:     {severity_counts.get('HIGH', 0)}\")\n    print(f\"  Total:    {len(vulnerabilities)}\")\n```\n\n## Error Handling\n\n### Handling Missing or Malformed Data\n\n```python\ndef safe_get_field(vuln, field, default='N\u002FA'):\n    \"\"\"Safely extract field with default fallback.\"\"\"\n    value = vuln.get(field, default)\n    # Ensure value is not None\n    return value if value is not None else default\n\n# Usage in field mapping\nrecord = {\n    \"Package\": safe_get_field(vuln, 'PkgName', 'Unknown'),\n    \"Fixed_Version\": safe_get_field(vuln, 'FixedVersion', 'N\u002FA'),\n    # ...\n}\n```\n\n## Best Practices\n\n1. **Always write headers**: Makes CSV self-documenting\n2. **Use UTF-8 encoding**: Handles international characters\n3. **Set newline=''**: Prevents blank lines on Windows\n4. **Validate data**: Check for None\u002Fnull values before writing\n5. **Add timestamp**: Include scan date for tracking\n6. **Document schema**: Maintain a data dictionary\n7. **Test with edge cases**: Empty results, missing fields\n\n## Dependencies\n\n### Python Modules\n- `csv` (standard library)\n- `json` (standard library)\n\n### Input Format\n- Requires structured vulnerability data (typically JSON from scanners)\n\n## References\n\n- [Python CSV Documentation](https:\u002F\u002Fdocs.python.org\u002F3\u002Flibrary\u002Fcsv.html)\n- [RFC 4180 - CSV Format Specification](https:\u002F\u002Ftools.ietf.org\u002Fhtml\u002Frfc4180)\n- [NIST Vulnerability Database](https:\u002F\u002Fnvd.nist.gov\u002F)\n",{"name":5,"description":7},"main","cdcb6d230f3b15c3c33f8a2bdd16439f43602cbe","evaluation\u002Fresults\u002FOpus47-OriginalSkill-79Tasks-20260920\u002Fruns\u002Fopus47-original-skill\u002Fsoftware-dependency-audit-opus47-original-skill-r001\u002Finputs\u002Fskills\u002Fvulnerability-csv-reporting",1,"https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark","https:\u002F\u002Fgithub.com\u002Flinyouxue","2026-11-14 20:28:35",{"source":8,"skillName":5,"commands":32,"prompt":42,"zipAvailable":43},[33,36,39],{"tool":34,"command":35},"npx","npx skills add linyouxue\u002Fskill-repair-benchmark --skill vulnerability-csv-reporting",{"tool":37,"command":38},"bunx","bunx skills add linyouxue\u002Fskill-repair-benchmark --skill vulnerability-csv-reporting",{"tool":40,"command":41},"pnpm","pnpm dlx skills add linyouxue\u002Fskill-repair-benchmark --skill vulnerability-csv-reporting","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fevaluation\u002Fresults\u002FOpus47-OriginalSkill-79Tasks-20260920\u002Fruns\u002Fopus47-original-skill\u002Fsoftware-dependency-audit-opus47-original-skill-r001\u002Finputs\u002Fskills\u002Fvulnerability-csv-reporting\u002FSKILL.md",true,[],[46,53,60,67,72,77],{"skillNo":47,"name":48,"nameZh":6,"description":49,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":50,"categories":51,"keywords":52,"publishedAt":19},"01M7E1HGVRY73NBJ022CJG13X6","video-frame-extraction","Extract frames from video files and save them as images using OpenCV","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_03\u002Finputs\u002Fskills\u002Fvideo-frame-extraction\u002FSKILL.md",[],[],{"skillNo":54,"name":55,"nameZh":6,"description":56,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":57,"categories":58,"keywords":59,"publishedAt":19},"01M7E1HAG5R7CJ9C8NYJS771MB","openai-vision","Analyze images and multi-frame sequences using OpenAI GPT vision models","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_03\u002Finputs\u002Fskills\u002Fopenai-vision\u002FSKILL.md",[],[],{"skillNo":61,"name":62,"nameZh":6,"description":63,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":66,"publishedAt":19},"01M7E1H7DADKB6QBWKC2KQ63SZ","image-ocr","Extract text content from images using Tesseract OCR via Python, including structured field extraction from receipts and forms","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_03\u002Finputs\u002Fskills\u002Fimage-ocr\u002FSKILL.md",[],[],{"skillNo":68,"name":48,"nameZh":6,"description":49,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":69,"categories":70,"keywords":71,"publishedAt":19},"01M7E1H0WBNT43TENGQY7AVZHD","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_02\u002Finputs\u002Fskills\u002Fvideo-frame-extraction\u002FSKILL.md",[],[],{"skillNo":73,"name":55,"nameZh":6,"description":56,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":74,"categories":75,"keywords":76,"publishedAt":19},"01M7E1GTC7D4N4Q2EF03875J9E","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_02\u002Finputs\u002Fskills\u002Fopenai-vision\u002FSKILL.md",[],[],{"skillNo":78,"name":62,"nameZh":6,"description":63,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":81,"publishedAt":19},"01M7E1GQ92CWFMGH53KSSE4WER","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_02\u002Finputs\u002Fskills\u002Fimage-ocr\u002FSKILL.md",[],[]]