Skip to content

Merge pull request #1 from EdgarPsda/v0.2.0-changes #15

Merge pull request #1 from EdgarPsda/v0.2.0-changes

Merge pull request #1 from EdgarPsda/v0.2.0-changes #15

Workflow file for this run

name: Security Scan
on:
push:
branches: ["main"]
pull_request:
permissions:
contents: read
issues: write
pull-requests: write
jobs:
security:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Prepare artifacts directory
run: mkdir -p artifacts/security
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.21"
- name: Install dependencies
run: go mod download
- name: Run Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: "p/ci"
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run Trivy FS Scan
uses: aquasecurity/trivy-action@master
with:
scan-type: fs
format: json
output: artifacts/security/trivy-fs.json
severity: HIGH,CRITICAL
- name: Generate security summary (JSON)
if: always()
run: |
echo "Generating security summary..."
mkdir -p artifacts/security
# Gitleaks: count total findings (supports array or {findings:[...]})
if [ -f artifacts/security/gitleaks-report.json ]; then
GITLEAKS_COUNT=$(jq 'if type=="array" then length else (.findings | length // 0) end' artifacts/security/gitleaks-report.json)
else
GITLEAKS_COUNT=0
fi
# Trivy: group vulnerabilities by severity (CRITICAL/HIGH/etc.)
if [ -f artifacts/security/trivy-fs.json ]; then
TRIVY_SUMMARY=$(jq '
( [ .Results[].Vulnerabilities[]? | .Severity ]
| group_by(.)
| map({ (.[0]): length })
| add
) // {}' artifacts/security/trivy-fs.json)
else
TRIVY_SUMMARY='{}'
fi
jq -n \
--argjson gitleaks_count "$GITLEAKS_COUNT" \
--argjson trivy "$TRIVY_SUMMARY" \
'{ gitleaks: { total: $gitleaks_count }, trivy: $trivy }' \
> artifacts/security/summary.json
echo "Summary written to artifacts/security/summary.json"
- name: Post security summary as PR comment
if: always() && github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const path = 'artifacts/security/summary.json';
const marker = '<!-- devsecops-kit-security-summary -->';
let summary;
try {
const raw = fs.readFileSync(path, 'utf8');
summary = JSON.parse(raw);
} catch (err) {
core.warning(`Could not read ${path}: ${err}`);
summary = null;
}
let body = `${marker}\n`;
body += '### 🔐 DevSecOps Kit Security Summary\n\n';
if (!summary) {
body += '_No summary.json available. Check workflow logs._\n';
} else {
const gitleaksTotal = summary?.gitleaks?.total ?? 0;
const trivy = summary?.trivy || {};
body += `- **Gitleaks:** ${gitleaksTotal} leak(s)\n`;
const severities = Object.keys(trivy);
if (severities.length > 0) {
body += '- **Trivy vulnerabilities:**\n';
for (const sev of severities.sort()) {
body += ` - ${sev}: ${trivy[sev]}\n`;
}
} else {
body += '- **Trivy vulnerabilities:** none counted in summary\n';
}
const hasBlocking =
gitleaksTotal > 0 ||
(trivy.CRITICAL ?? 0) > 0 ||
(trivy.HIGH ?? 0) > 0;
body += '\n';
body += hasBlocking
? '🚨 _Status: Potential blocking issues detected._\n'
: '✅ _Status: No blocking issues detected (HIGH/CRITICAL)._ \n';
}
const { owner, repo } = context.repo;
const issue_number = context.issue.number;
const comments = await github.rest.issues.listComments({
owner,
repo,
issue_number,
});
const existing = comments.data.find(c => c.body && c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({
owner,
repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner,
repo,
issue_number,
body,
});
}
- name: Upload security artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: security-reports
path: artifacts/security/