Use Case: Scheduled Security Audit
Complexity: Intermediate
Trigger: Daily cron schedule
Deliverable: CVE findings report, optional Jira tickets for high-severity issues
Goal
Keep your dependency security posture visible without manual effort. Every night Xema scans configured repositories for known CVEs, aggregates findings by severity, and emits a report. High-severity findings automatically open Jira issues assigned to the relevant team.
Trigger
A cron schedule fires at 00:02 UTC every day. No external webhook needed.
Steps
| Step | Type | Description |
|---|---|---|
scan-repos | Agent action (parallel fan-out) | Runs a CVE audit per repository; each job is independent |
aggregate | Agent action | Merges per-repo results into a unified findings document |
notify | Agent action | Summarises the report and sends a Slack digest to #security-alerts |
open-tickets | HTTP action (conditional) | Creates Jira issues for any critical or high CVEs found |
Deliverables
cve-findings-report— Full severity-ranked list of vulnerabilities across all scanned repos. Stored as a versioned artifact.- Jira issues — One per high/critical CVE, linked to the affected repo and component.
- Slack message — Digest summary posted to the security channel.
Workflow YAML
yaml
1apiVersion: workflow/v1alpha1
2kind: Workflow
3metadata:
4 name: scheduled-security-audit
5 version: "1.0.0"
6
7on:
8 schedule:
9 cron: "2 0 * * *"
10 timezone: UTC
11
12inputs:
13 repositories:
14 type: array
15 default:
16 - org/frontend
17 - org/backend-api
18 - org/infra-scripts
19 severityThreshold:
20 type: string
21 default: high
22
23jobs:
24 scan-repos:
25 strategy:
26 matrix:
27 repo: "{{ inputs.repositories }}"
28 action: [email protected]
29 input:
30 task: |
31 Run a CVE audit for the repository {{ matrix.repo }}.
32 Identify all dependency vulnerabilities. For each finding include:
33 CVE ID, severity, affected package, installed version, fixed version.
34 deliverableSpec: cve-findings-v1
35 output:
36 artifactKey: "scan-{{ matrix.repo | slugify }}"
37
38 aggregate:
39 needs: [scan-repos]
40 action: [email protected]
41 input:
42 task: |
43 Aggregate the per-repository CVE scan results below into a single findings report.
44 Group by severity (critical, high, medium, low). Deduplicate CVEs that appear in
45 multiple repos. Produce a structured markdown report.
46 context:
47 scanResults: "{{ jobs.scan-repos.outputs }}"
48 deliverableSpec: cve-findings-report-v1
49 output:
50 artifactKey: cve-findings-report
51
52 notify:
53 needs: [aggregate]
54 action: biomes.slack-notifier.post-[email protected]
55 input:
56 channelId: "{{ env.SECURITY_SLACK_CHANNEL }}"
57 message: |
58 *Daily CVE Audit — {{ now | date: '%Y-%m-%d' }}*
59 {{ jobs.aggregate.outputs.artifact.summary }}
60 Full report: {{ jobs.aggregate.outputs.artifact.url }}
61
62 open-tickets:
63 needs: [aggregate]
64 if: "{{ jobs.aggregate.outputs.criticalCount > 0 or jobs.aggregate.outputs.highCount > 0 }}"
65 strategy:
66 matrix:
67 finding: "{{ jobs.aggregate.outputs.highSeverityFindings }}"
68 action: [email protected]
69 input:
70 task: |
71 Create a Jira issue for the following CVE finding.
72 Project: SECURITY. Issue type: Bug. Priority: High.
73 Title: "[CVE] {{ matrix.finding.cveId }} in {{ matrix.finding.package }} ({{ matrix.finding.repo }})"
74 Description: include CVE ID, severity, affected package, installed vs fixed version, and recommended action.
75 context:
76 finding: "{{ matrix.finding }}"Extending It
- Slack thread replies — Post per-repo scan results as thread replies under the main digest.
- Approval gate before Jira creation — Wrap
open-ticketsin agate.humanApprovalso a security lead approves ticket creation. - Custom deliverable spec — Create a
cve-findings-v1spec with a strict JSON schema to enforce structured output you can query programmatically. - SARIF export — Add a step that converts findings to SARIF format and uploads to GitHub Security tab.
Previous: ← Automated PR Review Comment
Next: Spec Generation from Backlog →