Skip to content

Commit 8bc6ab1

Browse files
committed
Merge branch 'feature/web-chat-milestone2' of https://github.com/getditto/DittoChat into feature/web-chat-milestone2
2 parents 585b92f + 2093e7a commit 8bc6ab1

17 files changed

Lines changed: 23382 additions & 4016 deletions

.github/workflows/owasp-check.yml

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
name: OWASP Dependency Check
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
7+
permissions:
8+
contents: read
9+
pull-requests: write
10+
issues: write
11+
security-events: write
12+
13+
jobs:
14+
dependency-check:
15+
runs-on: ubuntu-latest
16+
17+
strategy:
18+
matrix:
19+
# Add your specific project paths here
20+
project:
21+
- "sdks/js/DittoChatCore"
22+
- "sdks/js/DittoChatUI"
23+
fail-fast: false
24+
25+
steps:
26+
- name: Checkout code
27+
uses: actions/checkout@v4
28+
29+
- name: Setup Node.js
30+
uses: actions/setup-node@v4
31+
with:
32+
node-version: "24"
33+
cache: "npm"
34+
cache-dependency-path: "${{ matrix.project }}/package-lock.json"
35+
36+
- name: Install dependencies for ${{ matrix.project }}
37+
working-directory: ${{ matrix.project }}
38+
run: npm ci
39+
40+
- name: Create suppression file
41+
run: |
42+
cat > suppression.xml << 'EOF'
43+
<?xml version="1.0" encoding="UTF-8"?>
44+
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
45+
<!-- Suppress DLL files as they are not JS dependencies -->
46+
<suppress>
47+
<notes>Ignore all DLL files - not JavaScript dependencies</notes>
48+
<filePath regex="true">.*\.dll$</filePath>
49+
<cpe regex="true">.*</cpe>
50+
</suppress>
51+
<suppress>
52+
<notes>Ignore all EXE files - not JavaScript dependencies</notes>
53+
<filePath regex="true">.*\.exe$</filePath>
54+
<cpe regex="true">.*</cpe>
55+
</suppress>
56+
<suppress>
57+
<notes>Ignore all MSI files - not JavaScript dependencies</notes>
58+
<filePath regex="true">.*\.msi$</filePath>
59+
<cpe regex="true">.*</cpe>
60+
</suppress>
61+
<suppress>
62+
<notes>Ignore all SO files - not JavaScript dependencies</notes>
63+
<filePath regex="true">.*\.so$</filePath>
64+
<cpe regex="true">.*</cpe>
65+
</suppress>
66+
<suppress>
67+
<notes>Ignore all DYLIB files - not JavaScript dependencies</notes>
68+
<filePath regex="true">.*\.dylib$</filePath>
69+
<cpe regex="true">.*</cpe>
70+
</suppress>
71+
</suppressions>
72+
EOF
73+
74+
- name: Run OWASP Dependency-Check
75+
uses: dependency-check/Dependency-Check_Action@main
76+
id: depcheck
77+
with:
78+
project: "${{ matrix.project }}"
79+
path: "${{ matrix.project }}"
80+
format: "ALL"
81+
# Only scan JS/Node related files
82+
scan: |
83+
${{ matrix.project }}/package.json
84+
${{ matrix.project }}/package-lock.json
85+
${{ matrix.project }}/node_modules
86+
args: >
87+
--enableRetired
88+
--enableExperimental
89+
--disableYarnAudit
90+
--disableNodeAudit
91+
--nodeAuditSkipDevDependencies
92+
--nodePackageSkipDevDependencies
93+
--disableAssembly
94+
--disableAutoconf
95+
--disableBundleAudit
96+
--disableCentral
97+
--disableCmake
98+
--disableCocoapodsAnalyzer
99+
--disableComposer
100+
--disableCpan
101+
--disableDart
102+
--disableGolangDep
103+
--disableGolangMod
104+
--disableJar
105+
--disableMSBuild
106+
--disableNugetconf
107+
--disableNuspec
108+
--disableOpenSSL
109+
--disablePip
110+
--disablePipfile
111+
--disablePnpmAudit
112+
--disablePoetry
113+
--disablePyDist
114+
--disablePyPkg
115+
--disableRubygems
116+
--disableSwiftPackageManagerAnalyzer
117+
--disableSwiftPackageResolvedAnalyzer
118+
--suppression suppression.xml
119+
--exclude "**/*.dll"
120+
--exclude "**/*.exe"
121+
--exclude "**/*.msi"
122+
--exclude "**/*.so"
123+
--exclude "**/*.dylib"
124+
--failOnCVSS 7
125+
126+
- name: Upload Dependency-Check Report
127+
uses: actions/upload-artifact@v4
128+
if: always()
129+
# if: ${{ !env.ACT }} /// Check to run in local action runner
130+
with:
131+
name: dependency-check-report-${{ hashFiles(format('{0}/package.json', matrix.project)) }}
132+
path: reports/
133+
retention-days: 15
134+
135+
- name: Generate Vulnerability Summary
136+
if: always()
137+
id: summary
138+
run: |
139+
PROJECT="${{ matrix.project }}"
140+
REPORT_FILE="reports/dependency-check-report.json"
141+
142+
if [ -f "$REPORT_FILE" ]; then
143+
# Extract vulnerability counts
144+
CRITICAL=$(jq '[.dependencies[].vulnerabilities[]? | select(.severity == "CRITICAL")] | length' "$REPORT_FILE")
145+
HIGH=$(jq '[.dependencies[].vulnerabilities[]? | select(.severity == "HIGH")] | length' "$REPORT_FILE")
146+
MEDIUM=$(jq '[.dependencies[].vulnerabilities[]? | select(.severity == "MEDIUM")] | length' "$REPORT_FILE")
147+
LOW=$(jq '[.dependencies[].vulnerabilities[]? | select(.severity == "LOW")] | length' "$REPORT_FILE")
148+
TOTAL=$(jq '[.dependencies[].vulnerabilities[]?] | length' "$REPORT_FILE")
149+
150+
echo "critical=$CRITICAL" >> $GITHUB_OUTPUT
151+
echo "high=$HIGH" >> $GITHUB_OUTPUT
152+
echo "medium=$MEDIUM" >> $GITHUB_OUTPUT
153+
echo "low=$LOW" >> $GITHUB_OUTPUT
154+
echo "total=$TOTAL" >> $GITHUB_OUTPUT
155+
156+
# Extract detailed vulnerabilities
157+
echo "VULNERABILITIES<<EOF" >> $GITHUB_OUTPUT
158+
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
159+
echo "EOF" >> $GITHUB_OUTPUT
160+
else
161+
echo "critical=0" >> $GITHUB_OUTPUT
162+
echo "high=0" >> $GITHUB_OUTPUT
163+
echo "medium=0" >> $GITHUB_OUTPUT
164+
echo "low=0" >> $GITHUB_OUTPUT
165+
echo "total=0" >> $GITHUB_OUTPUT
166+
echo "VULNERABILITIES=No vulnerabilities found" >> $GITHUB_OUTPUT
167+
fi
168+
169+
- name: Comment PR with Detailed Results
170+
if: always()
171+
# if: ${{ !env.ACT }} /// Check to run in local action runner
172+
uses: actions/github-script@v7
173+
with:
174+
script: |
175+
const project = '${{ matrix.project }}';
176+
const critical = '${{ steps.summary.outputs.critical }}';
177+
const high = '${{ steps.summary.outputs.high }}';
178+
const medium = '${{ steps.summary.outputs.medium }}';
179+
const low = '${{ steps.summary.outputs.low }}';
180+
const total = '${{ steps.summary.outputs.total }}';
181+
const vulnerabilities = `${{ steps.summary.outputs.VULNERABILITIES }}`;
182+
183+
// Determine status emoji and message
184+
let statusEmoji = '✅';
185+
let statusMessage = 'No vulnerabilities found';
186+
187+
if (parseInt(critical) > 0 || parseInt(high) > 0) {
188+
statusEmoji = '🚨';
189+
statusMessage = 'Critical or High severity vulnerabilities detected!';
190+
} else if (parseInt(medium) > 0) {
191+
statusEmoji = '⚠️';
192+
statusMessage = 'Medium severity vulnerabilities detected';
193+
} else if (parseInt(low) > 0) {
194+
statusEmoji = 'ℹ️';
195+
statusMessage = 'Low severity vulnerabilities detected';
196+
}
197+
198+
const body = `## ${statusEmoji} OWASP Dependency Check - \`${project}\`
199+
200+
### ${statusMessage}
201+
202+
| Severity | Count |
203+
|----------|------:|
204+
| 🔴 Critical | **${critical}** |
205+
| 🟠 High | **${high}** |
206+
| 🟡 Medium | **${medium}** |
207+
| 🔵 Low | **${low}** |
208+
| **Total** | **${total}** |
209+
210+
${parseInt(total) > 0 ? `
211+
### 📋 Vulnerability Details
212+
213+
${vulnerabilities}
214+
215+
${parseInt(total) > 50 ? '_Note: Showing first 50 vulnerabilities. Check the full report for complete details._' : ''}
216+
` : ''}
217+
218+
---
219+
220+
📊 **[View Full HTML Report](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})**
221+
222+
<details>
223+
<summary>ℹ️ How to fix vulnerabilities</summary>
224+
225+
1. Update vulnerable dependencies to patched versions
226+
2. Run \`npm audit fix\` or \`npm audit fix --force\`
227+
3. Check for alternative packages if updates aren't available
228+
4. Review and update your \`package.json\` and \`package-lock.json\`
229+
230+
</details>
231+
`;
232+
233+
// Find existing comment
234+
const { data: comments } = await github.rest.issues.listComments({
235+
owner: context.repo.owner,
236+
repo: context.repo.repo,
237+
issue_number: context.issue.number,
238+
});
239+
240+
const botComment = comments.find(comment =>
241+
comment.user.type === 'Bot' &&
242+
comment.body.includes(`OWASP Dependency Check - \`${project}\``)
243+
);
244+
245+
// Update or create comment
246+
if (botComment) {
247+
await github.rest.issues.updateComment({
248+
owner: context.repo.owner,
249+
repo: context.repo.repo,
250+
comment_id: botComment.id,
251+
body: body
252+
});
253+
} else {
254+
await github.rest.issues.createComment({
255+
owner: context.repo.owner,
256+
repo: context.repo.repo,
257+
issue_number: context.issue.number,
258+
body: body
259+
});
260+
}
261+
262+
// Fail the job if critical or high vulnerabilities found
263+
if (parseInt(critical) > 0 || parseInt(high) > 0) {
264+
core.setFailed(`Found ${critical} critical and ${high} high severity vulnerabilities in ${project}`);
265+
}

0 commit comments

Comments
 (0)