security-scan #1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: security-scan | |
on: | |
schedule: | |
- cron: "45 8 * * 1" | |
workflow_dispatch: | |
env: | |
APPLICATION: submit | |
DOCKER_REPO: ${{ secrets.DEPLOY_DOCKER_REPOSITORY }}/submit | |
ZAP_VERSION: 2.15.0 | |
jobs: | |
dynamic-audit: | |
runs-on: ubuntu-latest | |
env: | |
DOCKER_APPLICATION_TAG: latest | |
outputs: | |
alerts_info: ${{ steps.report.outputs.alerts_info }} | |
alerts_low: ${{ steps.report.outputs.alerts_low }} | |
alerts_medium: ${{ steps.report.outputs.alerts_medium }} | |
alerts_high: ${{ steps.report.outputs.alerts_high }} | |
alerts_total: ${{ steps.report.outputs.alerts_total }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Setup dependencies | |
run: | | |
npm ci | |
sudo curl -SL https://github.com/docker/compose/releases/download/v2.10.2/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose | |
sudo chmod +x /usr/local/bin/docker-compose | |
docker pull ${DOCKER_REPO}:${DOCKER_APPLICATION_TAG} | |
- name: Run dynamic security scan | |
run: | | |
npm run scan:zap | |
cat zap-working-dir/zap-report.md >> "$GITHUB_STEP_SUMMARY" | |
- name: Upload ZAP logs | |
uses: actions/upload-artifact@v4 | |
if: always() | |
with: | |
name: zap.log | |
path: zap-working-dir/zap.log | |
- name: Parse ZAP scan report | |
id: report | |
run: | | |
echo "alerts_info=$(jq -rc '[ .site[0].alerts[] | select(.riskcode == "0") | .riskcode ] | length' zap-working-dir/zap-report.json)" >> $GITHUB_OUTPUT | |
echo "alerts_low=$(jq -rc '[ .site[0].alerts[] | select(.riskcode == "1") | .riskcode ] | length' zap-working-dir/zap-report.json)" >> $GITHUB_OUTPUT | |
echo "alerts_medium=$(jq -rc '[ .site[0].alerts[] | select(.riskcode == "2") | .riskcode ] | length' zap-working-dir/zap-report.json)" >> $GITHUB_OUTPUT | |
echo "alerts_high=$(jq -rc '[ .site[0].alerts[] | select(.riskcode == "3") | .riskcode ] | length' zap-working-dir/zap-report.json)" >> $GITHUB_OUTPUT | |
echo "alerts_total=$(jq -rc '[ .site[0].alerts[] ] | length' zap-working-dir/zap-report.json)" >> $GITHUB_OUTPUT | |
static-audit: | |
runs-on: ubuntu-latest | |
outputs: | |
alerts_undefined: ${{ steps.report.outputs.alerts_undefined }} | |
alerts_low: ${{ steps.report.outputs.alerts_low }} | |
alerts_medium: ${{ steps.report.outputs.alerts_medium }} | |
alerts_high: ${{ steps.report.outputs.alerts_high }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Setup dependencies | |
run: | | |
npm ci | |
- name: Run static security scan | |
run: | | |
npm audit -f markdown | tee npm-audit-report.md >> "$GITHUB_STEP_SUMMARY" | |
npm audit --json > npm-audit-report.json || true | |
- name: Upload npm audit report | |
uses: actions/upload-artifact@v4 | |
if: always() | |
with: | |
name: npm-audit-report | |
path: npm-audit-report.json | |
- name: Parse npm audit report | |
id: report | |
run: | | |
# Parse the npm audit report and output the number of alerts based on severity | |
echo "alerts_low=$(jq '[..vulnerabilities[] | select(.severity == "low")] | length' npm-audit-report.json)" >> $GITHUB_OUTPUT | |
echo "alerts_medium=$(jq '[..vulnerabilities[] | select(.severity == "moderate")] | length' npm-audit-report.json)" >> $GITHUB_OUTPUT | |
echo "alerts_high=$(jq '[..vulnerabilities[] | select(.severity == "high")] | length' npm-audit-report.json)" >> $GITHUB_OUTPUT | |
send-report: | |
runs-on: ubuntu-latest | |
needs: | |
- dynamic-audit | |
- static-audit | |
steps: | |
- name: send report notification | |
uses: slackapi/slack-github-action@v1 | |
env: | |
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
with: | |
channel-id: 'planning-data-platform' | |
payload: | | |
{ | |
"text": "Security Scan: LPA Validator Frontend Pipeline(Submit)", | |
"icon_emoji": ":lock:", | |
"username": "SecurityScanner", | |
"blocks": [ | |
{ | |
"type": "header", | |
"text": { | |
"type": "plain_text", | |
"text": "Security Scan: LPA Validator Frontend Pipeline(Submit)" | |
} | |
}, | |
{ | |
"type": "context", | |
"elements": [ | |
{ | |
"type": "mrkdwn", | |
"text": "*Dynamic Audit*" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*TOTAL* ${{ needs.dynamic-audit.outputs.alerts_total }}" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*HIGH* ${{ needs.dynamic-audit.outputs.alerts_high }}" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*MEDIUM* ${{ needs.dynamic-audit.outputs.alerts_medium }}" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*LOW* ${{ needs.dynamic-audit.outputs.alerts_low }}" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*INFO* ${{ needs.dynamic-audit.outputs.alerts_info }}" | |
} | |
] | |
}, | |
{ | |
"type": "context", | |
"elements": [ | |
{ | |
"type": "mrkdwn", | |
"text": "*Static Audit*" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*HIGH* ${{ needs.static-audit.outputs.alerts_high }}" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*MEDIUM* ${{ needs.static-audit.outputs.alerts_medium }}" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*LOW* ${{ needs.static-audit.outputs.alerts_low }}" | |
}, | |
{ | |
"type": "mrkdwn", | |
"text": "*UNDEFINED* ${{ needs.static-audit.outputs.alerts_undefined }}" | |
} | |
] | |
}, | |
{ | |
"type": "divider" | |
}, | |
{ | |
"type": "section", | |
"text": { | |
"type": "mrkdwn", | |
"text": "The report for this scan is available on <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub>" | |
} | |
} | |
] | |
} | |
check-audit-errors: | |
runs-on: ubuntu-latest | |
needs: | |
- dynamic-audit | |
- static-audit | |
if: always() && contains(join(needs.*.result, ','), 'failure') | |
steps: | |
- name: send failure notification | |
uses: slackapi/slack-github-action@v1 | |
env: | |
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
with: | |
channel-id: 'planning-data-platform' | |
payload: | | |
{ | |
"text": "Security Scan: LPA Validator Frontend Pipeline(Submit)", | |
"icon_emoji": ":alert:", | |
"username": "SecurityScanner", | |
"blocks": [ | |
{ | |
"type": "header", | |
"text": { | |
"type": "plain_text", | |
"text": "Security Scan Failed: LPA Validator Frontend Pipeline(Submit)" | |
} | |
}, | |
{ | |
"type": "divider" | |
}, | |
{ | |
"type": "section", | |
"text": { | |
"type": "mrkdwn", | |
"text": "The report for this scan is available on <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|GitHub>" | |
} | |
} | |
] | |
} |