Skip to content

security-scan

security-scan #1

Workflow file for this run

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>"
}
}
]
}