Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,23 @@ on:
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
Expand All @@ -22,3 +34,132 @@ jobs:
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/
100 changes: 100 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres (loosely) to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

---

## [Unreleased]

- TBD

---

## [0.2.0] - 2025-11-21

### Added

- **`devsecops diagnose` command** to verify environment readiness:
- Checks installed scanners (Semgrep, Gitleaks, Trivy)
- Verifies Docker availability (for Trivy)
- Confirms project type detection
- **Interactive wizard** for initialization:
- `devsecops init --wizard`
- Guides users through selecting tools, severity thresholds, and configuration choices.
- **Automated PR security summary comment**:
- GitHub Actions workflow posts (and updates) a comment on pull requests.
- Comment includes Gitleaks leak counts, Trivy vulnerability counts, and a pass/fail recommendation.
- **JSON summary output**:
- New `artifacts/security/summary.json` file generated on each run.
- Includes:
- Total number of leaks from Gitleaks (when available)
- Aggregated Trivy vulnerabilities per severity (CRITICAL/HIGH/MEDIUM/LOW)
- **Security artifacts upload**:
- Workflow now uploads a `security-reports` artifact containing:
- `summary.json`
- `trivy-fs.json` (when Trivy is enabled)
- `gitleaks-report.json` (reserved for future enhancements)
- **Expanded `security-config.yml` schema**:
- New fields added:
- `version`: configuration schema version (starting at `"0.2.0"`)
- `exclude_paths`: reserved list for future path exclusions
- `fail_on`: reserved map for future per-tool fail gates
- `notifications`:
- `pr_comment`: enabled by default
- `slack`, `email`: placeholders for future integrations

### Changed

- **GitHub Actions workflows hardened**:
- Explicit `permissions` block:
- `contents: read`
- `issues: write`
- `pull-requests: write`
- Added job-level `timeout-minutes` to avoid hanging runs.
- Ensured artifacts folder (`artifacts/security/`) is created early in the job.
- **Workflow templates updated** to:
- Always generate `summary.json` even if some tools are disabled.
- Use `actions/github-script@v7` to manage PR comments with an idempotent marker.
- **README** refreshed to reflect v0.2.0 features:
- Added sections for wizard, diagnose, JSON summary, PR comments, and updated config format.
- Clarified installation and quick-start flows.

### Fixed

- Resolved issues with:
- Gitleaks GitHub token requirements on pull requests by setting `GITHUB_TOKEN` env in the workflow.
- Incompatible `with:` inputs for the Gitleaks action (removed unsupported inputs).
- `github-script` step script errors related to re-declaring `core` and insufficient `GITHUB_TOKEN` permissions.

---

## [0.1.0] - 2025-11-20

### Added

- Initial release of **DevSecOps Kit** CLI:
- `devsecops` binary.
- **Project type detection**:
- Node.js via `package.json`
- Go via `go.mod`
- **GitHub Actions workflow generation**:
- Node.js and Go workflows with:
- Semgrep (SAST)
- Gitleaks (secrets scanning)
- Trivy (filesystem/dependency scanning)
- **`security-config.yml` generation**:
- Base fields:
- `language`
- `framework`
- `severity_threshold`
- `tools` (Semgrep, Gitleaks, Trivy flags)
- **CLI flags for configuration**:
- `--severity` to set severity threshold.
- `--no-semgrep`, `--no-gitleaks`, `--no-trivy` to toggle tools.
- **Version subcommand**:
- `devsecops version` prints the current CLI version.

---
Loading
Loading