mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
ci: Add lint to Github actions (#18172)
This commit is contained in:
122
.github/workflows/security-trivy-scan-callable.yml
vendored
122
.github/workflows/security-trivy-scan-callable.yml
vendored
@@ -14,14 +14,14 @@ on:
|
||||
description: 'Full image reference to scan e.g. ghcr.io/n8n-io/n8n:latest'
|
||||
required: true
|
||||
secrets:
|
||||
SLACK_BOT_TOKEN:
|
||||
QBOT_SLACK_TOKEN:
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
SLACK_BOT_TOKEN: ${{ secrets.QBOT_SLACK_TOKEN }}
|
||||
QBOT_SLACK_TOKEN: ${{ secrets.QBOT_SLACK_TOKEN }}
|
||||
SLACK_CHANNEL_ID: C042WDXPTEZ #mission-security
|
||||
|
||||
jobs:
|
||||
@@ -43,16 +43,18 @@ jobs:
|
||||
- name: Calculate vulnerability counts
|
||||
id: process_results
|
||||
run: |
|
||||
if [ ! -s trivy-results.json ] || [ $(jq '.Results | length' trivy-results.json) -eq 0 ]; then
|
||||
echo "No high-severity vulnerabilities found."
|
||||
echo "vulnerabilities_found=false" >> $GITHUB_OUTPUT
|
||||
if [ ! -s trivy-results.json ] || [ "$(jq '.Results | length' trivy-results.json)" -eq 0 ]; then
|
||||
echo "No vulnerabilities found."
|
||||
echo "vulnerabilities_found=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Calculate counts by severity
|
||||
CRITICAL_COUNT=$(jq '([.Results[]?.Vulnerabilities[]? | select(.Severity == "CRITICAL")] | length)' trivy-results.json)
|
||||
HIGH_COUNT=$(jq '([.Results[]?.Vulnerabilities[]? | select(.Severity == "HIGH")] | length)' trivy-results.json)
|
||||
TOTAL_VULNS=$((CRITICAL_COUNT + HIGH_COUNT))
|
||||
MEDIUM_COUNT=$(jq '([.Results[]?.Vulnerabilities[]? | select(.Severity == "MEDIUM")] | length)' trivy-results.json)
|
||||
LOW_COUNT=$(jq '([.Results[]?.Vulnerabilities[]? | select(.Severity == "LOW")] | length)' trivy-results.json)
|
||||
TOTAL_VULNS=$((CRITICAL_COUNT + HIGH_COUNT + MEDIUM_COUNT + LOW_COUNT))
|
||||
|
||||
# Get unique CVE count
|
||||
UNIQUE_CVES=$(jq -r '[.Results[]?.Vulnerabilities[]?.VulnerabilityID] | unique | length' trivy-results.json)
|
||||
@@ -60,12 +62,16 @@ jobs:
|
||||
# Get affected packages count
|
||||
AFFECTED_PACKAGES=$(jq -r '[.Results[]?.Vulnerabilities[]? | .PkgName] | unique | length' trivy-results.json)
|
||||
|
||||
echo "vulnerabilities_found=$( [ $TOTAL_VULNS -gt 0 ] && echo 'true' || echo 'false' )" >> $GITHUB_OUTPUT
|
||||
echo "total_count=$TOTAL_VULNS" >> $GITHUB_OUTPUT
|
||||
echo "critical_count=$CRITICAL_COUNT" >> $GITHUB_OUTPUT
|
||||
echo "high_count=$HIGH_COUNT" >> $GITHUB_OUTPUT
|
||||
echo "unique_cves=$UNIQUE_CVES" >> $GITHUB_OUTPUT
|
||||
echo "affected_packages=$AFFECTED_PACKAGES" >> $GITHUB_OUTPUT
|
||||
{
|
||||
echo "vulnerabilities_found=$( [ "$TOTAL_VULNS" -gt 0 ] && echo 'true' || echo 'false' )"
|
||||
echo "total_count=$TOTAL_VULNS"
|
||||
echo "critical_count=$CRITICAL_COUNT"
|
||||
echo "high_count=$HIGH_COUNT"
|
||||
echo "medium_count=$MEDIUM_COUNT"
|
||||
echo "low_count=$LOW_COUNT"
|
||||
echo "unique_cves=$UNIQUE_CVES"
|
||||
echo "affected_packages=$AFFECTED_PACKAGES"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Generate GitHub Job Summary
|
||||
if: always()
|
||||
@@ -76,10 +82,12 @@ jobs:
|
||||
echo "**Image:** \`${{ inputs.image_ref }}\`"
|
||||
echo "**Scan Date:** $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|
||||
echo ""
|
||||
} >> $GITHUB_STEP_SUMMARY
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
if [ "${{ steps.process_results.outputs.vulnerabilities_found }}" == "false" ]; then
|
||||
echo "✅ **No critical or high severity vulnerabilities found!**" >> $GITHUB_STEP_SUMMARY
|
||||
{
|
||||
echo "✅ **No vulnerabilities found!**"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
else
|
||||
{
|
||||
echo "## 📊 Summary"
|
||||
@@ -87,43 +95,52 @@ jobs:
|
||||
echo "|--------|-------|"
|
||||
echo "| 🔴 Critical Vulnerabilities | ${{ steps.process_results.outputs.critical_count }} |"
|
||||
echo "| 🟠 High Vulnerabilities | ${{ steps.process_results.outputs.high_count }} |"
|
||||
echo "| 🟡 Medium Vulnerabilities | ${{ steps.process_results.outputs.medium_count }} |"
|
||||
echo "| 🟡 Low Vulnerabilities | ${{ steps.process_results.outputs.low_count }} |"
|
||||
echo "| 📋 Unique CVEs | ${{ steps.process_results.outputs.unique_cves }} |"
|
||||
echo "| 📦 Affected Packages | ${{ steps.process_results.outputs.affected_packages }} |"
|
||||
echo ""
|
||||
echo "## 🚨 Top Vulnerabilities"
|
||||
echo ""
|
||||
} >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Generate detailed vulnerability table
|
||||
jq -r --arg image_ref "${{ inputs.image_ref }}" '
|
||||
# Collect all vulnerabilities
|
||||
[.Results[] | select(.Vulnerabilities != null) | .Vulnerabilities[]] |
|
||||
# Group by CVE ID to avoid duplicates
|
||||
group_by(.VulnerabilityID) |
|
||||
map({
|
||||
cve: .[0].VulnerabilityID,
|
||||
severity: .[0].Severity,
|
||||
cvss: (.[0].CVSS.nvd.V3Score // "N/A"),
|
||||
cvss_sort: (.[0].CVSS.nvd.V3Score // 0),
|
||||
packages: [.[] | "\(.PkgName)@\(.InstalledVersion)"] | unique | join(", "),
|
||||
fixed: (.[0].FixedVersion // "No fix available"),
|
||||
description: (.[0].Description // "No description available") | split("\n")[0] | .[0:150]
|
||||
}) |
|
||||
# Sort by severity (CRITICAL first) and CVSS score
|
||||
sort_by((.severity == "HIGH" | if . then 1 else 0 end), -.cvss_sort) |
|
||||
# Take top 15
|
||||
.[:15] |
|
||||
# Generate markdown table
|
||||
"| CVE | Severity | CVSS | Package(s) | Fix Version | Description |",
|
||||
"|-----|----------|------|------------|-------------|-------------|",
|
||||
(.[] | "| [\(.cve)](https://nvd.nist.gov/vuln/detail/\(.cve)) | \(.severity) | \(.cvss) | `\(.packages)` | `\(.fixed)` | \(.description) |")
|
||||
' trivy-results.json >> $GITHUB_STEP_SUMMARY
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
{
|
||||
# Generate detailed vulnerability table
|
||||
jq -r --arg image_ref "${{ inputs.image_ref }}" '
|
||||
# Collect all vulnerabilities
|
||||
[.Results[] | select(.Vulnerabilities != null) | .Vulnerabilities[]] |
|
||||
# Group by CVE ID to avoid duplicates
|
||||
group_by(.VulnerabilityID) |
|
||||
map({
|
||||
cve: .[0].VulnerabilityID,
|
||||
severity: .[0].Severity,
|
||||
cvss: (.[0].CVSS.nvd.V3Score // "N/A"),
|
||||
cvss_sort: (.[0].CVSS.nvd.V3Score // 0),
|
||||
packages: [.[] | "\(.PkgName)@\(.InstalledVersion)"] | unique | join(", "),
|
||||
fixed: (.[0].FixedVersion // "No fix available"),
|
||||
description: (.[0].Description // "No description available") | split("\n")[0] | .[0:150]
|
||||
}) |
|
||||
# Sort by severity (CRITICAL, HIGH, MEDIUM, LOW) and CVSS score
|
||||
sort_by(
|
||||
if .severity == "CRITICAL" then 0
|
||||
elif .severity == "HIGH" then 1
|
||||
elif .severity == "MEDIUM" then 2
|
||||
elif .severity == "LOW" then 3
|
||||
else 4 end,
|
||||
-.cvss_sort
|
||||
) |
|
||||
# Take top 15
|
||||
.[:15] |
|
||||
# Generate markdown table
|
||||
"| CVE | Severity | CVSS | Package(s) | Fix Version | Description |",
|
||||
"|-----|----------|------|------------|-------------|-------------|",
|
||||
(.[] | "| [\(.cve)](https://nvd.nist.gov/vuln/detail/\(.cve)) | \(.severity) | \(.cvss) | `\(.packages)` | `\(.fixed)` | \(.description) |")
|
||||
' trivy-results.json
|
||||
|
||||
echo ""
|
||||
echo "---"
|
||||
echo "🔍 **View detailed logs above for full analysis**"
|
||||
} >> $GITHUB_STEP_SUMMARY
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
fi
|
||||
|
||||
- name: Generate Slack Blocks JSON
|
||||
@@ -136,6 +153,8 @@ jobs:
|
||||
--arg run_url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
|
||||
--arg critical_count "${{ steps.process_results.outputs.critical_count }}" \
|
||||
--arg high_count "${{ steps.process_results.outputs.high_count }}" \
|
||||
--arg medium_count "${{ steps.process_results.outputs.medium_count }}" \
|
||||
--arg low_count "${{ steps.process_results.outputs.low_count }}" \
|
||||
--arg unique_cves "${{ steps.process_results.outputs.unique_cves }}" \
|
||||
'
|
||||
# Function to create a vulnerability block with emoji indicators
|
||||
@@ -143,7 +162,7 @@ jobs:
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "\(if .Severity == "CRITICAL" then ":red_circle:" else ":large_orange_circle:" end) *<https://nvd.nist.gov/vuln/detail/\(.VulnerabilityID)|\(.VulnerabilityID)>* (CVSS: `\(.CVSS.nvd.V3Score // "N/A")`)\n*Package:* `\(.PkgName)@\(.InstalledVersion)` → `\(.FixedVersion // "No fix available")`"
|
||||
"text": "\(if .Severity == "CRITICAL" then ":red_circle:" elif .Severity == "HIGH" then ":large_orange_circle:" elif .Severity == "MEDIUM" then ":large_yellow_circle:" else ":large_green_circle:" end) *<https://nvd.nist.gov/vuln/detail/\(.VulnerabilityID)|\(.VulnerabilityID)>* (CVSS: `\(.CVSS.nvd.V3Score // "N/A")`)\n*Package:* `\(.PkgName)@\(.InstalledVersion)` → `\(.FixedVersion // "No fix available")`"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -159,7 +178,9 @@ jobs:
|
||||
{ "type": "mrkdwn", "text": "*Repository:*\n<\($repo_url)|\($repo_name)>" },
|
||||
{ "type": "mrkdwn", "text": "*Image:*\n`\($image_ref)`" },
|
||||
{ "type": "mrkdwn", "text": "*Critical:*\n:red_circle: \($critical_count)" },
|
||||
{ "type": "mrkdwn", "text": "*High:*\n:large_orange_circle: \($high_count)" }
|
||||
{ "type": "mrkdwn", "text": "*High:*\n:large_orange_circle: \($high_count)" },
|
||||
{ "type": "mrkdwn", "text": "*Medium:*\n:large_yellow_circle: \($medium_count)" },
|
||||
{ "type": "mrkdwn", "text": "*Low:*\n:large_green_circle: \($low_count)" }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -175,7 +196,14 @@ jobs:
|
||||
[.Results[] | select(.Vulnerabilities != null) | .Vulnerabilities[]] |
|
||||
group_by(.VulnerabilityID) |
|
||||
map(.[0]) |
|
||||
sort_by((.Severity == "HIGH" | if . then 1 else 0 end), -((.CVSS.nvd.V3Score // 0) | tonumber? // 0)) |
|
||||
sort_by(
|
||||
(if .Severity == "CRITICAL" then 0
|
||||
elif .Severity == "HIGH" then 1
|
||||
elif .Severity == "MEDIUM" then 2
|
||||
elif .Severity == "LOW" then 3
|
||||
else 4 end),
|
||||
-((.CVSS.nvd.V3Score // 0) | tonumber? // 0)
|
||||
) |
|
||||
.[:8] |
|
||||
map(. | vuln_block)
|
||||
) +
|
||||
@@ -195,15 +223,15 @@ jobs:
|
||||
]
|
||||
' trivy-results.json)
|
||||
|
||||
echo "slack_blocks=$BLOCKS_JSON" >> $GITHUB_OUTPUT
|
||||
echo "slack_blocks=$BLOCKS_JSON" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Send Slack Notification
|
||||
if: steps.process_results.outputs.vulnerabilities_found == 'true'
|
||||
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
|
||||
with:
|
||||
method: chat.postMessage
|
||||
token: ${{ secrets.SLACK_BOT_TOKEN }}
|
||||
token: ${{ secrets.QBOT_SLACK_TOKEN }}
|
||||
payload: |
|
||||
channel: ${{ env.SLACK_CHANNEL_ID }}
|
||||
text: "🚨 Trivy Scan: ${{ steps.process_results.outputs.critical_count }} Critical, ${{ steps.process_results.outputs.high_count }} High vulnerabilities found in ${{ inputs.image_ref }}"
|
||||
text: "🚨 Trivy Scan: ${{ steps.process_results.outputs.critical_count }} Critical, ${{ steps.process_results.outputs.high_count }} High, ${{ steps.process_results.outputs.medium_count }} Medium, ${{ steps.process_results.outputs.low_count }} Low vulnerabilities found in ${{ inputs.image_ref }}"
|
||||
blocks: ${{ steps.generate_blocks.outputs.slack_blocks }}
|
||||
|
||||
Reference in New Issue
Block a user