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
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

## Table of Contents

- [What's new (2026-06-21) — OpenVEX Vulnerability Triage](#whats-new-2026-06-21--openvex-vulnerability-triage)
- [What's new (2026-06-21) — Dependency Vulnerability Scanning (OSV)](#whats-new-2026-06-21--dependency-vulnerability-scanning-osv)
- [What's new (2026-06-21) — JSON Schema Validation](#whats-new-2026-06-21--json-schema-validation)
- [What's new (2026-06-20) — SARIF 2.1.0 Findings Export](#whats-new-2026-06-20--sarif-210-findings-export)
Expand Down Expand Up @@ -111,6 +112,12 @@

---

## What's new (2026-06-21) — OpenVEX Vulnerability Triage

Suppress the vulns that don't affect you. Full reference: [`docs/source/Eng/doc/new_features/v59_features_doc.rst`](docs/source/Eng/doc/new_features/v59_features_doc.rst).

- **`vex_statement` / `build_vex` / `apply_vex`** (`AC_apply_vex`, `ac_apply_vex`): the OSV scanner surfaces every known CVE forever — there was no way to record "we checked, this one doesn't affect us". This authors [OpenVEX](https://openvex.dev) 0.2.0 statements and applies them to the scanner's findings: `not_affected`/`fixed` **suppress** a finding, `affected`/`under_investigation` **annotate** it. Statements join on the vuln id *or* an alias, optionally product-scoped; `not_affected` requires a justification or impact statement. Pure-stdlib; chains directly after `AC_scan_vulns`.

## What's new (2026-06-21) — Dependency Vulnerability Scanning (OSV)

Match the SBOM against known CVEs. Full reference: [`docs/source/Eng/doc/new_features/v58_features_doc.rst`](docs/source/Eng/doc/new_features/v58_features_doc.rst).
Expand Down
7 changes: 7 additions & 0 deletions README/README_zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

## 目录

- [本次更新 (2026-06-21) — OpenVEX 漏洞分级](#本次更新-2026-06-21--openvex-漏洞分级)
- [本次更新 (2026-06-21) — 依赖项漏洞扫描(OSV)](#本次更新-2026-06-21--依赖项漏洞扫描osv)
- [本次更新 (2026-06-21) — JSON Schema 验证](#本次更新-2026-06-21--json-schema-验证)
- [本次更新 (2026-06-20) — SARIF 2.1.0 发现项目导出](#本次更新-2026-06-20--sarif-210-发现项目导出)
Expand Down Expand Up @@ -110,6 +111,12 @@

---

## 本次更新 (2026-06-21) — OpenVEX 漏洞分级

抑制不影响你的漏洞。完整参考:[`docs/source/Zh/doc/new_features/v59_features_doc.rst`](../docs/source/Zh/doc/new_features/v59_features_doc.rst)。

- **`vex_statement` / `build_vex` / `apply_vex`**(`AC_apply_vex`、`ac_apply_vex`):OSV 扫描器会让每个已知 CVE 一直出现 —— 没有办法记录「我们查过了,这个不影响我们」。本功能撰写 [OpenVEX](https://openvex.dev) 0.2.0 陈述并套用到扫描器的发现项目:`not_affected`/`fixed` **抑制**一项发现,`affected`/`under_investigation` **标注**它。陈述以漏洞 id *或*别名配对,并可限定产品;`not_affected` 需附理由或冲击说明。纯标准库;可直接接在 `AC_scan_vulns` 之后。

## 本次更新 (2026-06-21) — 依赖项漏洞扫描(OSV)

以 SBOM 比对已知 CVE。完整参考:[`docs/source/Zh/doc/new_features/v58_features_doc.rst`](../docs/source/Zh/doc/new_features/v58_features_doc.rst)。
Expand Down
7 changes: 7 additions & 0 deletions README/README_zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

## 目錄

- [本次更新 (2026-06-21) — OpenVEX 漏洞分級](#本次更新-2026-06-21--openvex-漏洞分級)
- [本次更新 (2026-06-21) — 相依套件漏洞掃描(OSV)](#本次更新-2026-06-21--相依套件漏洞掃描osv)
- [本次更新 (2026-06-21) — JSON Schema 驗證](#本次更新-2026-06-21--json-schema-驗證)
- [本次更新 (2026-06-20) — SARIF 2.1.0 發現項目匯出](#本次更新-2026-06-20--sarif-210-發現項目匯出)
Expand Down Expand Up @@ -110,6 +111,12 @@

---

## 本次更新 (2026-06-21) — OpenVEX 漏洞分級

抑制不影響你的漏洞。完整參考:[`docs/source/Zh/doc/new_features/v59_features_doc.rst`](../docs/source/Zh/doc/new_features/v59_features_doc.rst)。

- **`vex_statement` / `build_vex` / `apply_vex`**(`AC_apply_vex`、`ac_apply_vex`):OSV 掃描器會讓每個已知 CVE 一直出現 —— 沒有辦法記錄「我們查過了,這個不影響我們」。本功能撰寫 [OpenVEX](https://openvex.dev) 0.2.0 陳述並套用到掃描器的發現項目:`not_affected`/`fixed` **抑制**一項發現,`affected`/`under_investigation` **標註**它。陳述以漏洞 id *或*別名配對,並可限定產品;`not_affected` 需附理由或衝擊說明。純標準函式庫;可直接接在 `AC_scan_vulns` 之後。

## 本次更新 (2026-06-21) — 相依套件漏洞掃描(OSV)

以 SBOM 比對已知 CVE。完整參考:[`docs/source/Zh/doc/new_features/v58_features_doc.rst`](../docs/source/Zh/doc/new_features/v58_features_doc.rst)。
Expand Down
52 changes: 52 additions & 0 deletions docs/source/Eng/doc/new_features/v59_features_doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
OpenVEX Vulnerability Triage
============================

``scan_components`` (the OSV matcher) produces vulnerability findings, but every
known CVE then shows up on every run forever — there was no way to record "we
looked, this one does not affect us" and drop it. VEX (Vulnerability
Exploitability eXchange) is the standard for exactly that triage signal. This
authors `OpenVEX <https://openvex.dev>`_ 0.2.0 statements and applies them to
the scanner's findings.

``not_affected`` / ``fixed`` statements **suppress** a finding; ``affected`` /
``under_investigation`` **annotate** it with the assessed status. Statements
join to findings on the vulnerability id *or* any of its aliases, optionally
scoped to a product. Pure standard library (``hashlib`` + ``json`` +
``datetime``); imports no ``PySide6``.

Headless API
------------

.. code-block:: python

from je_auto_control import (
scan_components, vex_statement, build_vex, apply_vex)

findings = scan_components(sbom["components"], advisories)

statements = [
vex_statement("CVE-2024-1", "not_affected",
products=["pkg:pypi/foo"],
justification="vulnerable_code_not_present"),
vex_statement("GHSA-bar", "under_investigation"),
]
vex = build_vex(statements, author="security@example.com")

triaged = apply_vex(findings, vex)
# CVE-2024-1 (not_affected) dropped; GHSA-bar kept with vex_status set

``vex_statement`` validates the inputs: ``status`` must be one of
``VEX_STATUSES`` (``not_affected`` / ``affected`` / ``fixed`` /
``under_investigation``); a ``not_affected`` statement must carry a
``justification`` (one of ``VEX_JUSTIFICATIONS``) or an ``impact_statement``.
``build_vex`` wraps statements in an OpenVEX document (pass an explicit
``timestamp`` for a reproducible ``@id``). ``apply_vex`` returns the surviving
findings, each non-suppressed match annotated with ``vex_status``.

Executor command
----------------

``AC_apply_vex`` takes ``findings`` and a ``vex`` document (each a list/object
or a JSON string) and returns ``{findings, count}`` of the survivors. The same
operation is exposed as the MCP tool ``ac_apply_vex`` and as a Script Builder
command under **Security**. It chains directly after ``AC_scan_vulns``.
1 change: 1 addition & 0 deletions docs/source/Eng/eng_index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Comprehensive guides for all AutoControl features.
doc/new_features/v56_features_doc
doc/new_features/v57_features_doc
doc/new_features/v58_features_doc
doc/new_features/v59_features_doc
doc/ocr_backends/ocr_backends_doc
doc/observability/observability_doc
doc/operations_layer/operations_layer_doc
Expand Down
45 changes: 45 additions & 0 deletions docs/source/Zh/doc/new_features/v59_features_doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
OpenVEX 漏洞分級
===============

``scan_components``(OSV 比對器)會產生漏洞發現項目,但之後每次執行每個已知 CVE 都會一直出現
—— 沒有辦法記錄「我們看過了,這個不影響我們」並把它捨棄。VEX(Vulnerability Exploitability
eXchange)正是這個分級訊號的標準。本功能撰寫 `OpenVEX <https://openvex.dev>`_ 0.2.0 陳述並
套用到掃描器的發現項目上。

``not_affected`` / ``fixed`` 陳述會**抑制**一項發現;``affected`` / ``under_investigation``
則以評估後的狀態**標註**它。陳述以漏洞 id *或*其任一別名與發現項目配對,並可選擇性地限定到某個
產品。純標準函式庫(``hashlib`` + ``json`` + ``datetime``);不匯入 ``PySide6``。

無頭 API
--------

.. code-block:: python

from je_auto_control import (
scan_components, vex_statement, build_vex, apply_vex)

findings = scan_components(sbom["components"], advisories)

statements = [
vex_statement("CVE-2024-1", "not_affected",
products=["pkg:pypi/foo"],
justification="vulnerable_code_not_present"),
vex_statement("GHSA-bar", "under_investigation"),
]
vex = build_vex(statements, author="security@example.com")

triaged = apply_vex(findings, vex)
# CVE-2024-1(not_affected)被捨棄;GHSA-bar 保留並設定 vex_status

``vex_statement`` 會驗證輸入:``status`` 必須是 ``VEX_STATUSES`` 之一(``not_affected`` /
``affected`` / ``fixed`` / ``under_investigation``);``not_affected`` 陳述必須帶有
``justification``(``VEX_JUSTIFICATIONS`` 其一)或 ``impact_statement``。``build_vex`` 把
陳述包成 OpenVEX 文件(傳入明確的 ``timestamp`` 可得到可重現的 ``@id``)。``apply_vex`` 回傳
存活的發現項目,每個未被抑制的配對都會標註 ``vex_status``。

執行器命令
----------

``AC_apply_vex`` 接受 ``findings`` 與一份 ``vex`` 文件(各為 list/object 或 JSON 字串),回傳
存活者的 ``{findings, count}``。同一操作亦以 MCP 工具 ``ac_apply_vex`` 以及 Script Builder
中 **Security** 分類下的命令提供。它可直接接在 ``AC_scan_vulns`` 之後。
1 change: 1 addition & 0 deletions docs/source/Zh/zh_index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ AutoControl 所有功能的完整使用指南。
doc/new_features/v56_features_doc
doc/new_features/v57_features_doc
doc/new_features/v58_features_doc
doc/new_features/v59_features_doc
doc/ocr_backends/ocr_backends_doc
doc/observability/observability_doc
doc/operations_layer/operations_layer_doc
Expand Down
6 changes: 6 additions & 0 deletions je_auto_control/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,10 @@
from je_auto_control.utils.vuln_scan import (
findings_to_sarif, is_affected, match_package, scan_components, version_key,
)
# OpenVEX triage over vulnerability findings
from je_auto_control.utils.vex import (
VEX_JUSTIFICATIONS, VEX_STATUSES, apply_vex, build_vex, vex_statement,
)
# Background popup/interrupt watchdog (unattended automation)
from je_auto_control.utils.watchdog import (
PopupWatchdog, WatchdogRule, default_popup_watchdog,
Expand Down Expand Up @@ -778,6 +782,8 @@ def start_autocontrol_gui(*args, **kwargs):
"SchemaValidationResult", "assert_schema", "is_valid", "validate_json",
"findings_to_sarif", "is_affected", "match_package", "scan_components",
"version_key",
"VEX_JUSTIFICATIONS", "VEX_STATUSES", "apply_vex", "build_vex",
"vex_statement",
# MCP server
"AuditLogger", "HttpMCPServer", "MCPContent", "MCPPrompt",
"MCPPromptArgument", "MCPResource", "MCPServer", "MCPTool",
Expand Down
11 changes: 11 additions & 0 deletions je_auto_control/gui/script_builder/command_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,17 @@ def _add_misc_specs(specs: List[CommandSpec]) -> None:
),
description="Match SBOM components against an OSV advisory database.",
))
specs.append(CommandSpec(
"AC_apply_vex", "Security", "Apply VEX Triage to Findings",
fields=(
FieldSpec("findings", FieldType.STRING,
placeholder='[{"id": "GHSA-...", "package": "foo"}]'),
FieldSpec("vex", FieldType.STRING,
placeholder='{"statements": [{"vulnerability": '
'{"name": "CVE-..."}, "status": "not_affected"}]}'),
),
description="Suppress not_affected/fixed vulns via an OpenVEX document.",
))
specs.append(CommandSpec(
"AC_run_saga", "Flow", "Run Saga (Compensating Rollback)",
fields=(
Expand Down
13 changes: 13 additions & 0 deletions je_auto_control/utils/executor/action_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2885,6 +2885,18 @@ def _scan_vulns(components: Any, advisories: Any = None,
return result


def _apply_vex(findings: Any, vex: Any) -> Dict[str, Any]:
"""Adapter: suppress VEX'd vulnerability findings (each JSON string/obj)."""
import json
from je_auto_control.utils.vex import apply_vex
if isinstance(findings, str):
findings = json.loads(findings)
if isinstance(vex, str):
vex = json.loads(vex)
kept = apply_vex(findings, vex)
return {"findings": kept, "count": len(kept)}


def _generate_sop(actions: List[Any], title: str = "Automation Procedure",
path: Optional[str] = None) -> Dict[str, Any]:
"""Adapter: build (or write) a step-by-step SOP from an action list."""
Expand Down Expand Up @@ -3665,6 +3677,7 @@ def __init__(self):
"AC_heal_stats": _heal_stats,
"AC_scan_secrets": _scan_secrets,
"AC_scan_vulns": _scan_vulns,
"AC_apply_vex": _apply_vex,
"AC_generate_sop": _generate_sop,
"AC_tween_drag": _tween_drag,
"AC_list_plugins": _list_plugins,
Expand Down
19 changes: 18 additions & 1 deletion je_auto_control/utils/mcp_server/tools/_factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -3262,6 +3262,23 @@ def vuln_scan_tools() -> List[MCPTool]:
]


def vex_tools() -> List[MCPTool]:
return [
MCPTool(
name="ac_apply_vex",
description=("Apply an OpenVEX document to vulnerability "
"'findings': drop the ones marked not_affected/fixed "
"and annotate the rest with their VEX status. Returns "
"{findings, count}."),
input_schema=schema(
{"findings": {"type": "array"}, "vex": {"type": "object"}},
["findings", "vex"]),
handler=h.apply_vex,
annotations=READ_ONLY,
),
]


def saga_tools() -> List[MCPTool]:
return [
MCPTool(
Expand Down Expand Up @@ -4456,7 +4473,7 @@ def media_assert_tools() -> List[MCPTool]:
video_report_tools, fuzzy_tools, artifact_store_tools, image_dedup_tools,
locale_tools, voice_tools, coordinate_space_tools, loop_guard_tools,
process_mining_tools, asset_tools, events_tools, notify_channel_tools,
jsonpath_tools, json_schema_tools, vuln_scan_tools, saga_tools,
jsonpath_tools, json_schema_tools, vuln_scan_tools, vex_tools, saga_tools,
decision_table_tools, locator_repair_tools,
pii_text_tools, sarif_tools,
screen_record_tools,
Expand Down
6 changes: 6 additions & 0 deletions je_auto_control/utils/mcp_server/tools/_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1569,6 +1569,12 @@ def scan_vulns(components, advisories=None):
return {"findings": findings, "count": len(findings)}


def apply_vex(findings, vex):
from je_auto_control.utils.vex import apply_vex as _apply
kept = _apply(findings, vex)
return {"findings": kept, "count": len(kept)}


def run_saga(steps):
from je_auto_control.utils.saga import run_saga as _run
result = _run(steps)
Expand Down
9 changes: 9 additions & 0 deletions je_auto_control/utils/vex/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""OpenVEX statement authoring and triage over vulnerability findings."""
from je_auto_control.utils.vex.vex import (
VEX_JUSTIFICATIONS, VEX_STATUSES, apply_vex, build_vex, vex_statement,
)

__all__ = [
"VEX_JUSTIFICATIONS", "VEX_STATUSES", "apply_vex", "build_vex",
"vex_statement",
]
Loading
Loading