Skip to content

APP-951-New architecture for ditto #72

APP-951-New architecture for ditto

APP-951-New architecture for ditto #72

Workflow file for this run

name: OWASP Dependency Check
on:
pull_request:
branches: [main]
permissions:
contents: read
pull-requests: write
issues: write
security-events: write
jobs:
dependency-check:
runs-on: ubuntu-latest
strategy:
matrix:
# Workspace package names
workspace:
- "@dittolive/ditto-chat-core"
- "@dittolive/ditto-chat-ui"
include:
- workspace: "@dittolive/ditto-chat-core"
path: "sdks/js/ditto-chat-core"
- workspace: "@dittolive/ditto-chat-ui"
path: "sdks/js/ditto-chat-ui"
fail-fast: false
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "24"
cache: "npm"
cache-dependency-path: "package-lock.json"
- name: Install dependencies
run: npm ci
- name: Create suppression file
run: |
cat > suppression.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
<!-- Suppress non-Node.js files: binaries, CocoaPods, Gradle, Xcode -->
<suppress>
<filePath regex="true">.*((node_modules.*\.(dll|exe|so|dylib|msi))|\.podspec|/Podfile(\.lock)?|/Pods/.*|\.gradle|/gradlew(\.bat)?|\.(xcodeproj|xcworkspace)/.*)$</filePath>
<cpe regex="true">.*</cpe>
</suppress>
</suppressions>
EOF
- name: Run OWASP Dependency-Check
uses: dependency-check/Dependency-Check_Action@main
id: depcheck
with:
project: "${{ matrix.workspace }}"
path: "${{ matrix.path }}"
format: "ALL"
args: >
-s "${{ matrix.path }}/package.json"
-s "package-lock.json"
--enableExperimental
--suppression suppression.xml
--failOnCVSS 7
- name: Upload Dependency-Check Report
uses: actions/upload-artifact@v4
if: always()
with:
name: dependency-check-report-${{ hashFiles(format('{0}/package.json', matrix.path)) }}
path: reports/
retention-days: 15
- name: Generate Vulnerability Summary
if: always()
id: summary
run: |
WORKSPACE="${{ matrix.workspace }}"
REPORT_FILE="reports/dependency-check-report.json"
if [ -f "$REPORT_FILE" ]; then
# Extract vulnerability counts (handle both uppercase and lowercase severity values)
CRITICAL=$(jq '[.dependencies[].vulnerabilities[]? | select(.severity == "CRITICAL" or .severity == "critical")] | length' "$REPORT_FILE")
HIGH=$(jq '[.dependencies[].vulnerabilities[]? | select(.severity == "HIGH" or .severity == "high")] | length' "$REPORT_FILE")
MEDIUM=$(jq '[.dependencies[].vulnerabilities[]? | select(.severity == "MEDIUM" or .severity == "moderate")] | length' "$REPORT_FILE")
LOW=$(jq '[.dependencies[].vulnerabilities[]? | select(.severity == "LOW" or .severity == "low")] | length' "$REPORT_FILE")
TOTAL=$(jq '[.dependencies[].vulnerabilities[]?] | length' "$REPORT_FILE")
echo "critical=$CRITICAL" >> $GITHUB_OUTPUT
echo "high=$HIGH" >> $GITHUB_OUTPUT
echo "medium=$MEDIUM" >> $GITHUB_OUTPUT
echo "low=$LOW" >> $GITHUB_OUTPUT
echo "total=$TOTAL" >> $GITHUB_OUTPUT
# Extract detailed vulnerabilities
echo "VULNERABILITIES<<EOF" >> $GITHUB_OUTPUT
jq -r '.dependencies[] | select(.vulnerabilities) | .fileName as $file | .vulnerabilities[] | "- **\(.name)** (\(.severity)) in `\($file)`\n - Description: \(.description // "N/A" | gsub("[`\\n\\r\"$]"; " "))\n - CVSS: \(.cvssv3.baseScore // .cvssv2.score // "N/A")\n"' "$REPORT_FILE" | head -n 50 >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
else
echo "critical=0" >> $GITHUB_OUTPUT
echo "high=0" >> $GITHUB_OUTPUT
echo "medium=0" >> $GITHUB_OUTPUT
echo "low=0" >> $GITHUB_OUTPUT
echo "total=0" >> $GITHUB_OUTPUT
echo "VULNERABILITIES=No vulnerabilities found" >> $GITHUB_OUTPUT
fi
- name: Comment PR with Detailed Results
if: always()
uses: actions/github-script@v7
env:
VULN_DATA: ${{ steps.summary.outputs.VULNERABILITIES }}
with:
script: |
const workspace = '${{ matrix.workspace }}';
const critical = '${{ steps.summary.outputs.critical }}';
const high = '${{ steps.summary.outputs.high }}';
const medium = '${{ steps.summary.outputs.medium }}';
const low = '${{ steps.summary.outputs.low }}';
const total = '${{ steps.summary.outputs.total }}';
const vulnerabilities = process.env.VULN_DATA;
// Determine status emoji and message
let statusEmoji = '✅';
let statusMessage = 'No vulnerabilities found';
if (parseInt(critical) > 0 || parseInt(high) > 0) {
statusEmoji = '🚨';
statusMessage = 'Critical or High severity vulnerabilities detected!';
} else if (parseInt(medium) > 0) {
statusEmoji = '⚠️';
statusMessage = 'Medium severity vulnerabilities detected';
} else if (parseInt(low) > 0) {
statusEmoji = 'ℹ️';
statusMessage = 'Low severity vulnerabilities detected';
}
const body = `## ${statusEmoji} OWASP Dependency Check - \`${workspace}\`
### ${statusMessage}
| Severity | Count |
|----------|------:|
| 🔴 Critical | **${critical}** |
| 🟠 High | **${high}** |
| 🟡 Medium | **${medium}** |
| 🔵 Low | **${low}** |
| **Total** | **${total}** |
${parseInt(total) > 0 ? `
### 📋 Vulnerability Details
${vulnerabilities}
${parseInt(total) > 50 ? '_Note: Showing first 50 vulnerabilities. Check the full report for complete details._' : ''}
` : ''}
---
📊 **[View Full HTML Report](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})**
<details>
<summary>ℹ️ How to fix vulnerabilities</summary>
1. Update vulnerable dependencies to patched versions
2. Run \`npm audit fix\` or \`npm audit fix --force\` in the root directory
3. Check for alternative packages if updates aren't available
4. Review and update your \`package.json\` and \`package-lock.json\`
</details>
`;
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes(`OWASP Dependency Check - \`${workspace}\``)
);
// Update or create comment
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}
// Fail the job if critical or high vulnerabilities found
if (parseInt(critical) > 0 || parseInt(high) > 0) {
core.setFailed(`Found ${critical} critical and ${high} high severity vulnerabilities in ${workspace}`);
}