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

StepTypeDescription
scan-reposAgent action (parallel fan-out)Runs a CVE audit per repository; each job is independent
aggregateAgent actionMerges per-repo results into a unified findings document
notifyAgent actionSummarises the report and sends a Slack digest to #security-alerts
open-ticketsHTTP 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-tickets in a gate.humanApproval so a security lead approves ticket creation.
  • Custom deliverable spec — Create a cve-findings-v1 spec 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 →