From 139e9bf705a3c1ff02c0615b29e4a1723e7ab621 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Thu, 16 Apr 2026 23:06:01 +0200 Subject: [PATCH 01/16] chore: add governance files (SECURITY, CHANGELOG, CODEOWNERS, PR template) Closes governance gaps surfaced by the automated-assessment run: - SECURITY.md: private vulnerability reporting (advisories + email) - CHANGELOG.md: Keep-a-Changelog format with an Unreleased bucket - .github/CODEOWNERS: default reviewer team per area - .github/PULL_REQUEST_TEMPLATE.md: summary/test-plan/checklist Covers: GH-03, GH-05, GW-05, GW-06, ER-44. Signed-off-by: Sebastian Mendel --- .github/CODEOWNERS | 15 +++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 37 ++++++++++++++++++++++++++++++++ CHANGELOG.md | 28 ++++++++++++++++++++++++ SECURITY.md | 30 ++++++++++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 CHANGELOG.md create mode 100644 SECURITY.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..3ed5a49 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,15 @@ +# See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-security/customizing-your-repository/about-code-owners +# Order matters — the last matching rule wins. + +# Default reviewers for anything not matched below. +* @netresearch/coding-agents + +# Python package, audit, detection. +/cli_audit/ @netresearch/coding-agents +/audit.py @netresearch/coding-agents + +# Installer and upgrade orchestration. +/scripts/ @netresearch/coding-agents + +# CI, release, security automation. +/.github/ @netresearch/coding-agents diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..7ae0d3a --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,37 @@ + + +## Summary + + + +## Linked issues / PRs + + + +## Type of change + +- [ ] Bug fix (`fix:`) +- [ ] New feature (`feat:`) +- [ ] Refactor / internal change (`refactor:`) +- [ ] Docs only (`docs:`) +- [ ] Chore / CI / deps (`chore:`) +- [ ] Breaking change (describe migration below) + +## Test plan + + + +- [ ] `uv run pytest` +- [ ] `uv run python -m flake8 cli_audit tests` +- [ ] `./scripts/test_smoke.sh` +- [ ] Manual scenario: … + +## Checklist + +- [ ] Conventional Commits (`type(scope): description`) +- [ ] Commits signed (`git commit -S --signoff`) +- [ ] `CHANGELOG.md` updated for user-visible changes +- [ ] Relevant `AGENTS.md` files updated if structure / commands changed +- [ ] No secrets, credentials, or PII committed diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..1e94606 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,28 @@ +# Changelog + +All notable changes to this project are documented in this file. + +The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added +- Governance files: `SECURITY.md`, `CODEOWNERS`, PR template, `CHANGELOG.md`. +- `.github/workflows/codeql.yml`, `scorecard.yml`, `dependency-review.yml` for supply-chain scanning. +- `.pre-commit-config.yaml` for local hook enforcement. +- README badges (CI, Codecov, License). +- AGENTS.md structural sections (Commands, Setup, Testing, Architecture, Development). +- Per-cycle `auto_update` storage for multi-version tools (`python@3.13` vs `python@3.14`). +- Persistent endoflife.date cache at `~/.cache/cli-audit/endoflife.json` with fallback on HTTP failure. +- Binary-probe fallback in `guide.sh` when the post-install snapshot refresh is stale. + +### Fixed +- `cmd_update_local` in MERGE mode now refreshes multi-version cycle entries (`python@3.14`, …) instead of only the base-tool entry. Resolved false-negative "Upgrade did not succeed" messages after successful uv installs. + +### Changed +- Upgraded 23 locked Python dev-dependencies to latest compatible versions (bandit 1.9.4, mypy 1.20.1, isort 8.0.1, rich 15.0, coverage 7.13.5, …). + +## Prior history + +See [git log](https://github.com/netresearch/coding_agent_cli_toolset/commits/main) for commits prior to this changelog. Tagged releases: [Releases page](https://github.com/netresearch/coding_agent_cli_toolset/releases). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..0b7306b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +## Reporting a Vulnerability + +Please **do not** open a public issue for security-relevant findings. + +Use one of the following instead: + +- **Preferred:** [Privately report a vulnerability](https://github.com/netresearch/coding_agent_cli_toolset/security/advisories/new) via GitHub. +- Or email `security@netresearch.de` with details and steps to reproduce. + +You should receive an acknowledgement within 3 working days. We will confirm the +issue, agree on disclosure timelines with you, and publish a fix + GitHub +Security Advisory once the fix is available. + +## Scope + +In scope: code in this repository, published releases of `cli-audit`, the +installation / audit / upgrade scripts under `scripts/`, and anything that +would let an attacker execute code on or exfiltrate data from a machine that +runs `make upgrade` / `audit.py` against trusted upstream sources. + +Out of scope: vulnerabilities in third-party tools installed via the `install_*` +scripts (report those upstream), bugs that are only reachable by an attacker +with shell-level access to the machine running this toolkit. + +## Supported Versions + +Security fixes target the latest tagged release on the `main` branch. Older +tags do not receive backports. From 304ddddace272950d69d980a7e17fbc60a7b56f7 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Thu, 16 Apr 2026 23:07:27 +0200 Subject: [PATCH 02/16] ci: add CodeQL, Scorecard, and dependency-review workflows - codeql.yml: reuses existing .github/codeql/codeql-config.yml (security-extended + security-and-quality queries), weekly + per-PR. - scorecard.yml: weekly OpenSSF Scorecard analysis, publishes to scorecard.dev and uploads SARIF to the Security tab. - dependency-review.yml: blocks PRs that introduce vulnerable dependencies at moderate severity or above. All actions SHA-pinned. Covers: ER-19/20/21, GH-19. Signed-off-by: Sebastian Mendel --- .github/workflows/codeql.yml | 42 +++++++++++++++++++++++++ .github/workflows/dependency-review.yml | 22 +++++++++++++ .github/workflows/scorecard.yml | 38 ++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/dependency-review.yml create mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..d23aa84 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,42 @@ +name: CodeQL + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + # Weekly, Monday 06:00 UTC — catches advisories for deps that change slowly. + - cron: '0 6 * * 1' + workflow_dispatch: + +permissions: + contents: read + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: [python] + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Initialize CodeQL + uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + with: + languages: ${{ matrix.language }} + config-file: ./.github/codeql/codeql-config.yml + queries: security-extended,security-and-quality + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + with: + category: /language:${{ matrix.language }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..5782f8f --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,22 @@ +name: Dependency Review + +on: + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + dependency-review: + name: Review dependency changes + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Dependency Review + uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 + with: + fail-on-severity: moderate + comment-summary-in-pr: true diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..99dfbac --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,38 @@ +name: OpenSSF Scorecard + +on: + branch_protection_rule: + schedule: + - cron: '0 6 * * 1' + push: + branches: [main] + workflow_dispatch: + +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + security-events: write + id-token: write + contents: read + actions: read + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Run analysis + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + - name: Upload SARIF + uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + with: + sarif_file: results.sarif From 5c006ab1b941dd1d696bc7ccf1f2686a9dadd0c5 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Thu, 16 Apr 2026 23:08:04 +0200 Subject: [PATCH 03/16] chore: add pre-commit config (flake8, black, isort, shellcheck, hygiene) Install locally with: uv run pre-commit install Hooks: - pre-commit-hooks v6.0.0: whitespace, EOL, YAML/JSON validity, large file guard, merge-conflict markers. - flake8 7.3.0 / isort 8.0.1 / black 26.3.1: Python lint and format. - shellcheck v0.11.0 (warning severity): shell script hygiene. Covers: GW-14. Signed-off-by: Sebastian Mendel --- .pre-commit-config.yaml | 47 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..2418e56 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,47 @@ +# See https://pre-commit.com for usage. +# +# Install: uv run pre-commit install +# Run all: uv run pre-commit run --all-files + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-json + - id: check-added-large-files + - id: check-merge-conflict + - id: mixed-line-ending + args: ['--fix=lf'] + + - repo: https://github.com/PyCQA/flake8 + rev: 7.3.0 + hooks: + - id: flake8 + files: ^(cli_audit|tests)/ + + - repo: https://github.com/PyCQA/isort + rev: 8.0.1 + hooks: + - id: isort + files: ^(cli_audit|tests)/ + args: ['--profile=black'] + + - repo: https://github.com/psf/black + rev: 26.3.1 + hooks: + - id: black + files: ^(cli_audit|tests)/ + + - repo: https://github.com/koalaman/shellcheck-precommit + rev: v0.11.0 + hooks: + - id: shellcheck + files: ^scripts/.*\.sh$ + args: ['--severity=warning'] + +ci: + autofix_commit_msg: 'chore: pre-commit autofixes' + autoupdate_commit_msg: 'chore(deps): pre-commit autoupdate' From 28654fa5127266ac7852367e5fb0ea875b551368 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Thu, 16 Apr 2026 23:08:19 +0200 Subject: [PATCH 04/16] docs(readme): add CI, CodeQL, Codecov, Scorecard, license badges Covers: ER-22, ER-23, ER-04, GH-10, GH-11, GH-12. Signed-off-by: Sebastian Mendel --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 8d29d29..8bdb54b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # AI CLI Preparation +[![CI](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/ci.yml/badge.svg)](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/ci.yml) +[![CodeQL](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/codeql.yml/badge.svg)](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/codeql.yml) +[![codecov](https://codecov.io/gh/netresearch/coding_agent_cli_toolset/branch/main/graph/badge.svg)](https://codecov.io/gh/netresearch/coding_agent_cli_toolset) +[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/netresearch/coding_agent_cli_toolset/badge)](https://scorecard.dev/viewer/?uri=github.com/netresearch/coding_agent_cli_toolset) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + A minimal utility to verify that tools used by AI coding agents are installed and up to date on your system. It audits versions of common agent toolchain CLIs against the latest upstream releases and prints a pipe-delimited report suitable for quick human scan or downstream tooling. ## Quick Start From e427278d11579880bf87961032ccaad0b0ca706b Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Thu, 16 Apr 2026 23:10:32 +0200 Subject: [PATCH 05/16] docs(agents): add Setup/Development/Testing/Architecture sections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit agent-rules checkpoints require canonical headings for automated scanning. Rename/restructure to the canonical names and add the two missing sections: - 'Package management (uv)' → 'Setup' (AG-03) - 'Quick reference' → 'Commands (verified 2026-04-16)' (AG-04) - 'Project overview' → 'Architecture', with Project structure (AG-05) - New 'Development' section with hook install + branch/commit conventions (AG-06) - New 'Testing' section with focused pytest invocations (AG-07) - 'Last verified' footer (AG-18) Covers AG-03, AG-04, AG-05, AG-06, AG-07, AG-18. Content preserved; only structure changed. Signed-off-by: Sebastian Mendel --- AGENTS.md | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6d1296c..1ff6c89 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,7 +13,7 @@ - Ask before: heavy deps, full rewrites, breaking changes - Never commit secrets, PII, or credentials -## Package management (uv) +## Setup **This project uses [uv](https://docs.astral.sh/uv/) for package management.** Always use `uv run` to execute Python commands. @@ -29,7 +29,11 @@ uv run python -m flake8 # Run linter **Why uv?** Fast dependency resolution, proper lockfile support, and isolated environments without manual venv activation. -## Minimal pre-commit checks +**Prerequisites:** Python ≥ 3.14, `uv`, and a POSIX shell (most installer scripts are Bash). + +## Development + +Minimal pre-commit checks (also enforced by `.pre-commit-config.yaml`): ```bash uv run python -m pytest # All tests (required) @@ -39,6 +43,21 @@ uv run python -m mypy cli_audit # mypy (optional) uv run python audit.py --help # Verify CLI works ``` +Install the git hooks once per checkout: `uv run pre-commit install`. +New features and bug fixes go on a feature branch (`fix/…`, `feat/…`, `chore/…`) → PR against `main` → signed commits (`git commit -S --signoff`). +See [`SECURITY.md`](./SECURITY.md) for vulnerability reporting and [`CHANGELOG.md`](./CHANGELOG.md) for release history. + +## Testing + +```bash +uv run pytest # Full suite (546 tests) +uv run pytest -x -q # Fail-fast, quiet +uv run pytest tests/test_upgrade.py -k multi_version # Focused run +uv run pytest --cov=cli_audit --cov-report=term # With coverage +``` + +Test layout and conventions: see [`tests/AGENTS.md`](./tests/AGENTS.md). Integration suite under `tests/integration/` is collected separately — CI runs it as its own step. + ## Project maintenance vs. tool feature This repo **is** a CLI tool manager, so the word "upgrade" is overloaded: @@ -57,7 +76,7 @@ This repo **is** a CLI tool manager, so the word "upgrade" is overloaded: - [scripts/AGENTS.md](./scripts/AGENTS.md) — Installation scripts (Bash, 33 scripts) - [tests/AGENTS.md](./tests/AGENTS.md) — Test suite (pytest, 14 test files) -## Quick reference +## Commands (verified 2026-04-16) | Command | Purpose | |---------|---------| @@ -99,15 +118,28 @@ This repo **is** a CLI tool manager, so the word "upgrade" is overloaded: **Caches:** - `~/.cache/cli-audit/endoflife.json` — endoflife.date response cache, used as fallback on transient HTTP failures (override path via `CLI_AUDIT_ENDOFLIFE_CACHE`). -## Project overview +## Architecture **AI CLI Preparation v2.0** — Tool version auditing and installation management for AI coding agents. -- **Architecture:** 21 Python modules, 89 JSON tool catalogs +- **Modules:** 21 Python modules under `cli_audit/` (see [`cli_audit/AGENTS.md`](./cli_audit/AGENTS.md)) +- **Catalog:** 89 JSON tool definitions under `catalog/` +- **Installers:** 33 Bash scripts under `scripts/` (see [`scripts/AGENTS.md`](./scripts/AGENTS.md)) - **Phase 1:** Detection & auditing (complete) - **Phase 2:** Installation & upgrade management (complete) - **Entry point:** `audit.py` → `cli_audit` package +### Project structure + +``` +audit.py # CLI dispatcher (cmd_audit, cmd_update, cmd_install, …) +cli_audit/ # Core library (detection, collectors, snapshot, installer, …) +catalog/ # Per-tool JSON definitions (binary_name, version_command, multi_version) +scripts/ # Installer / upgrade / reconcile shell scripts + scripts/lib helpers +tests/ # pytest suite (unit + integration) +Makefile / Makefile.d/ # Task runner: `make audit`, `make upgrade`, `make upgrade-all` +``` + ## Multi-version runtimes Runtimes supporting multiple concurrent versions (PHP, Python, Node.js, Ruby, Go) use dynamic detection from [endoflife.date](https://endoflife.date/) API. @@ -125,3 +157,7 @@ CLI_AUDIT_JSON=1 uv run python audit.py --versions ## When instructions conflict Nearest AGENTS.md wins. User prompts override all files. + +--- + +*Last verified: 2026-04-16 (against `main` at HEAD).* From a59374579137f40b79c40f0a98bc15883a109cd1 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Thu, 16 Apr 2026 23:12:38 +0200 Subject: [PATCH 06/16] ci: add Security workflow (pip-audit, bandit, SBOM) + .gitignore vendor - security.yml: scheduled weekly + per-PR pip-audit, bandit, and CycloneDX SBOM generation uploaded as a 90-day artifact. - .gitignore: add vendor/ (harmless for Python; matches cross-ecosystem scanner expectations). Covers: ER-01, ER-02, ER-03, GW-03. Signed-off-by: Sebastian Mendel --- .github/workflows/security.yml | 79 ++++++++++++++++++++++++++++++++++ .gitignore | 3 ++ 2 files changed, 82 insertions(+) create mode 100644 .github/workflows/security.yml diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..12d80a3 --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,79 @@ +name: Security + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + - cron: '0 6 * * 1' + workflow_dispatch: + +permissions: + contents: read + +jobs: + audit: + name: Python security audit + runs-on: ubuntu-latest + steps: + - name: Harden runner + uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 + with: + egress-policy: audit + + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3.14' + + - name: Install pip-audit and bandit + run: | + python -m pip install --upgrade pip + pip install pip-audit bandit[toml] + + # pip-audit reads pyproject.toml + uv.lock; fail only on known CVEs + - name: pip-audit (pyproject + uv.lock) + run: pip-audit --skip-editable + + - name: bandit (static analysis) + run: bandit -r cli_audit -c pyproject.toml + + sbom: + name: Generate SBOM (CycloneDX) + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + attestations: write + steps: + - name: Harden runner + uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 + with: + egress-policy: audit + + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: '3.14' + + - name: Install cyclonedx-py + run: | + python -m pip install --upgrade pip + pip install cyclonedx-bom + + - name: Generate CycloneDX SBOM + run: cyclonedx-py environment --of JSON -o sbom.cdx.json + + - name: Upload SBOM artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: sbom-cyclonedx + path: sbom.cdx.json + retention-days: 90 diff --git a/.gitignore b/.gitignore index 583f861..3f353a3 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,9 @@ tools_snapshot.json # Node.js node_modules/ +# Vendored dependencies (this project uses uv; vendor/ is reserved for ad-hoc checkouts) +vendor/ + # AI agent session context (not committed) claudedocs/ .serena/ From a616933dace83bd3d00317db7aac775d4be6baf7 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Thu, 16 Apr 2026 23:12:38 +0200 Subject: [PATCH 07/16] ci: add step-security/harden-runner to security scanners Audit-mode egress monitoring on codeql, scorecard, and dependency-review workflows. Non-blocking; reports unexpected network calls. Covers: ER-27. Signed-off-by: Sebastian Mendel --- .github/workflows/codeql.yml | 5 +++++ .github/workflows/dependency-review.yml | 5 +++++ .github/workflows/scorecard.yml | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d23aa84..916cc0b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -26,6 +26,11 @@ jobs: matrix: language: [python] steps: + - name: Harden runner + uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 5782f8f..08df612 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -12,6 +12,11 @@ jobs: name: Review dependency changes runs-on: ubuntu-latest steps: + - name: Harden runner + uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 99dfbac..c2d84e5 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -20,6 +20,11 @@ jobs: contents: read actions: read steps: + - name: Harden runner + uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: From 638aa6910c622404e49362c575daca12fbc874c7 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Fri, 17 Apr 2026 00:09:17 +0200 Subject: [PATCH 08/16] ci: remove codeql.yml; rely on default code-scanning setup GitHub's default setup is already configured for this repo (query suite: extended), and it rejected uploads from the new advanced workflow with: CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled. Drop the workflow, drop the README badge that would otherwise point at a missing file. CodeQL results remain visible in the Security tab. Fixes PR #75 CI failure. Signed-off-by: Sebastian Mendel --- .github/workflows/codeql.yml | 47 ------------------------------------ 1 file changed, 47 deletions(-) delete mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 916cc0b..0000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: CodeQL - -on: - push: - branches: [main] - pull_request: - branches: [main] - schedule: - # Weekly, Monday 06:00 UTC — catches advisories for deps that change slowly. - - cron: '0 6 * * 1' - workflow_dispatch: - -permissions: - contents: read - -jobs: - analyze: - name: Analyze (${{ matrix.language }}) - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - strategy: - fail-fast: false - matrix: - language: [python] - steps: - - name: Harden runner - uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 - with: - egress-policy: audit - - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Initialize CodeQL - uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 - with: - languages: ${{ matrix.language }} - config-file: ./.github/codeql/codeql-config.yml - queries: security-extended,security-and-quality - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 - with: - category: /language:${{ matrix.language }} From 2272b965f7581e4f4c948ce37fa1d37d11640ad5 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Fri, 17 Apr 2026 00:09:32 +0200 Subject: [PATCH 09/16] docs(readme): drop CodeQL badge (workflow removed, default setup active) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to the previous commit — the CodeQL workflow file was dropped, so its badge would 404. Signed-off-by: Sebastian Mendel --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8bdb54b..b2169d9 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@ # AI CLI Preparation [![CI](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/ci.yml/badge.svg)](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/ci.yml) -[![CodeQL](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/codeql.yml/badge.svg)](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/codeql.yml) [![codecov](https://codecov.io/gh/netresearch/coding_agent_cli_toolset/branch/main/graph/badge.svg)](https://codecov.io/gh/netresearch/coding_agent_cli_toolset) [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/netresearch/coding_agent_cli_toolset/badge)](https://scorecard.dev/viewer/?uri=github.com/netresearch/coding_agent_cli_toolset) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + + + A minimal utility to verify that tools used by AI coding agents are installed and up to date on your system. It audits versions of common agent toolchain CLIs against the latest upstream releases and prints a pipe-delimited report suitable for quick human scan or downstream tooling. ## Quick Start From 39aab23094f5f97c88e27e800348aad03842f84f Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Fri, 17 Apr 2026 00:09:45 +0200 Subject: [PATCH 10/16] ci(security): install deps before pip-audit/SBOM, add bandit config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review feedback from Copilot on PR #75: - pip-audit previously ran against the bare runner environment, so it effectively audited nothing. Now uses uv: `uv sync --all-extras --dev --frozen` → `uv export > requirements.txt` → `pip-audit -r`. - SBOM job similarly needed the project installed before cyclonedx-py could enumerate real dependencies; now syncs first. - Dropped the unused `id-token: write` and `attestations: write` permissions on the SBOM job (not creating attestations). - bandit now runs with `-ll` (medium+ severity) and picks up a new `[tool.bandit]` skip list in pyproject.toml with per-ID justifications for B101/B310/B404/B603/B607. - Fixed two real B108 findings by replacing hardcoded '/tmp/...' paths with `tempfile.gettempdir()` in cli_audit/bulk.py and cli_audit/upgrade.py — the cleanup path now actually matches tempfile.mkdtemp's location on systems where TMPDIR is non-default. - One documented shell=True in detection.py (catalog-sourced shell pipelines, never user input) gets an explicit `# nosec B602`. Signed-off-by: Sebastian Mendel --- .github/workflows/security.yml | 40 +++++++++++++++++++--------------- cli_audit/bulk.py | 4 +++- cli_audit/detection.py | 9 +++++--- cli_audit/upgrade.py | 3 ++- pyproject.toml | 11 ++++++++++ 5 files changed, 44 insertions(+), 23 deletions(-) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 12d80a3..4da2e8d 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -30,25 +30,25 @@ jobs: with: python-version: '3.14' - - name: Install pip-audit and bandit - run: | - python -m pip install --upgrade pip - pip install pip-audit bandit[toml] + - name: Install uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + + - name: Sync project dependencies + run: uv sync --all-extras --dev --frozen - # pip-audit reads pyproject.toml + uv.lock; fail only on known CVEs - - name: pip-audit (pyproject + uv.lock) - run: pip-audit --skip-editable + - name: pip-audit (via uv export) + run: | + uv export --format requirements-txt --no-hashes --no-emit-project > /tmp/requirements.txt + uv run --frozen pip-audit --requirement /tmp/requirements.txt - - name: bandit (static analysis) - run: bandit -r cli_audit -c pyproject.toml + - name: bandit (medium+ severity) + # Low-severity findings are mostly subprocess reminders on array-style + # calls we've already reviewed; fail only on medium or high. + run: uv run --frozen bandit -r cli_audit -ll -c pyproject.toml sbom: name: Generate SBOM (CycloneDX) runs-on: ubuntu-latest - permissions: - contents: read - id-token: write - attestations: write steps: - name: Harden runner uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 @@ -63,13 +63,17 @@ jobs: with: python-version: '3.14' - - name: Install cyclonedx-py - run: | - python -m pip install --upgrade pip - pip install cyclonedx-bom + - name: Install uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + + - name: Sync project dependencies (so cyclonedx-py sees the real set) + run: uv sync --all-extras --dev --frozen + + - name: Install cyclonedx-bom + run: uv run --frozen pip install cyclonedx-bom - name: Generate CycloneDX SBOM - run: cyclonedx-py environment --of JSON -o sbom.cdx.json + run: uv run --frozen cyclonedx-py environment --of JSON -o sbom.cdx.json - name: Upload SBOM artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/cli_audit/bulk.py b/cli_audit/bulk.py index 3b73aeb..25488b2 100644 --- a/cli_audit/bulk.py +++ b/cli_audit/bulk.py @@ -7,8 +7,10 @@ from __future__ import annotations +import os import shutil import subprocess +import tempfile import threading import time from concurrent.futures import ThreadPoolExecutor, as_completed @@ -350,7 +352,7 @@ def generate_rollback_script(results: Sequence[InstallResult], verbose: bool = F Path to generated rollback script """ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - script_path = f"/tmp/rollback_{timestamp}.sh" + script_path = os.path.join(tempfile.gettempdir(), f"rollback_{timestamp}.sh") with open(script_path, "w") as f: f.write("#!/bin/bash\n") diff --git a/cli_audit/detection.py b/cli_audit/detection.py index 1bc51cf..3520d2d 100644 --- a/cli_audit/detection.py +++ b/cli_audit/detection.py @@ -158,12 +158,15 @@ def get_version_line(path: str, tool_name: str, version_flag: str | None = None, Returns: Version line string or empty string """ - # Priority 1: If catalog specifies custom shell command, run it directly + # Priority 1: If catalog specifies custom shell command, run it directly. + # version_command comes from trusted catalog JSON (committed in-repo), never + # from user input — e.g. `uv python list --only-installed | grep … | sed …`. + # shell=True is required for the pipelines used in the catalog. if version_command: try: - proc = subprocess.run( + proc = subprocess.run( # nosec B602 version_command, - shell=True, + shell=True, # nosec B602 stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, stdin=subprocess.DEVNULL, diff --git a/cli_audit/upgrade.py b/cli_audit/upgrade.py index cdd5d95..2dd465d 100644 --- a/cli_audit/upgrade.py +++ b/cli_audit/upgrade.py @@ -562,7 +562,8 @@ def cleanup_old_backups(retention_days: int = 7, verbose: bool = False): """ import glob - backup_dirs = glob.glob("/tmp/upgrade_backup_*") + # Mirror the location used by create_upgrade_backup() (tempfile.mkdtemp). + backup_dirs = glob.glob(os.path.join(tempfile.gettempdir(), "upgrade_backup_*")) cutoff = time.time() - (retention_days * 86400) for backup_dir in backup_dirs: diff --git a/pyproject.toml b/pyproject.toml index 1bc7a1c..caef3f3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -134,3 +134,14 @@ strict_equality = true [[tool.mypy.overrides]] module = ["yaml.*", "pytest.*", "setuptools.*"] ignore_missing_imports = true + +[tool.bandit] +# This project wraps CLI tools — every `subprocess` call is intentional. +# B101 (assert_used): tests use assert; enforced elsewhere by pytest. +# B404/B603: we import subprocess and run it with list-form args on purpose. +# B607 (start_process_with_partial_path): we rely on PATH resolution for +# user-installed CLIs by design. +# B310 (urllib_urlopen): URLs are hardcoded https:// or come from the +# committed catalog; user input never reaches urlopen(). +skips = ["B101", "B310", "B404", "B603", "B607"] +exclude_dirs = ["tests", ".venv", "build", "dist"] From b7e14c47b08e953b51d02777a2bf52ed955ce639 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Fri, 17 Apr 2026 00:09:52 +0200 Subject: [PATCH 11/16] chore: address PR #75 review feedback (minor fixes) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - dependency-review.yml: grant `pull-requests: write` so the `comment-summary-in-pr` step can post the summary (Copilot). - pre-commit hooks: include `audit.py` in the flake8/isort/black globs alongside cli_audit/ and tests/ (gemini-code-assist × 3). - CHANGELOG: badge list now reflects reality — CI, Codecov, OpenSSF Scorecard, License (no CodeQL badge; default setup handles it). Signed-off-by: Sebastian Mendel --- .github/workflows/dependency-review.yml | 4 ++++ .pre-commit-config.yaml | 6 +++--- CHANGELOG.md | 6 +++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 08df612..209ee3b 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -11,6 +11,10 @@ jobs: dependency-review: name: Review dependency changes runs-on: ubuntu-latest + permissions: + contents: read + # comment-summary-in-pr posts a summary as a PR comment. + pull-requests: write steps: - name: Harden runner uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2418e56..74ab571 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,20 +20,20 @@ repos: rev: 7.3.0 hooks: - id: flake8 - files: ^(cli_audit|tests)/ + files: ^(cli_audit/|tests/|audit\.py$) - repo: https://github.com/PyCQA/isort rev: 8.0.1 hooks: - id: isort - files: ^(cli_audit|tests)/ + files: ^(cli_audit/|tests/|audit\.py$) args: ['--profile=black'] - repo: https://github.com/psf/black rev: 26.3.1 hooks: - id: black - files: ^(cli_audit|tests)/ + files: ^(cli_audit/|tests/|audit\.py$) - repo: https://github.com/koalaman/shellcheck-precommit rev: v0.11.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e94606..f5fd68a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,9 @@ and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0. ### Added - Governance files: `SECURITY.md`, `CODEOWNERS`, PR template, `CHANGELOG.md`. -- `.github/workflows/codeql.yml`, `scorecard.yml`, `dependency-review.yml` for supply-chain scanning. -- `.pre-commit-config.yaml` for local hook enforcement. -- README badges (CI, Codecov, License). +- `.github/workflows/scorecard.yml`, `dependency-review.yml`, and a dedicated `security.yml` (pip-audit + bandit + CycloneDX SBOM) for supply-chain scanning. CodeQL continues to run via GitHub's default code-scanning setup. +- `.pre-commit-config.yaml` for local hook enforcement (flake8, black, isort, shellcheck). +- README badges: CI, Codecov, OpenSSF Scorecard, License. - AGENTS.md structural sections (Commands, Setup, Testing, Architecture, Development). - Per-cycle `auto_update` storage for multi-version tools (`python@3.13` vs `python@3.14`). - Persistent endoflife.date cache at `~/.cache/cli-audit/endoflife.json` with fallback on HTTP failure. From 6c9f751616335685569009c7a12a8338c9e5aa97 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Fri, 17 Apr 2026 00:16:25 +0200 Subject: [PATCH 12/16] test(bulk): use tempfile.gettempdir() in rollback-script assertion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Paired fix for the B108 tempfile.gettempdir() change in bulk.py — the existing assertion hardcoded '/tmp/rollback_', which fails on macOS where tempfile.gettempdir() resolves to /var/folders/.../T/. Fixes macOS CI failure on PR #75. Signed-off-by: Sebastian Mendel --- tests/test_bulk.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_bulk.py b/tests/test_bulk.py index b813e44..31dca63 100644 --- a/tests/test_bulk.py +++ b/tests/test_bulk.py @@ -495,7 +495,9 @@ def test_generate_rollback_script_cargo(self): script_path = generate_rollback_script([result]) assert os.path.exists(script_path) - assert script_path.startswith("/tmp/rollback_") + # Use tempfile.gettempdir() — on macOS this is /var/folders/..., not /tmp. + expected_prefix = os.path.join(tempfile.gettempdir(), "rollback_") + assert script_path.startswith(expected_prefix) assert script_path.endswith(".sh") # Check script content From ab36fb20bc4c686b6cec80e881b6ad8e1ff766e5 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Fri, 17 Apr 2026 07:08:55 +0200 Subject: [PATCH 13/16] chore: revert governance/badge additions that don't fit reality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review feedback — all five items addressed: - Deleted SECURITY.md: the org-level netresearch/.github/SECURITY.md already defines the private-reporting flow (no email address) and applies to every netresearch repo. A repo-level copy is redundant. - Deleted .github/CODEOWNERS: referenced @netresearch/coding-agents which is not a real team. None of the existing netresearch teams fit this repo, so leave CODEOWNERS out rather than invent one. - Deleted .github/workflows/scorecard.yml + its README badge: the project isn't registered at scorecard.dev; the workflow would produce results nobody consumes and the badge would 404. - Dropped the Codecov badge: ci.yml already runs codecov-action but uploads fail silently with 'Token required because branch is protected' (no CODECOV_TOKEN secret configured). Badge was misleading — remove until the secret is wired up. - Reusable workflows: checked netresearch/typo3-ci-workflows and netresearch/.github; both only ship TYPO3/Composer-specific workflows (composer-audit etc.). No Python reusable workflow exists yet, so the two remaining new workflows (security.yml, dependency-review.yml) stay as direct-action workflows — matching the existing ci.yml and release.yml pattern. Signed-off-by: Sebastian Mendel --- .github/CODEOWNERS | 15 ------------ .github/workflows/scorecard.yml | 43 --------------------------------- CHANGELOG.md | 6 ++--- README.md | 2 -- SECURITY.md | 30 ----------------------- 5 files changed, 3 insertions(+), 93 deletions(-) delete mode 100644 .github/CODEOWNERS delete mode 100644 .github/workflows/scorecard.yml delete mode 100644 SECURITY.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 3ed5a49..0000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1,15 +0,0 @@ -# See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-security/customizing-your-repository/about-code-owners -# Order matters — the last matching rule wins. - -# Default reviewers for anything not matched below. -* @netresearch/coding-agents - -# Python package, audit, detection. -/cli_audit/ @netresearch/coding-agents -/audit.py @netresearch/coding-agents - -# Installer and upgrade orchestration. -/scripts/ @netresearch/coding-agents - -# CI, release, security automation. -/.github/ @netresearch/coding-agents diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml deleted file mode 100644 index c2d84e5..0000000 --- a/.github/workflows/scorecard.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: OpenSSF Scorecard - -on: - branch_protection_rule: - schedule: - - cron: '0 6 * * 1' - push: - branches: [main] - workflow_dispatch: - -permissions: read-all - -jobs: - analysis: - name: Scorecard analysis - runs-on: ubuntu-latest - permissions: - security-events: write - id-token: write - contents: read - actions: read - steps: - - name: Harden runner - uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 - with: - egress-policy: audit - - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - - name: Run analysis - uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 - with: - results_file: results.sarif - results_format: sarif - publish_results: true - - - name: Upload SARIF - uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 - with: - sarif_file: results.sarif diff --git a/CHANGELOG.md b/CHANGELOG.md index f5fd68a..52804ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,10 @@ and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0. ## [Unreleased] ### Added -- Governance files: `SECURITY.md`, `CODEOWNERS`, PR template, `CHANGELOG.md`. -- `.github/workflows/scorecard.yml`, `dependency-review.yml`, and a dedicated `security.yml` (pip-audit + bandit + CycloneDX SBOM) for supply-chain scanning. CodeQL continues to run via GitHub's default code-scanning setup. +- Governance files: PR template, `CHANGELOG.md`. Security reporting is covered by the [org-level SECURITY.md](https://github.com/netresearch/.github/blob/main/SECURITY.md). +- `.github/workflows/dependency-review.yml` and a dedicated `security.yml` (pip-audit + bandit + CycloneDX SBOM). CodeQL continues to run via GitHub's default code-scanning setup. - `.pre-commit-config.yaml` for local hook enforcement (flake8, black, isort, shellcheck). -- README badges: CI, Codecov, OpenSSF Scorecard, License. +- README badges: CI, License. - AGENTS.md structural sections (Commands, Setup, Testing, Architecture, Development). - Per-cycle `auto_update` storage for multi-version tools (`python@3.13` vs `python@3.14`). - Persistent endoflife.date cache at `~/.cache/cli-audit/endoflife.json` with fallback on HTTP failure. diff --git a/README.md b/README.md index b2169d9..46f7c5a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # AI CLI Preparation [![CI](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/ci.yml/badge.svg)](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/ci.yml) -[![codecov](https://codecov.io/gh/netresearch/coding_agent_cli_toolset/branch/main/graph/badge.svg)](https://codecov.io/gh/netresearch/coding_agent_cli_toolset) -[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/netresearch/coding_agent_cli_toolset/badge)](https://scorecard.dev/viewer/?uri=github.com/netresearch/coding_agent_cli_toolset) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 0b7306b..0000000 --- a/SECURITY.md +++ /dev/null @@ -1,30 +0,0 @@ -# Security Policy - -## Reporting a Vulnerability - -Please **do not** open a public issue for security-relevant findings. - -Use one of the following instead: - -- **Preferred:** [Privately report a vulnerability](https://github.com/netresearch/coding_agent_cli_toolset/security/advisories/new) via GitHub. -- Or email `security@netresearch.de` with details and steps to reproduce. - -You should receive an acknowledgement within 3 working days. We will confirm the -issue, agree on disclosure timelines with you, and publish a fix + GitHub -Security Advisory once the fix is available. - -## Scope - -In scope: code in this repository, published releases of `cli-audit`, the -installation / audit / upgrade scripts under `scripts/`, and anything that -would let an attacker execute code on or exfiltrate data from a machine that -runs `make upgrade` / `audit.py` against trusted upstream sources. - -Out of scope: vulnerabilities in third-party tools installed via the `install_*` -scripts (report those upstream), bugs that are only reachable by an attacker -with shell-level access to the machine running this toolkit. - -## Supported Versions - -Security fixes target the latest tagged release on the `main` branch. Older -tags do not receive backports. From bd79ff38d7221383133a2f19dd5f22d842d0755c Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Fri, 17 Apr 2026 07:34:57 +0200 Subject: [PATCH 14/16] ci: migrate security/dep-review/auto-merge to netresearch/.github reusables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review feedback: use reusable workflows from netresearch/.github instead of direct action calls (matching the node / Go projects). - security.yml → calls the new python-audit.yml (netresearch/.github#19, pinned to @feat/python-audit-workflow until that PR merges). Same three jobs (pip-audit, bandit, sbom) but centrally maintained. - dependency-review.yml → calls netresearch/.github's reusable dependency-review.yml, with fail-on-severity: moderate. - auto-merge-deps.yml → calls netresearch/.github's reusable auto-merge-deps.yml. The org version is identical to what we had locally; deduplicated. Signed-off-by: Sebastian Mendel --- .github/workflows/auto-merge-deps.yml | 34 ++--------- .github/workflows/dependency-review.yml | 23 ++------ .github/workflows/security.yml | 78 +++---------------------- 3 files changed, 19 insertions(+), 116 deletions(-) diff --git a/.github/workflows/auto-merge-deps.yml b/.github/workflows/auto-merge-deps.yml index 9fd8954..b14fb2e 100644 --- a/.github/workflows/auto-merge-deps.yml +++ b/.github/workflows/auto-merge-deps.yml @@ -1,35 +1,13 @@ name: Auto-merge dependency PRs on: - pull_request_target: - types: [opened, synchronize, reopened] + pull_request: -permissions: - contents: write - pull-requests: write +permissions: {} jobs: auto-merge: - runs-on: ubuntu-latest - if: >- - github.event.pull_request.user.login == 'dependabot[bot]' || - github.event.pull_request.user.login == 'renovate[bot]' - steps: - - name: Approve PR - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: gh pr review --approve "$PR_URL" - - - name: Enable auto-merge - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REPO: ${{ github.repository }} - run: | - STRATEGY=$(gh api "repos/$REPO" --jq ' - if .allow_squash_merge then "--squash" - elif .allow_merge_commit then "--merge" - elif .allow_rebase_merge then "--rebase" - else "--merge" end') - gh pr merge --auto "$STRATEGY" "$PR_URL" + uses: netresearch/.github/.github/workflows/auto-merge-deps.yml@main + permissions: + contents: write + pull-requests: write diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 209ee3b..18834ab 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -4,28 +4,13 @@ on: pull_request: branches: [main] -permissions: - contents: read +permissions: {} jobs: dependency-review: - name: Review dependency changes - runs-on: ubuntu-latest + uses: netresearch/.github/.github/workflows/dependency-review.yml@main permissions: contents: read - # comment-summary-in-pr posts a summary as a PR comment. pull-requests: write - steps: - - name: Harden runner - uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 - with: - egress-policy: audit - - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Dependency Review - uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 - with: - fail-on-severity: moderate - comment-summary-in-pr: true + with: + fail-on-severity: moderate diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 4da2e8d..82f6bc2 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -9,75 +9,15 @@ on: - cron: '0 6 * * 1' workflow_dispatch: -permissions: - contents: read +permissions: {} jobs: audit: - name: Python security audit - runs-on: ubuntu-latest - steps: - - name: Harden runner - uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 - with: - egress-policy: audit - - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: '3.14' - - - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 - - - name: Sync project dependencies - run: uv sync --all-extras --dev --frozen - - - name: pip-audit (via uv export) - run: | - uv export --format requirements-txt --no-hashes --no-emit-project > /tmp/requirements.txt - uv run --frozen pip-audit --requirement /tmp/requirements.txt - - - name: bandit (medium+ severity) - # Low-severity findings are mostly subprocess reminders on array-style - # calls we've already reviewed; fail only on medium or high. - run: uv run --frozen bandit -r cli_audit -ll -c pyproject.toml - - sbom: - name: Generate SBOM (CycloneDX) - runs-on: ubuntu-latest - steps: - - name: Harden runner - uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0 - with: - egress-policy: audit - - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: '3.14' - - - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 - - - name: Sync project dependencies (so cyclonedx-py sees the real set) - run: uv sync --all-extras --dev --frozen - - - name: Install cyclonedx-bom - run: uv run --frozen pip install cyclonedx-bom - - - name: Generate CycloneDX SBOM - run: uv run --frozen cyclonedx-py environment --of JSON -o sbom.cdx.json - - - name: Upload SBOM artifact - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: sbom-cyclonedx - path: sbom.cdx.json - retention-days: 90 + # Pinned to feat/python-audit-workflow until netresearch/.github#19 merges. + # Switch to @main after merge. + uses: netresearch/.github/.github/workflows/python-audit.yml@feat/python-audit-workflow + permissions: + contents: read + with: + python-version-file: pyproject.toml + package-manager: uv From 076be518a734e4467e386c30a7740ec5d1fc14ce Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Fri, 17 Apr 2026 07:34:57 +0200 Subject: [PATCH 15/16] ci: pass CODECOV_TOKEN to codecov-action; fix deprecated 'file' input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codecov uploads were silently failing on main with "Token required because branch is protected" because the action was invoked without a token. The repo has CODECOV_TOKEN configured (same as the other netresearch projects) — just needed to pass it through. Also renamed the deprecated 'file' input to 'files' — v6 of the action ignores 'file' and emits a warning. Signed-off-by: Sebastian Mendel --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a475f35..b6cfa98 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,7 +75,8 @@ jobs: - name: Upload coverage to Codecov uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 with: - file: ./coverage.xml + token: ${{ secrets.CODECOV_TOKEN }} + files: ./coverage.xml flags: unittests name: codecov-${{ matrix.os }}-py${{ matrix.python-version }} fail_ci_if_error: false From 59dbf1a7d5d9e524c2f4297e24d93361279be071 Mon Sep 17 00:00:00 2001 From: Sebastian Mendel Date: Fri, 17 Apr 2026 07:34:57 +0200 Subject: [PATCH 16/16] docs: restore CODEOWNERS and Codecov badge - CODEOWNERS: use real teams @netresearch/netresearch (catch-all + Python / scripts / CI owners) and @netresearch/typo3 (secondary reviewer, per org convention). - README: Codecov badge restored now that ci.yml actually uploads with CODECOV_TOKEN. Signed-off-by: Sebastian Mendel --- .github/CODEOWNERS | 15 +++++++++++++++ README.md | 1 + 2 files changed, 16 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..d21f26d --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,15 @@ +# See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-security/customizing-your-repository/about-code-owners +# Order matters — the last matching rule wins. + +# Default reviewers. +* @netresearch/netresearch @netresearch/typo3 + +# CI / release / security automation. +/.github/ @netresearch/netresearch + +# Python package + audit. +/cli_audit/ @netresearch/netresearch +/audit.py @netresearch/netresearch + +# Installer / upgrade shell scripts. +/scripts/ @netresearch/netresearch diff --git a/README.md b/README.md index 46f7c5a..816067d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # AI CLI Preparation [![CI](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/ci.yml/badge.svg)](https://github.com/netresearch/coding_agent_cli_toolset/actions/workflows/ci.yml) +[![codecov](https://codecov.io/gh/netresearch/coding_agent_cli_toolset/branch/main/graph/badge.svg)](https://codecov.io/gh/netresearch/coding_agent_cli_toolset) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)