yocto-security-tools 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yocto_security_tools-1.0.0/LICENSE +21 -0
- yocto_security_tools-1.0.0/PKG-INFO +27 -0
- yocto_security_tools-1.0.0/README.md +149 -0
- yocto_security_tools-1.0.0/cve_agent/AGENT_INSTRUCTIONS.md +161 -0
- yocto_security_tools-1.0.0/cve_agent/__init__.py +138 -0
- yocto_security_tools-1.0.0/cve_agent/__main__.py +341 -0
- yocto_security_tools-1.0.0/cve_agent/agents/yocto-cve-backport-interactive.json +52 -0
- yocto_security_tools-1.0.0/cve_agent/agents/yocto-cve-backport.json +47 -0
- yocto_security_tools-1.0.0/cve_agent/backend.py +173 -0
- yocto_security_tools-1.0.0/cve_agent/context.py +435 -0
- yocto_security_tools-1.0.0/cve_agent/corrector.py +123 -0
- yocto_security_tools-1.0.0/cve_agent/git.py +262 -0
- yocto_security_tools-1.0.0/cve_agent/knowledge.py +311 -0
- yocto_security_tools-1.0.0/cve_agent/orchestrator.py +425 -0
- yocto_security_tools-1.0.0/cve_agent/py.typed +0 -0
- yocto_security_tools-1.0.0/cve_agent/review.py +312 -0
- yocto_security_tools-1.0.0/cve_agent/session.py +359 -0
- yocto_security_tools-1.0.0/cve_agent/setup.py +147 -0
- yocto_security_tools-1.0.0/cve_corrector/__init__.py +39 -0
- yocto_security_tools-1.0.0/cve_corrector/__main__.py +279 -0
- yocto_security_tools-1.0.0/cve_corrector/bitbake_ops.py +214 -0
- yocto_security_tools-1.0.0/cve_corrector/blame.py +334 -0
- yocto_security_tools-1.0.0/cve_corrector/cherry_pick.py +299 -0
- yocto_security_tools-1.0.0/cve_corrector/git_ops.py +296 -0
- yocto_security_tools-1.0.0/cve_corrector/meta_layer.py +255 -0
- yocto_security_tools-1.0.0/cve_corrector/patch_ops.py +136 -0
- yocto_security_tools-1.0.0/cve_corrector/ptest.py +131 -0
- yocto_security_tools-1.0.0/cve_corrector/py.typed +0 -0
- yocto_security_tools-1.0.0/cve_corrector/recipe_ops.py +344 -0
- yocto_security_tools-1.0.0/cve_corrector/state.py +200 -0
- yocto_security_tools-1.0.0/cve_corrector/ui.py +87 -0
- yocto_security_tools-1.0.0/cve_corrector/utils.py +93 -0
- yocto_security_tools-1.0.0/cve_corrector/version.py +75 -0
- yocto_security_tools-1.0.0/cve_corrector/workflow.py +591 -0
- yocto_security_tools-1.0.0/cve_corrector/workspace.py +233 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/__init__.py +19 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/__main__.py +421 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/config.json +13 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/config.py +56 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/cve_sources.py +57 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/cvelistv5.py +188 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/debian.py +552 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/mirrors.py +143 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/oe_status.py +274 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/osv.py +190 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/processing.py +114 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/py.typed +0 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/sources.py +97 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/ubuntu.py +189 -0
- yocto_security_tools-1.0.0/cve_metadata_extractor/utils.py +123 -0
- yocto_security_tools-1.0.0/pyproject.toml +89 -0
- yocto_security_tools-1.0.0/setup.cfg +4 -0
- yocto_security_tools-1.0.0/shared/__init__.py +38 -0
- yocto_security_tools-1.0.0/shared/exit_codes.py +26 -0
- yocto_security_tools-1.0.0/shared/git_runner.py +68 -0
- yocto_security_tools-1.0.0/shared/json_cache.py +48 -0
- yocto_security_tools-1.0.0/shared/paths.py +27 -0
- yocto_security_tools-1.0.0/shared/py.typed +0 -0
- yocto_security_tools-1.0.0/shared/url_parser.py +284 -0
- yocto_security_tools-1.0.0/yocto_security_tools.egg-info/PKG-INFO +27 -0
- yocto_security_tools-1.0.0/yocto_security_tools.egg-info/SOURCES.txt +63 -0
- yocto_security_tools-1.0.0/yocto_security_tools.egg-info/dependency_links.txt +1 -0
- yocto_security_tools-1.0.0/yocto_security_tools.egg-info/entry_points.txt +4 -0
- yocto_security_tools-1.0.0/yocto_security_tools.egg-info/requires.txt +8 -0
- yocto_security_tools-1.0.0/yocto_security_tools.egg-info/top_level.txt +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (C) 2026 Ericsson AB
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yocto-security-tools
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Standalone CVE management tools for Yocto/OpenEmbedded
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/Ericsson/yocto-security-tools
|
|
7
|
+
Project-URL: Repository, https://github.com/Ericsson/yocto-security-tools
|
|
8
|
+
Project-URL: Issues, https://github.com/Ericsson/yocto-security-tools/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/Ericsson/yocto-security-tools/blob/main/CHANGELOG.md
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Security
|
|
17
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: requests<3,>=2.28
|
|
21
|
+
Requires-Dist: packaging<27,>=23.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest<10,>=7.0; extra == "dev"
|
|
24
|
+
Requires-Dist: pytest-cov<8,>=4.0; extra == "dev"
|
|
25
|
+
Requires-Dist: mypy<3,>=1.8; extra == "dev"
|
|
26
|
+
Requires-Dist: ruff<1,>=0.4; extra == "dev"
|
|
27
|
+
Dynamic: license-file
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
# yocto-security-tools
|
|
3
|
+
|
|
4
|
+
Standalone CVE management tools for Yocto/OpenEmbedded Linux distributions.
|
|
5
|
+
|
|
6
|
+
## Tools
|
|
7
|
+
|
|
8
|
+
| Tool | Purpose |
|
|
9
|
+
|------|---------|
|
|
10
|
+
| **cve-metadata-extractor** | Find fix commits for CVEs from multiple public sources (Debian, OSV, CVEList V5, Ubuntu, NVD) |
|
|
11
|
+
| **cve-corrector** | Automate backporting CVE fixes to Yocto recipes using devtool |
|
|
12
|
+
| **cve-agent** | Orchestrate CVE backporting with AI-assisted conflict resolution |
|
|
13
|
+
|
|
14
|
+
## Requirements
|
|
15
|
+
|
|
16
|
+
- Python 3.9+
|
|
17
|
+
- Git
|
|
18
|
+
- For `cve-corrector` / `cve-agent`: a sourced Yocto build environment (`BBPATH` set)
|
|
19
|
+
- For `cve-agent`: [kiro-cli](https://github.com/aws/kiro-cli) (or a custom AI backend plugin)
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install -e .
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
### Find CVE fix metadata
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# From Yocto cve-summary.json (output of sbom-cve-check)
|
|
33
|
+
cve-metadata-extractor --yocto-summary cve-summary.json --output cve-metadata.json
|
|
34
|
+
|
|
35
|
+
# For a specific CVE
|
|
36
|
+
cve-metadata-extractor --cve-id CVE-2024-1234 --cve-component-name openssl
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Apply CVE patches
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Source your Yocto build environment first
|
|
43
|
+
source oe-init-build-env
|
|
44
|
+
|
|
45
|
+
# Apply a CVE fix
|
|
46
|
+
cve-corrector --cve-id CVE-2024-1234 --cve-info cve-metadata.json
|
|
47
|
+
|
|
48
|
+
# Resume after manual conflict resolution
|
|
49
|
+
cve-corrector --continue
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### AI-assisted backporting
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Requires kiro-cli (or another AI backend)
|
|
56
|
+
cve-agent --cve-id CVE-2024-1234 --cve-info cve-metadata.json --trust
|
|
57
|
+
|
|
58
|
+
# Batch mode
|
|
59
|
+
cve-agent --cve-list cves.txt --cve-info cve-metadata.json --trust
|
|
60
|
+
|
|
61
|
+
# Use a different AI backend
|
|
62
|
+
cve-agent --cve-id CVE-2024-1234 --cve-info cve-metadata.json --backend my_backend
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## How It Works
|
|
66
|
+
|
|
67
|
+
```mermaid
|
|
68
|
+
graph LR
|
|
69
|
+
E["cve-metadata-extractor<br/>Find fix commits"] -->|cve-metadata.json| C["cve-corrector<br/>Apply patches via devtool"]
|
|
70
|
+
C -->|exit code + state| A["cve-agent<br/>AI-assisted resolution"]
|
|
71
|
+
A -->|subprocess| C
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Each tool works independently. Chain them via `--cve-info cve-metadata.json`.
|
|
75
|
+
|
|
76
|
+
## Supported Input Formats
|
|
77
|
+
|
|
78
|
+
| Format | Flag | Description |
|
|
79
|
+
|--------|------|-------------|
|
|
80
|
+
| cve-summary.json | `--yocto-summary` | Output from Yocto's `sbom-cve-check` class |
|
|
81
|
+
| Direct CVE ID | `--cve-id` | One or more CVE identifiers |
|
|
82
|
+
| CVE list file | `--cve-list` | Text file with one CVE ID per line (agent only) |
|
|
83
|
+
|
|
84
|
+
## Configuration
|
|
85
|
+
|
|
86
|
+
The extractor reads configuration from `cve_metadata_extractor/config.json` by default.
|
|
87
|
+
Override with the `CVE_EXTRACTOR_CONFIG` environment variable.
|
|
88
|
+
|
|
89
|
+
### Storage (XDG Compliant)
|
|
90
|
+
|
|
91
|
+
| Directory | Default | Override |
|
|
92
|
+
|-----------|---------|----------|
|
|
93
|
+
| Persistent data | `~/.local/share/yocto-security-tools/` | `CVE_TOOLS_DATA_DIR` |
|
|
94
|
+
| Cache (expendable) | `~/.cache/yocto-security-tools/` | `CVE_TOOLS_CACHE_DIR` |
|
|
95
|
+
|
|
96
|
+
### Config Keys
|
|
97
|
+
|
|
98
|
+
| Key | Default | Description |
|
|
99
|
+
|-----|---------|-------------|
|
|
100
|
+
| `cvelistv5_url` | GitHub | Git URL to clone CVEList V5 from |
|
|
101
|
+
| `debian_tracker_url` | salsa.debian.org | Git URL for Debian tracker |
|
|
102
|
+
| `nvd_url` | GitHub | Git URL for NVD data |
|
|
103
|
+
| `oe_branches` | `["scarthgap"]` | OE branches to check for fix status |
|
|
104
|
+
|
|
105
|
+
## Environment Variables
|
|
106
|
+
|
|
107
|
+
| Variable | Purpose |
|
|
108
|
+
|----------|---------|
|
|
109
|
+
| `CVE_EXTRACTOR_CONFIG` | Override config.json path |
|
|
110
|
+
| `CVE_TOOLS_DATA_DIR` | Override XDG data directory |
|
|
111
|
+
| `CVE_TOOLS_CACHE_DIR` | Override XDG cache directory |
|
|
112
|
+
| `GITHUB_TOKEN` | GitHub API access (required for PR metadata) |
|
|
113
|
+
| `OPENEMBEDDED_TOKEN` | OE mailing list API |
|
|
114
|
+
| `BBPATH` | Required for cve-corrector/cve-agent (Yocto build env) |
|
|
115
|
+
| `CVE_EXTRA_SOURCES_DIR` | Override plugin directory for extractor |
|
|
116
|
+
| `CVE_EXTRA_BACKENDS_DIR` | Override plugin directory for agent backends |
|
|
117
|
+
|
|
118
|
+
## Plugin System
|
|
119
|
+
|
|
120
|
+
Add custom CVE data sources or AI backends by dropping `.py` files in the `extra/` directory. See [extra/README.md](extra/README.md) for the plugin development guide.
|
|
121
|
+
|
|
122
|
+
### Quick Example: Custom Source
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
# extra/my_source.py
|
|
126
|
+
from cve_metadata_extractor.sources import CveSource, SOURCE_REGISTRY
|
|
127
|
+
|
|
128
|
+
class MySource(CveSource):
|
|
129
|
+
name = 'my_source'
|
|
130
|
+
def is_enabled(self, args): return True
|
|
131
|
+
def extract(self, cve_id, stats): return [], [], [], []
|
|
132
|
+
|
|
133
|
+
SOURCE_REGISTRY.append(MySource())
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Development
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
python3 -m venv venv
|
|
140
|
+
source venv/bin/activate
|
|
141
|
+
pip install -e ".[dev]"
|
|
142
|
+
pytest
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for full development guidelines.
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
MIT — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: MIT -->
|
|
2
|
+
# CVE Backport Agent Instructions
|
|
3
|
+
|
|
4
|
+
## Scope Rules
|
|
5
|
+
|
|
6
|
+
You may ONLY modify files listed in the **Allowed Files** section of the context header.
|
|
7
|
+
A git pre-commit hook enforces this — commits with unauthorized files will be rejected.
|
|
8
|
+
|
|
9
|
+
**NEVER do any of these:**
|
|
10
|
+
- `git add .` or `git add -A`
|
|
11
|
+
- `git commit --no-verify` or `git cherry-pick --no-verify`
|
|
12
|
+
- Cherry-pick additional upstream commits beyond what cve_corrector already applied
|
|
13
|
+
- Create or rename files not in the Allowed Files list
|
|
14
|
+
- Modify `.gitignore` or any file not in the Allowed Files list
|
|
15
|
+
- Run `cve_corrector.py` (the agent handles workflow progression)
|
|
16
|
+
- Read files outside the workspace directory
|
|
17
|
+
- Use the `glob` tool
|
|
18
|
+
|
|
19
|
+
**Prerequisite commits**: If the upstream fix depends on a prior commit, do NOT
|
|
20
|
+
cherry-pick it separately. Instead, manually adapt the conflicting code to work
|
|
21
|
+
without the prerequisite — inline the necessary changes into the files already
|
|
22
|
+
being modified. The generated patch must only contain the upstream fix commit's
|
|
23
|
+
changes, adapted for the stable branch.
|
|
24
|
+
|
|
25
|
+
**Files not in the baseline**: If the upstream commit adds a NEW file that is
|
|
26
|
+
in the Allowed Files list, include it — `git cherry-pick` will stage it
|
|
27
|
+
automatically. If it conflicts or requires infrastructure not present in the
|
|
28
|
+
stable branch, mention it in the commit message as:
|
|
29
|
+
`<file>: omitted (depends on <missing infrastructure>)`
|
|
30
|
+
|
|
31
|
+
Only omit a file if including it would break the build or if it depends on
|
|
32
|
+
code/headers/build rules that don't exist in the stable branch.
|
|
33
|
+
|
|
34
|
+
## Workflow
|
|
35
|
+
|
|
36
|
+
### 1. Analyse (always)
|
|
37
|
+
```bash
|
|
38
|
+
git log original-version..HEAD --oneline # what was applied
|
|
39
|
+
git show HEAD # understand the fix
|
|
40
|
+
```
|
|
41
|
+
If the patch is incompatible with the stable base, adapt it.
|
|
42
|
+
|
|
43
|
+
If the CVE fix is **not applicable** to this version (e.g. the vulnerable code
|
|
44
|
+
path, function, struct, or feature does not exist in the stable branch), do NOT
|
|
45
|
+
make any code changes. Instead, write a conclusion file:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cat > "<agent_dir>/conclusion.json" <<'EOF'
|
|
49
|
+
{"not_applicable": true, "reason": "<one-line explanation of why the CVE does not apply>"}
|
|
50
|
+
EOF
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Replace `<agent_dir>` with the actual agent dir path from the context header.
|
|
54
|
+
The reason should be specific — mention the missing function, struct, code path,
|
|
55
|
+
or feature and the version. Example:
|
|
56
|
+
`"PBMAC1 infrastructure (PBMAC1PARAM, PBMAC1_get1_pbkdf2_param) does not exist in 3.2.6; CVE-2025-11187 is not applicable to this version"`
|
|
57
|
+
|
|
58
|
+
After writing the conclusion file, **stop — do not make any other changes.**
|
|
59
|
+
|
|
60
|
+
### 2. Resolve Conflicts (exit code 1)
|
|
61
|
+
```bash
|
|
62
|
+
git status && git diff # examine conflicts
|
|
63
|
+
git show <upstream_sha> # upstream fix intent
|
|
64
|
+
git log --oneline -20 -- <file> # file history for context
|
|
65
|
+
```
|
|
66
|
+
Resolve conflicts, then:
|
|
67
|
+
```bash
|
|
68
|
+
git add <resolved_files> # ONLY allowed files
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
If you adapted the patch (not a verbatim cherry-pick), append your backport
|
|
72
|
+
notes to `.git/MERGE_MSG` — **read the file first**, keep the original content,
|
|
73
|
+
and append your notes after a blank line. Then:
|
|
74
|
+
```bash
|
|
75
|
+
git cherry-pick --no-edit --continue
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 3. Fix Build Errors (exit code 4)
|
|
79
|
+
Read the last 50 lines of the build log. If the failing task belongs to a
|
|
80
|
+
**different recipe** than the one being patched, **abort immediately** — do not
|
|
81
|
+
attempt to fix it. This indicates a pre-existing or environmental issue.
|
|
82
|
+
Otherwise, fix the code and amend the commit.
|
|
83
|
+
|
|
84
|
+
### 4. Fix Test Failures (exit code 3)
|
|
85
|
+
Fix the **backported code in the allowed files only**.
|
|
86
|
+
If the fix requires changing a file not in the allowed list, stop and
|
|
87
|
+
flag for human review. Document which tests failed and what code change
|
|
88
|
+
fixed them in the commit message.
|
|
89
|
+
|
|
90
|
+
### 5. Build Verification (mandatory after every change)
|
|
91
|
+
```bash
|
|
92
|
+
BUILD_LOG="<agent_dir>/build_$$.log"
|
|
93
|
+
devtool build <recipe> > "$BUILD_LOG" 2>&1
|
|
94
|
+
echo "Exit code: $?"
|
|
95
|
+
```
|
|
96
|
+
On failure: `tail -50 "$BUILD_LOG"`, fix, `git commit --amend --no-edit`, retry.
|
|
97
|
+
If `devtool build` logs are insufficient, check Yocto task logs at:
|
|
98
|
+
`<yocto_tmp>/work/<arch>/<recipe>/*/temp/log.do_compile`
|
|
99
|
+
(paths are in the context header).
|
|
100
|
+
On success: **stop — your work is done.**
|
|
101
|
+
|
|
102
|
+
For cross-compilation: use `bitbake -c devshell <recipe>`, never run
|
|
103
|
+
make/cmake/gcc directly.
|
|
104
|
+
|
|
105
|
+
## Resolution Principles
|
|
106
|
+
|
|
107
|
+
- **Minimal changes only** — smallest adaptation to make the fix work on stable
|
|
108
|
+
- **Preserve upstream intent** — adapt APIs/signatures, never change fix logic
|
|
109
|
+
- **Match surrounding whitespace** — use the same indentation style (tabs vs spaces, alignment width) as the surrounding code in the stable branch, not the upstream patch
|
|
110
|
+
- **Check dependencies** — look for `Link:` in commit, prerequisite patches
|
|
111
|
+
- **If uncertain, stop** — flag for human review rather than guess
|
|
112
|
+
|
|
113
|
+
## Common Conflict Patterns
|
|
114
|
+
|
|
115
|
+
| Pattern | Resolution | Commit Note |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| Function signature changed | Keep fix logic, adapt to stable signature | `Adapted foo_v2() to foo_v1() API` |
|
|
118
|
+
| Struct member renamed | Use stable member name with upstream logic | `Member renamed netdev→ndev in original patch` |
|
|
119
|
+
| Function moved to different file | Apply fix where function lives in stable | `Function in old_file.c in original patch` |
|
|
120
|
+
| Missing helper function | Inline it or use stable equivalent | `Inlined helper_foo() (not in stable)` |
|
|
121
|
+
|
|
122
|
+
## Commit Message Format
|
|
123
|
+
|
|
124
|
+
**IMPORTANT: Preserve the original upstream commit message.** The `.git/MERGE_MSG`
|
|
125
|
+
file contains the original upstream commit subject and body. You MUST keep it
|
|
126
|
+
intact and only **append** your backport notes after it. Never replace or rewrite
|
|
127
|
+
the original message.
|
|
128
|
+
|
|
129
|
+
Only append notes if you adapted the patch. Use EXACTLY this markdown format — no
|
|
130
|
+
alternative headers like "Conflict resolution notes:" or "Backport changes:".
|
|
131
|
+
|
|
132
|
+
Append the following block after the original commit message (separated by a
|
|
133
|
+
blank line):
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
Backport Resolution: <One or two sentences explaining what the upstream commit does — the functional
|
|
137
|
+
change, not the conflict details.>
|
|
138
|
+
|
|
139
|
+
Conflicts Resolved:
|
|
140
|
+
|
|
141
|
+
<file> (<N> conflict[s]):
|
|
142
|
+
- <What was changed and why, referencing stable vs upstream differences.>
|
|
143
|
+
|
|
144
|
+
<file> (<N> conflict[s]):
|
|
145
|
+
- <What was changed and why.>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Rules:
|
|
149
|
+
- **Never delete or rewrite the original subject line or body** from `.git/MERGE_MSG`
|
|
150
|
+
- Append your notes after the existing message, separated by a blank line
|
|
151
|
+
- Start with a summary of the upstream fix's purpose (what it changes, why)
|
|
152
|
+
- List ONLY files that had conflicts or required adaptation — skip clean files
|
|
153
|
+
- For each file, state the conflict count and describe each adaptation
|
|
154
|
+
- Mention specific function names, types, APIs, and why the stable branch differs
|
|
155
|
+
- Omitted files: `<file>: omitted (not in branch)`
|
|
156
|
+
- Do NOT add a "Changes from upstream" section (the agent generates that)
|
|
157
|
+
- If you adapted the patch (not a verbatim cherry-pick), add a trailer line
|
|
158
|
+
after a blank line at the end of the commit message:
|
|
159
|
+
`Assisted-by: <backend>:<model>` where `<backend>` and `<model>` are the
|
|
160
|
+
**Backend** and **Model** values from the context header (e.g.
|
|
161
|
+
`Assisted-by: kiro:claude-sonnet-4-20250514`)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Copyright (C) 2026 Ericsson AB
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
"""CVE Agent - Orchestrates CVE backporting with AI-assisted conflict resolution.
|
|
4
|
+
|
|
5
|
+
Wraps cve_corrector and spawns AI sessions to resolve conflicts, build errors,
|
|
6
|
+
and test failures during CVE backporting.
|
|
7
|
+
"""
|
|
8
|
+
import sys
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from enum import Enum
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
# Exit codes (single source of truth: shared/exit_codes.py)
|
|
15
|
+
from shared.exit_codes import (
|
|
16
|
+
EXIT_AGENT_ERROR,
|
|
17
|
+
EXIT_AI_TIMEOUT,
|
|
18
|
+
EXIT_ALREADY_APPLIED,
|
|
19
|
+
EXIT_BUILD_ERROR,
|
|
20
|
+
EXIT_BUILD_PREEXISTING,
|
|
21
|
+
EXIT_CHECKOUT_ERROR,
|
|
22
|
+
EXIT_CONFLICT,
|
|
23
|
+
EXIT_DEVTOOL_ERROR,
|
|
24
|
+
EXIT_GIT_ERROR,
|
|
25
|
+
EXIT_METADATA_ERROR,
|
|
26
|
+
EXIT_NOT_APPLICABLE,
|
|
27
|
+
EXIT_PATCH_ERROR,
|
|
28
|
+
EXIT_PTEST_ERROR,
|
|
29
|
+
EXIT_PTEST_PREEXISTING,
|
|
30
|
+
EXIT_SUCCESS,
|
|
31
|
+
EXIT_TRUST_DECLINED,
|
|
32
|
+
)
|
|
33
|
+
from shared.paths import data_dir
|
|
34
|
+
|
|
35
|
+
# Exit codes that trigger the resolution loop (agent can attempt to fix)
|
|
36
|
+
RECOVERABLE_EXITS = {EXIT_CONFLICT, EXIT_PTEST_ERROR, EXIT_BUILD_ERROR}
|
|
37
|
+
|
|
38
|
+
# Exit codes that require immediate escalation (no point retrying)
|
|
39
|
+
UNRECOVERABLE_EXITS = {EXIT_CHECKOUT_ERROR, EXIT_PATCH_ERROR,
|
|
40
|
+
EXIT_METADATA_ERROR, EXIT_GIT_ERROR,
|
|
41
|
+
EXIT_PTEST_PREEXISTING, EXIT_DEVTOOL_ERROR,
|
|
42
|
+
EXIT_BUILD_PREEXISTING, EXIT_NOT_APPLICABLE}
|
|
43
|
+
|
|
44
|
+
# Default paths
|
|
45
|
+
DEFAULT_KNOWLEDGE_PATH = data_dir() / 'knowledge.json'
|
|
46
|
+
DEFAULT_MAX_RETRIES = 3
|
|
47
|
+
DEFAULT_SESSION_TIMEOUT = 600
|
|
48
|
+
CORRECTOR_CMD = [sys.executable, '-m', 'cve_corrector']
|
|
49
|
+
AGENT_INSTRUCTIONS = Path(__file__).resolve().parent / 'AGENT_INSTRUCTIONS.md'
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class ResultStatus(Enum):
|
|
53
|
+
"""Outcome status for a CVE processing attempt."""
|
|
54
|
+
SUCCESS = "success"
|
|
55
|
+
CONFLICT_RESOLVED = "conflict_resolved"
|
|
56
|
+
FAILED = "failed"
|
|
57
|
+
ESCALATED = "escalated"
|
|
58
|
+
SKIPPED = "skipped"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class AgentConfig:
|
|
63
|
+
"""Configuration for a single CVE agent run."""
|
|
64
|
+
cve_id: str
|
|
65
|
+
cve_info_path: Optional[Path] = None
|
|
66
|
+
trust_mode: bool = False
|
|
67
|
+
max_retries: int = DEFAULT_MAX_RETRIES
|
|
68
|
+
max_total_attempts: int = 0 # 0 = no cap beyond per-step max_retries
|
|
69
|
+
mirror_dir: Optional[Path] = None
|
|
70
|
+
meta_layer: Optional[Path] = None
|
|
71
|
+
skip_ptest: bool = False
|
|
72
|
+
clean: bool = False
|
|
73
|
+
model: str = "claude-sonnet-4.6"
|
|
74
|
+
session_timeout: int = DEFAULT_SESSION_TIMEOUT
|
|
75
|
+
interactive: bool = False
|
|
76
|
+
bbappend: bool = False
|
|
77
|
+
skip_cve_applicability: bool = False
|
|
78
|
+
fix_url: Optional[str] = None
|
|
79
|
+
recipe: Optional[str] = None
|
|
80
|
+
backend: str = "kiro"
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass
|
|
84
|
+
class CveResult:
|
|
85
|
+
"""Outcome of processing a single CVE."""
|
|
86
|
+
cve_id: str
|
|
87
|
+
status: ResultStatus
|
|
88
|
+
retries: int = 0
|
|
89
|
+
duration: float = 0.0
|
|
90
|
+
resolution_summary: str = ""
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def get_build_dir(workspace_path: Path) -> Path:
|
|
94
|
+
"""Derive the Yocto build directory from a devtool workspace path.
|
|
95
|
+
|
|
96
|
+
The devtool workspace structure is: <build>/workspace/sources/<recipe>,
|
|
97
|
+
so the build directory is three levels up from the workspace path.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
workspace_path: Path to the devtool workspace source directory.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Path to the Yocto build directory.
|
|
104
|
+
"""
|
|
105
|
+
return workspace_path.parent.parent.parent
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_agent_dir(workspace_path: Path) -> Path:
|
|
109
|
+
"""Get or create the agent working directory outside the git workspace.
|
|
110
|
+
|
|
111
|
+
Uses the build workspace's cve_agent/ directory to avoid polluting
|
|
112
|
+
the source git repo with agent artifacts.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
workspace_path: Path to the devtool workspace source directory.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Path to the cve_agent/<recipe> directory, created if needed.
|
|
119
|
+
"""
|
|
120
|
+
recipe = workspace_path.name
|
|
121
|
+
build_workspace = workspace_path.parent.parent
|
|
122
|
+
agent_dir = build_workspace / 'cve_agent' / recipe
|
|
123
|
+
agent_dir.mkdir(parents=True, exist_ok=True)
|
|
124
|
+
return agent_dir
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
__all__ = [
|
|
128
|
+
'AgentConfig', 'CveResult', 'ResultStatus',
|
|
129
|
+
'RECOVERABLE_EXITS', 'UNRECOVERABLE_EXITS',
|
|
130
|
+
'DEFAULT_KNOWLEDGE_PATH', 'DEFAULT_MAX_RETRIES', 'DEFAULT_SESSION_TIMEOUT',
|
|
131
|
+
'CORRECTOR_CMD', 'AGENT_INSTRUCTIONS',
|
|
132
|
+
'get_build_dir', 'get_agent_dir',
|
|
133
|
+
'EXIT_SUCCESS', 'EXIT_CONFLICT', 'EXIT_CHECKOUT_ERROR', 'EXIT_PTEST_ERROR',
|
|
134
|
+
'EXIT_BUILD_ERROR', 'EXIT_PATCH_ERROR', 'EXIT_METADATA_ERROR', 'EXIT_GIT_ERROR',
|
|
135
|
+
'EXIT_PTEST_PREEXISTING', 'EXIT_DEVTOOL_ERROR', 'EXIT_BUILD_PREEXISTING',
|
|
136
|
+
'EXIT_ALREADY_APPLIED', 'EXIT_NOT_APPLICABLE',
|
|
137
|
+
'EXIT_TRUST_DECLINED', 'EXIT_AGENT_ERROR', 'EXIT_AI_TIMEOUT',
|
|
138
|
+
]
|