diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f1cc67..ade6209 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,66 @@ All notable changes to **signetry-core** are documented here. The format follows [Semantic Versioning](https://semver.org/). Until `1.0.0` the public API may change between minor versions. +## [0.7.0] — 2026-08-18 + +### Added — detection breadth + +- **Kotlin** (`.kt`/`.kts`) is now scanned at all. It was absent from the extension + map, so a Kotlin service or Android app scanned clean regardless of contents. + `kotlin.sql_injection` (CWE-89) and `kotlin.command_injection` (CWE-78) match + both the `$var`/`${var}` interpolation idiom — which the Java concat-only + patterns miss entirely — and `+` concatenation. (#52, #93) +- **Go SSRF** — `go.taint.ssrf` (CWE-918): `http.Get/Head/Post/PostForm`, + `*Client.Do`, `http.NewRequest`. (#95) +- **Go and Java path traversal** — `go.taint.path_traversal` / + `java.taint.path_traversal` (CWE-22). The Java pattern accepts a qualified + prefix, so `new java.io.FileInputStream(...)` matches, not only the imported + short form. (#95) +- **PHP XXE** — `php.xxe` (CWE-611), keyed on `LIBXML_NOENT`/`LIBXML_DTDLOAD` or + `libxml_disable_entity_loader(false)`. Since PHP 8 / libxml 2.9 external + entities are off by default, parsing untrusted XML is not itself the bug — + explicitly re-enabling entities is. (#95) +- `SinkSpec.skip_if` — an optional negative guard for taint sinks where a tainted + identifier *on the line* does not imply taint *in the dangerous position*. (#97) + +### Added — executors + +- **`AiderExecutor`**, registered as `aider`. Fail-closed on both + `SIGNETRY_ENABLE_AIDER=true` and the CLI responding. Commit authority stays with + the pipeline (`--no-auto-commits`, `--no-dirty-commits`), shell suggestion is + disabled, read-only runs use `--dry-run`, and the prompt is redacted from the + replay command. Ported from @adity982's #55, which predated the + `umbra_core` → `signetry_core` rename and could no longer be rebased. (#53, #96) + +### Fixed — SSRF precision + +- The Python SSRF rule now resolves the URL argument independently for keyword and + positional forms. `requests.request` was previously checked at `args[0]` — the + HTTP *method* — making that target effectively dead for positional calls. Adds + `httpx` put/patch/delete/head/options/request and `urllib.request` coverage. + Thanks @AdvaitVarhade. (#86, #89) +- `urllib.request.Request` removed from the SSRF sink list: taint already + propagates to the `urlopen` sink, so listing the constructor reported one + vulnerability twice on adjacent lines, where the `(file, line, category)` dedup + cannot collapse it. (#94) +- A constant host with a tainted query string is no longer reported as Go SSRF. + `http.Get("https://api.example.com/search?q=" + q)` pins the destination, so it + is not SSRF — while `http.Get("https://" + userHost)` still is, because the + attacker controls the host. (#97) + +### Fixed — CI + +- The advisory reviewer **could never comment on a fork PR**. Fork PRs get a + read-only `GITHUB_TOKEN` regardless of the `permissions:` block, so + `pull-requests: write` was silently dropped and the comment call returned 403 — + every outside contribution showed a red `review` check. Split into an untrusted + job (no write permission, uploads an artifact) and a trusted `workflow_run` job + that posts it and never executes PR code. Deliberately not `pull_request_target`. + (#92) +- The advisory review step's `exit 0 # never fail the PR` had never run: GitHub + invokes `run:` steps as `bash -e`, so a non-zero exit from the reviewer aborted + the step first and any Block verdict turned the check red. (#92) + ## [0.6.0] — 2026-08-12 ### Naming diff --git a/README.md b/README.md index cfe86e4..865e957 100644 --- a/README.md +++ b/README.md @@ -62,12 +62,12 @@ One core (`run_admission`), five checkpoints an agent's change must pass through ```bash # Source-available (not on PyPI). Install from the source repo: -pip install "signetry-core @ git+https://github.com/Signetry/core@v0.6.0" +pip install "signetry-core @ git+https://github.com/Signetry/core@v0.7.0" ``` | Surface | Governs | Command | |---|---|---| -| **Source install** | anything you script | `pip install "signetry-core @ git+https://github.com/Signetry/core@v0.6.0"` | +| **Source install** | anything you script | `pip install "signetry-core @ git+https://github.com/Signetry/core@v0.7.0"` | | **CLI + git hook** | the agent on your machine | `signetry admit . --mission "..." --agent claude-code` | | **Detection scan** | find vulns in any repo (7 languages) + govern the fix | `signetry scan . --sarif` · `signetry scan . --fix` | | **GitHub Action** | **every** agent's PR (Claude Code, Codex, Cursor, Copilot, Devin) | [Marketplace: Signetry Admission](https://github.com/marketplace/actions/signetry-admission) · [`@v1`](https://github.com/Signetry/action) | diff --git a/docs/INTEGRATIONS.md b/docs/INTEGRATIONS.md index 472c47b..5dc258d 100644 --- a/docs/INTEGRATIONS.md +++ b/docs/INTEGRATIONS.md @@ -14,7 +14,7 @@ Codex, Cursor, Copilot, Devin, or a human, identically. ```bash # source-available (All Rights Reserved); not on PyPI — install from source -pip install "signetry-core @ git+https://github.com/Signetry/core@v0.6.0" +pip install "signetry-core @ git+https://github.com/Signetry/core@v0.7.0" ``` ```python @@ -75,7 +75,7 @@ status check* in branch protection and nothing merges without a receipt. ## 4. MCP server (agents call governance themselves) ```bash -pip install "signetry-core[mcp] @ git+https://github.com/Signetry/core@v0.6.0" +pip install "signetry-core[mcp] @ git+https://github.com/Signetry/core@v0.7.0" python -m signetry_core.mcp_server # stdio transport ``` diff --git a/docs/LAUNCH.md b/docs/LAUNCH.md index 3fff971..f5e87a2 100644 --- a/docs/LAUNCH.md +++ b/docs/LAUNCH.md @@ -34,7 +34,7 @@ provenance. Make it a required status check and nothing merges without a receipt `auto_merge` is always false — a human merges. Agent-agnostic; **source-available** (All Rights Reserved — not open source), -installed from source (`pip install "signetry-core @ git+https://github.com/Signetry/core@v0.6.0"`). +installed from source (`pip install "signetry-core @ git+https://github.com/Signetry/core@v0.7.0"`). On the GitHub Marketplace: https://github.com/marketplace/actions/signetry-admission @@ -96,7 +96,7 @@ jobs: Live demo — a permitted change passes, a forbidden `deploy.yml` edit is blocked: https://github.com/Signetry/autofix-demo/pulls -Also usable as a CLI (`pip install "signetry-core @ git+https://github.com/Signetry/core@v0.6.0"` +Also usable as a CLI (`pip install "signetry-core @ git+https://github.com/Signetry/core@v0.7.0"` → `signetry admit`), a git pre-push hook, an MCP server, or a Python library. Source-available (All Rights Reserved — not open source). diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 84c6682..307eb93 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -4,7 +4,7 @@ signetry-core is **source-available** (All Rights Reserved) and is **not publish PyPI** — it is distributed and installed **from source by tag**: ```bash -pip install "signetry-core @ git+https://github.com/Signetry/core@v0.6.0" +pip install "signetry-core @ git+https://github.com/Signetry/core@v0.7.0" ``` Pushing a version tag runs [`.github/workflows/release.yml`](.github/workflows/release.yml), diff --git a/docs/site/index.md b/docs/site/index.md index 732b470..6c38095 100644 --- a/docs/site/index.md +++ b/docs/site/index.md @@ -33,7 +33,7 @@ false — a human merges. ```bash # source-available (All Rights Reserved); not on PyPI — install from source -pip install "signetry-core @ git+https://github.com/Signetry/core@v0.6.0" +pip install "signetry-core @ git+https://github.com/Signetry/core@v0.7.0" ``` - Source (install from here): diff --git a/docs/site/quickstart.md b/docs/site/quickstart.md index f40b0dd..28755c8 100644 --- a/docs/site/quickstart.md +++ b/docs/site/quickstart.md @@ -4,7 +4,7 @@ ```bash # source-available (All Rights Reserved); not on PyPI — install from source -pip install "signetry-core @ git+https://github.com/Signetry/core@v0.6.0" +pip install "signetry-core @ git+https://github.com/Signetry/core@v0.7.0" signetry completion zsh >> ~/.zshrc # optional: shell completion (bash | zsh | fish) ``` diff --git a/pyproject.toml b/pyproject.toml index c428f39..79ce0c6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "signetry-core" -version = "0.6.0" +version = "0.7.0" description = "An agent-agnostic change-control plane for coding agents. Governs Codex, Claude Code, Cursor, or any agent behind one admission pipeline and proves every change with a signed receipt." readme = "README.md" requires-python = ">=3.11" diff --git a/uv.lock b/uv.lock index 031295a..d3967ef 100644 --- a/uv.lock +++ b/uv.lock @@ -1258,7 +1258,7 @@ wheels = [ [[package]] name = "signetry-core" -version = "0.6.0" +version = "0.7.0" source = { editable = "." } dependencies = [ { name = "cryptography" },