up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Reachability Corpus Validation / validate-corpus (push) Has been cancelled
Reachability Corpus Validation / validate-ground-truths (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Reachability Corpus Validation / determinism-check (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-12-14 15:50:38 +02:00
parent f1a39c4ce3
commit 233873f620
249 changed files with 29746 additions and 154 deletions

View File

@@ -0,0 +1,210 @@
# GAP-VEX-006: Sample VEX decision notification templates
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Usage:
# 1. Copy to etc/notify-templates/vex-decision.yaml
# 2. Customize templates per channel type
# 3. Import via: stella notify template import vex-decision.yaml
templates:
# Email template for VEX decision notifications
- key: vex.decision.changed
channel_type: email
locale: en-US
render_mode: markdown
description: "Notification when VEX decision status changes"
body: |
## VEX Decision Changed: {{ vulnerability_id }}
**Product:** {{ product.name }} ({{ product.version }})
**PURL:** `{{ product.purl }}`
**Status Changed:** {{ previous_status }} → **{{ new_status }}**
### Reachability Evidence
{% if reachability_evidence %}
- **State:** {{ reachability_evidence.state }}
- **Confidence:** {{ reachability_evidence.confidence | percent }}
- **Graph Hash:** `{{ reachability_evidence.graph_hash }}`
{% if reachability_evidence.call_paths | length > 0 %}
#### Call Paths ({{ reachability_evidence.call_paths | length }})
{% for path in reachability_evidence.call_paths | slice(0, 3) %}
- **{{ path.entry_point }}** → ... → **{{ path.vulnerable_function }}** (depth {{ path.depth }})
{% endfor %}
{% if reachability_evidence.call_paths | length > 3 %}
_(and {{ reachability_evidence.call_paths | length - 3 }} more paths)_
{% endif %}
{% endif %}
{% if reachability_evidence.runtime_hits | length > 0 %}
#### Runtime Hits ({{ reachability_evidence.runtime_hits | length }})
| Function | Hits | Last Observed |
|----------|------|---------------|
{% for hit in reachability_evidence.runtime_hits | slice(0, 5) %}
| {{ hit.function_name }} | {{ hit.hit_count }} | {{ hit.last_observed | date }} |
{% endfor %}
{% endif %}
{% else %}
_(No reachability evidence available)_
{% endif %}
### Signature
{% if signature.signed %}
- **Signed:** Yes
- **Algorithm:** {{ signature.algorithm }}
- **Key ID:** `{{ signature.key_id }}`
- **DSSE Envelope:** `{{ signature.dsse_envelope_id }}`
{% if signature.rekor_entry_id %}
- **Rekor Entry:** [{{ signature.rekor_entry_id }}]({{ signature.rekor_url }})
{% endif %}
{% else %}
- **Signed:** No (unsigned decision)
{% endif %}
---
[View in StellaOps]({{ dashboard_url }}/vuln/{{ vulnerability_id }})
# Slack template for VEX decision notifications
- key: vex.decision.changed
channel_type: slack
locale: en-US
render_mode: slack_blocks
description: "Slack notification for VEX decision changes"
body: |
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "VEX Decision Changed: {{ vulnerability_id }}"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Product:*\n{{ product.name }}"
},
{
"type": "mrkdwn",
"text": "*Status:*\n{{ previous_status }} → *{{ new_status }}*"
}
]
},
{% if reachability_evidence %}
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Reachability:* {{ reachability_evidence.state }} ({{ reachability_evidence.confidence | percent }} confidence)\n*Graph Hash:* `{{ reachability_evidence.graph_hash | truncate(16) }}...`"
}
},
{% if reachability_evidence.call_paths | length > 0 %}
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Call Paths:* {{ reachability_evidence.call_paths | length }} found\n{% for path in reachability_evidence.call_paths | slice(0, 2) %}• {{ path.entry_point }} → {{ path.vulnerable_function }}\n{% endfor %}"
}
},
{% endif %}
{% endif %}
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "View Details"
},
"url": "{{ dashboard_url }}/vuln/{{ vulnerability_id }}"
}
]
}
]
}
# Teams template for VEX decision notifications
- key: vex.decision.changed
channel_type: teams
locale: en-US
render_mode: adaptive_card
description: "Teams notification for VEX decision changes"
body: |
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "TextBlock",
"text": "VEX Decision Changed: {{ vulnerability_id }}",
"weight": "Bolder",
"size": "Large"
},
{
"type": "FactSet",
"facts": [
{ "title": "Product", "value": "{{ product.name }} {{ product.version }}" },
{ "title": "PURL", "value": "{{ product.purl }}" },
{ "title": "Status", "value": "{{ previous_status }} → {{ new_status }}" }
{% if reachability_evidence %}
,{ "title": "Reachability", "value": "{{ reachability_evidence.state }} ({{ reachability_evidence.confidence | percent }})" }
,{ "title": "Call Paths", "value": "{{ reachability_evidence.call_paths | length }}" }
,{ "title": "Runtime Hits", "value": "{{ reachability_evidence.runtime_hits | length }}" }
{% endif %}
]
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "View in StellaOps",
"url": "{{ dashboard_url }}/vuln/{{ vulnerability_id }}"
}
]
}
# Webhook template for VEX decision notifications (JSON payload)
- key: vex.decision.changed
channel_type: webhook
locale: en-US
render_mode: json
description: "Webhook payload for VEX decision changes"
body: |
{
"event_type": "vex.decision.changed",
"timestamp": "{{ timestamp | iso8601 }}",
"vulnerability_id": "{{ vulnerability_id }}",
"product": {
"key": "{{ product.key }}",
"name": "{{ product.name }}",
"version": "{{ product.version }}",
"purl": "{{ product.purl }}"
},
"previous_status": "{{ previous_status }}",
"new_status": "{{ new_status }}",
"reachability_evidence": {% if reachability_evidence %}{
"state": "{{ reachability_evidence.state }}",
"confidence": {{ reachability_evidence.confidence }},
"graph_hash": "{{ reachability_evidence.graph_hash }}",
"graph_cas_uri": "{{ reachability_evidence.graph_cas_uri }}",
"call_path_count": {{ reachability_evidence.call_paths | length }},
"runtime_hit_count": {{ reachability_evidence.runtime_hits | length }},
"dsse_envelope_id": "{{ reachability_evidence.dsse_envelope_id }}",
"rekor_entry_id": "{{ reachability_evidence.rekor_entry_id }}"
}{% else %}null{% endif %},
"signature": {
"signed": {{ signature.signed | json }},
"algorithm": "{{ signature.algorithm }}",
"key_id": "{{ signature.key_id }}",
"dsse_envelope_id": "{{ signature.dsse_envelope_id }}",
"rekor_entry_id": "{{ signature.rekor_entry_id }}"
},
"tenant_id": "{{ tenant_id }}",
"dashboard_url": "{{ dashboard_url }}/vuln/{{ vulnerability_id }}"
}