From 682e7f688ff924f509e84d82719f4eb163559433 Mon Sep 17 00:00:00 2001 From: Hugo Date: Fri, 25 Sep 2026 00:35:06 +0200 Subject: [PATCH] chore: release 0.7.0 --- CHANGELOG.md | 4 ++-- docs/usage.md | 2 +- pyproject.toml | 2 +- src/coretrace_python/__init__.py | 2 +- tests/test_release.py | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a627734..cb31dc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,13 @@ # Changelog -## Unreleased +## 0.7.0 (2026-09-25) ### Precision - A dominating guard makes a flow a hotspot only when it examines what the sink receives. `if request.method == 'POST':` before `request.POST['cmd']` no longer lowers a vulnerability to a hotspot. A test of the value itself, of the same attribute, of a method called on it (`form.is_valid()`), or of any part of an object the flow passes whole still does. The regression snapshots record the verdict of each taint finding (#135). -- Django's `csrf.get_token` returns a token of letters and digits whatever the request holds, and `reverse`/`reverse_lazy` build a local path that attacker data in their arguments or query cannot turn into another host: the first is no longer an injection, the second no longer an open redirect. `reverse` still carries other kinds, since it leaves `'` unquoted (#132). - The SSRF sinks of Requests and httpx read the destination only: the URL (the first argument, the second after the method for `request` and `stream`, or `url=`) or the prepared request `send` takes. Attacker data in the body, the JSON, the headers or the query parameters is no longer a server-side request forgery. `Sink` gains `keywords` next to `positions`, and function summaries keep the name of each keyword argument, so a project function forwarding `url=` still reaches the sink; the cache format is bumped (#128). - `render_to_string` escapes what it renders where the analyzer can establish it: on a directory check, it reads the project's Django templates, and a template escapes when neither it nor what it extends or includes marks output safe, uses a tag, filter or library beyond Django's own, or prints a variable where HTML escaping does not protect it, and no settings turn autoescaping off. Data reaching a response through such a template is no longer `xss`; any other template keeps the flow reported. `TemplateRender` declares such rendering calls, and the escaped templates are part of the cache key (#130). +- Django's `csrf.get_token` returns a token of letters and digits whatever the request holds, and `reverse`/`reverse_lazy` build a local path that attacker data in their arguments or query cannot turn into another host: the first is no longer an injection, the second no longer an open redirect. `reverse` still carries other kinds, since it leaves `'` unquoted (#132). ## 0.6.0 (2026-09-24) diff --git a/docs/usage.md b/docs/usage.md index d478584..13f9d46 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -235,7 +235,7 @@ the directory of the checked file; a path outside it is printed as it is. ```json { "schema_version": 1, - "tool": {"name": "coretrace-python-analyzer", "version": "0.6.0"}, + "tool": {"name": "coretrace-python-analyzer", "version": "0.7.0"}, "root": "/home/me/project", "findings": [ { diff --git a/pyproject.toml b/pyproject.toml index faa7968..c30de4e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "coretrace-python-analyzer" -version = "0.6.0" +version = "0.7.0" description = "Static security analysis infrastructure for Python code" readme = "README.md" requires-python = ">=3.11" diff --git a/src/coretrace_python/__init__.py b/src/coretrace_python/__init__.py index 55edef6..5a37375 100644 --- a/src/coretrace_python/__init__.py +++ b/src/coretrace_python/__init__.py @@ -1,4 +1,4 @@ """CoreTrace's Python static analysis frontend.""" -__version__ = "0.6.0" +__version__ = "0.7.0" diff --git a/tests/test_release.py b/tests/test_release.py index 9c827df..64d368b 100644 --- a/tests/test_release.py +++ b/tests/test_release.py @@ -30,7 +30,7 @@ def require_changelog() -> None: def test_the_version_is_declared_once_and_mirrored() -> None: project = tomllib.loads((REPO / "pyproject.toml").read_text(encoding="utf-8"))["project"] - assert project["version"] == coretrace_python.__version__ == "0.6.0" + assert project["version"] == coretrace_python.__version__ == "0.7.0" def test_the_changelog_starts_with_the_current_version() -> None: