Skip to content

Commit 8a182e2

Browse files
committed
implement NPM
Signed-off-by: Jefferson <jefferson.rios.caro@gmail.com> implement NPM
1 parent ce7aa30 commit 8a182e2

7 files changed

Lines changed: 736 additions & 26 deletions

File tree

.github/ISSUE_TEMPLATE.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
---
22
title: "{{ env.VULN_ID }} ({{ env.VULN_DEP_NAME }}) found on {{ env.NODEJS_STREAM }}"
3-
asignees:
4-
labels: "{{ env.NODEJS_STREAM }}"
3+
labels: {{ env.ISSUE_LABELS }}
4+
assignees:
55
---
66

77
A new vulnerability for {{ env.VULN_DEP_NAME }} {{ env.VULN_DEP_VERSION }} was found:
88
Vulnerability ID: {{ env.VULN_ID }}
99
Vulnerability URL: {{ env.VULN_URL }}
10+
{% if env.VULN_SOURCE == 'npm' and env.VULN_MAIN_DEP_NAME %}
11+
Main Dependency: {{ env.VULN_MAIN_DEP_NAME }}
12+
Main Dependency Path: {{ env.VULN_MAIN_DEP_PATH }}
13+
{% endif %}
1014
Failed run: {{ env.ACTION_URL }}

.github/workflows/check-vulns.yml

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,28 @@ jobs:
3030
uses: actions/setup-python@v5
3131
with:
3232
python-version: '3.11'
33+
- name: Setup Node.js
34+
uses: actions/setup-node@v4
35+
with:
36+
node-version: '18'
37+
- name: Verify Node.js and npm installation
38+
run: |
39+
echo "Node.js version:"
40+
node --version
41+
echo "npm version:"
42+
npm --version
43+
echo "Python version:"
44+
python3 --version
3345
- name: Checkout current repository
3446
uses: actions/checkout@v4
47+
- name: Debug directory structure
48+
run: |
49+
echo "Current directory:"
50+
pwd
51+
echo "Directory contents:"
52+
ls -la
53+
echo "dep_checker directory exists:"
54+
ls -la dep_checker/ || echo "dep_checker directory not found"
3555
- name: Installing pre-reqs
3656
working-directory: ./dep_checker
3757
run: pip install -r requirements.txt
@@ -46,16 +66,21 @@ jobs:
4666
run: |
4767
(
4868
set -o pipefail
49-
python main.py --json-output --gh-token ${{ secrets.GITHUB_TOKEN }} --nvd-key=${{ secrets.NVD_API_KEY }} ../nsolid ${{ inputs.nsolidStream }} 2>&1 | tee result.log
69+
python3 main.py --json-output --include-npm --npm-timeout 600 --gh-token ${{ secrets.GITHUB_TOKEN }} --nvd-key=${{ secrets.NVD_API_KEY }} ../nsolid ${{ inputs.nsolidStream }} 2>&1 | tee result.log
5070
)
5171
cat result.log
5272
- name: build matrix
5373
id: set_matrix
5474
if: ${{ failure() }}
5575
working-directory: ./dep_checker
5676
run: |
57-
matrix=$(grep -o '{.*}' result.log | jq -c .)
58-
echo "matrix=$matrix"
77+
# Extract vulnerabilities JSON from the log
78+
vulnerabilities_json=$(grep -o '{.*}' result.log | tail -1)
79+
echo "Raw vulnerabilities JSON: $vulnerabilities_json"
80+
81+
# Use the matrix formatter to build the complete matrix with labels
82+
matrix=$(python3 ../.github/workflows/format_matrix.py "$vulnerabilities_json" "${{ inputs.nsolidStream }}")
83+
echo "Formatted matrix: $matrix"
5984
echo "matrix=$matrix" >> $GITHUB_OUTPUT
6085
6186
create-issues:
@@ -67,15 +92,28 @@ jobs:
6792
max-parallel: 1
6893
steps:
6994
- uses: actions/checkout@v4
70-
- uses: dblock/create-a-github-issue@v3
71-
with:
72-
update_existing: false
73-
search_existing: open
95+
- name: Debug matrix data
96+
run: |
97+
echo "Matrix vulnerability data:"
98+
echo "ID: ${{ matrix.vulnerabilities.id }}"
99+
echo "Dependency: ${{ matrix.vulnerabilities.dependency }}"
100+
echo "Source: ${{ matrix.vulnerabilities.source }}"
101+
echo "Labels: ${{ join(matrix.vulnerabilities.labels, ', ') }}"
102+
echo "ISSUE_LABELS: ${{ join(matrix.vulnerabilities.labels, ',') }}"
103+
104+
- name: Create or update GitHub issue
74105
env:
75106
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
107+
GITHUB_REPOSITORY: ${{ github.repository }}
76108
VULN_ID: ${{ matrix.vulnerabilities.id }}
77109
VULN_URL: ${{ matrix.vulnerabilities.url }}
78110
VULN_DEP_NAME: ${{ matrix.vulnerabilities.dependency }}
79111
VULN_DEP_VERSION: ${{ matrix.vulnerabilities.version }}
112+
VULN_SOURCE: ${{ matrix.vulnerabilities.source }}
113+
VULN_MAIN_DEP_NAME: ${{ matrix.vulnerabilities.main_dep_name }}
114+
VULN_MAIN_DEP_PATH: ${{ matrix.vulnerabilities.main_dep_path }}
80115
NODEJS_STREAM: ${{ inputs.nsolidStream }}
81116
ACTION_URL: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
117+
LABELS: ${{ join(matrix.vulnerabilities.labels, ',') }}
118+
run: |
119+
.github/workflows/create_issue.sh

.github/workflows/create_issue.sh

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#!/bin/bash
2+
3+
# GitHub Issue Creation Script
4+
# Creates or updates GitHub issues for vulnerabilities with automatic label management
5+
6+
set -e
7+
8+
# Validate required environment variables
9+
required_vars=("VULN_ID" "VULN_URL" "VULN_DEP_NAME" "VULN_DEP_VERSION" "VULN_SOURCE" "NODEJS_STREAM" "ACTION_URL" "LABELS" "GITHUB_TOKEN")
10+
11+
for var in "${required_vars[@]}"; do
12+
if [ -z "${!var}" ]; then
13+
echo "Error: Required environment variable $var is not set"
14+
exit 1
15+
fi
16+
done
17+
18+
# Set variables from environment
19+
VULN_ID="${VULN_ID}"
20+
VULN_URL="${VULN_URL}"
21+
VULN_DEP_NAME="${VULN_DEP_NAME}"
22+
VULN_DEP_VERSION="${VULN_DEP_VERSION}"
23+
VULN_SOURCE="${VULN_SOURCE}"
24+
VULN_MAIN_DEP_NAME="${VULN_MAIN_DEP_NAME:-}"
25+
VULN_MAIN_DEP_PATH="${VULN_MAIN_DEP_PATH:-}"
26+
NODEJS_STREAM="${NODEJS_STREAM}"
27+
ACTION_URL="${ACTION_URL}"
28+
LABELS="${LABELS}"
29+
30+
# Create issue title
31+
ISSUE_TITLE="${VULN_ID} (${VULN_DEP_NAME}) found on ${NODEJS_STREAM}"
32+
33+
# Create issue body
34+
ISSUE_BODY="A new vulnerability for ${VULN_DEP_NAME} ${VULN_DEP_VERSION} was found:
35+
Vulnerability ID: ${VULN_ID}
36+
Vulnerability URL: ${VULN_URL}"
37+
38+
# Add npm-specific info if applicable
39+
if [ "${VULN_SOURCE}" = "npm" ] && [ -n "${VULN_MAIN_DEP_NAME}" ]; then
40+
ISSUE_BODY="${ISSUE_BODY}
41+
Main Dependency: ${VULN_MAIN_DEP_NAME}
42+
Main Dependency Path: ${VULN_MAIN_DEP_PATH}"
43+
fi
44+
45+
ISSUE_BODY="${ISSUE_BODY}
46+
Failed run: ${ACTION_URL}"
47+
48+
echo "Processing vulnerability: ${VULN_ID}"
49+
echo "Issue title: ${ISSUE_TITLE}"
50+
echo "Labels: ${LABELS}"
51+
52+
# Check if issue already exists
53+
EXISTING_ISSUE=$(gh issue list --search "in:title ${ISSUE_TITLE}" --state open --json number,title --jq '.[] | select(.title == "'"${ISSUE_TITLE}"'") | .number')
54+
55+
if [ -n "${EXISTING_ISSUE}" ]; then
56+
echo "Updating existing issue #${EXISTING_ISSUE}: ${ISSUE_TITLE}"
57+
gh issue edit "${EXISTING_ISSUE}" --body "${ISSUE_BODY}"
58+
echo "Updated issue: https://github.com/${GITHUB_REPOSITORY}/issues/${EXISTING_ISSUE}"
59+
else
60+
echo "Creating new issue: ${ISSUE_TITLE}"
61+
# Create issue first without labels to avoid label not found errors
62+
ISSUE_URL=$(gh issue create --title "${ISSUE_TITLE}" --body "${ISSUE_BODY}")
63+
ISSUE_NUMBER=$(echo "${ISSUE_URL}" | sed 's/.*\/issues\///')
64+
echo "Created issue: ${ISSUE_URL}"
65+
66+
# Add labels one by one, creating them if they don't exist
67+
IFS=',' read -ra LABEL_ARRAY <<< "${LABELS}"
68+
for label in "${LABEL_ARRAY[@]}"; do
69+
# Trim whitespace
70+
label=$(echo "${label}" | xargs)
71+
echo "Adding label: ${label}"
72+
73+
# Try to add the label, if it fails, create it first then add it
74+
if ! gh issue edit "${ISSUE_NUMBER}" --add-label "${label}" 2>/dev/null; then
75+
echo "Label '${label}' doesn't exist, creating it..."
76+
77+
# Set label color based on label type
78+
case "${label}" in
79+
*CRITICAL*)
80+
LABEL_COLOR="d73a49" # Red
81+
LABEL_DESC="Critical severity vulnerability"
82+
;;
83+
*HIGH*)
84+
LABEL_COLOR="fd7e14" # Orange
85+
LABEL_DESC="High severity vulnerability"
86+
;;
87+
*MODERATE*|*MEDIUM*)
88+
LABEL_COLOR="ffc107" # Yellow
89+
LABEL_DESC="Moderate severity vulnerability"
90+
;;
91+
*LOW*)
92+
LABEL_COLOR="28a745" # Green
93+
LABEL_DESC="Low severity vulnerability"
94+
;;
95+
*NPM*)
96+
LABEL_COLOR="cb3837" # NPM red
97+
LABEL_DESC="NPM package vulnerability"
98+
;;
99+
*v[0-9]*\.x*)
100+
LABEL_COLOR="0366d6" # Blue
101+
LABEL_DESC="Version-specific label"
102+
;;
103+
*nsolid*)
104+
LABEL_COLOR="6f42c1" # Purple
105+
LABEL_DESC="N|Solid related"
106+
;;
107+
*)
108+
LABEL_COLOR="0366d6" # Default blue
109+
LABEL_DESC="Auto-created vulnerability label"
110+
;;
111+
esac
112+
113+
# Create the label with appropriate color and description
114+
if gh label create "${label}" --color "${LABEL_COLOR}" --description "${LABEL_DESC}" 2>/dev/null; then
115+
echo "Created label '${label}' with color #${LABEL_COLOR}"
116+
else
117+
echo "Warning: Failed to create label '${label}' (may already exist)"
118+
fi
119+
120+
# Try to add the label again
121+
if gh issue edit "${ISSUE_NUMBER}" --add-label "${label}" 2>/dev/null; then
122+
echo "Successfully added label: ${label}"
123+
else
124+
echo "Warning: Failed to add label: ${label}"
125+
fi
126+
else
127+
echo "Successfully added existing label: ${label}"
128+
fi
129+
done
130+
131+
echo "Issue creation completed with all labels applied"
132+
fi
133+
134+
echo "Issue processing completed successfully"

.github/workflows/format_matrix.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Matrix formatter for vulnerability data
4+
5+
This script takes the JSON output from the vulnerability checker and formats it
6+
into a GitHub Actions matrix with proper labels and all required data for issue creation.
7+
"""
8+
9+
import json
10+
import sys
11+
import re
12+
from typing import List, Dict, Any
13+
14+
15+
def generate_labels_for_vulnerability(vuln: Dict[str, Any], nsolid_stream: str) -> List[str]:
16+
"""Generate GitHub issue labels for a vulnerability based on its properties and nsolid stream"""
17+
labels = []
18+
19+
# Add nsolid stream as base label
20+
labels.append(nsolid_stream)
21+
22+
# Add NPM label if it's an npm vulnerability
23+
if vuln.get("source") == "npm":
24+
labels.append("NPM")
25+
26+
# Add severity label if available
27+
severity = vuln.get("severity")
28+
if severity and severity != "null":
29+
severity_upper = severity.upper()
30+
labels.append(severity_upper)
31+
32+
# Extract runtime version from stream (e.g., node-v20.x-nsolid-v5.x -> v20.x)
33+
runtime_match = re.search(r'node-(v[0-9]+\.x)', nsolid_stream)
34+
if runtime_match:
35+
runtime_version = runtime_match.group(1)
36+
labels.append(runtime_version)
37+
38+
# Extract nsolid version from stream (e.g., node-v20.x-nsolid-v5.x -> v5.x)
39+
nsolid_match = re.search(r'nsolid-(v[0-9]+\.x)', nsolid_stream)
40+
if nsolid_match:
41+
nsolid_version = nsolid_match.group(1)
42+
labels.append(f"nsolid-{nsolid_version}")
43+
44+
return labels
45+
46+
47+
def build_vulnerability_matrix(vulnerabilities_data: Dict[str, Any], nsolid_stream: str) -> Dict[str, Any]:
48+
"""Build the complete matrix with vulnerabilities and their labels for GitHub Actions"""
49+
vulnerabilities = vulnerabilities_data.get("vulnerabilities", [])
50+
51+
if not vulnerabilities:
52+
return {"include": []}
53+
54+
matrix_include = []
55+
56+
for vuln in vulnerabilities:
57+
labels = generate_labels_for_vulnerability(vuln, nsolid_stream)
58+
59+
matrix_entry = {
60+
"id": vuln["id"],
61+
"url": vuln["url"],
62+
"dependency": vuln["dependency"],
63+
"version": vuln["version"],
64+
"source": vuln["source"],
65+
"labels": labels
66+
}
67+
68+
# Add npm-specific fields if they exist
69+
if "severity" in vuln and vuln["severity"] is not None:
70+
matrix_entry["severity"] = vuln["severity"]
71+
if "via" in vuln and vuln["via"]:
72+
matrix_entry["via"] = vuln["via"]
73+
if "main_dep_name" in vuln and vuln["main_dep_name"] is not None:
74+
matrix_entry["main_dep_name"] = vuln["main_dep_name"]
75+
if "main_dep_path" in vuln and vuln["main_dep_path"] is not None:
76+
matrix_entry["main_dep_path"] = vuln["main_dep_path"]
77+
if "fix_available" in vuln and vuln["fix_available"] is not None:
78+
matrix_entry["fix_available"] = vuln["fix_available"]
79+
80+
matrix_include.append({"vulnerabilities": matrix_entry})
81+
82+
return {"include": matrix_include}
83+
84+
85+
def main():
86+
"""Main function to process vulnerability data and output matrix"""
87+
if len(sys.argv) != 3:
88+
print("Usage: format_matrix.py <vulnerabilities_json> <nsolid_stream>", file=sys.stderr)
89+
sys.exit(1)
90+
91+
vulnerabilities_json = sys.argv[1]
92+
nsolid_stream = sys.argv[2]
93+
94+
try:
95+
# Parse the vulnerabilities JSON
96+
vulnerabilities_data = json.loads(vulnerabilities_json)
97+
98+
# Build the matrix
99+
matrix = build_vulnerability_matrix(vulnerabilities_data, nsolid_stream)
100+
101+
# Output the matrix
102+
print(json.dumps(matrix))
103+
104+
except json.JSONDecodeError as e:
105+
print(f"Error parsing JSON: {e}", file=sys.stderr)
106+
sys.exit(1)
107+
except Exception as e:
108+
print(f"Error processing vulnerabilities: {e}", file=sys.stderr)
109+
sys.exit(1)
110+
111+
112+
if __name__ == "__main__":
113+
main()

0 commit comments

Comments
 (0)