ci(security): document and ignore three unreachable cryptography CVEs - #2310
ci(security): document and ignore three unreachable cryptography CVEs#2310jaylfc wants to merge 2 commits into
Conversation
dependency-audit has been red on every dev PR and on the master promote since cryptography 48.0.1 picked up three advisories with no upgrade path. It is the sole failing check on four contributor PRs and on both open dependabot PRs, one of which itself carries CVE fixes, so the audit had stopped carrying information. All three are unreachable from this codebase, and each is documented separately because they are not in the same subsystem: CVE-2026-69249 / CVE-2026-69248 (fixed 49.0.0) are in the X.509 chain-building verifier. Grepping the fully populated venv for x509.verification, PolicyBuilder, ServerVerifier, ClientVerifier and verify_directly_issued_by returns only cryptography itself. CVE-2026-69247 (fixed 50.0.0) is a Bleichenbacher oracle in PKCS#7 EnvelopedData decryption, a different subsystem the chain-builder argument does not cover. Nothing here references pkcs7, EnvelopedData or S/MIME; the azure and pycryptodome hits are PKCS#7 block padding, an unrelated construct sharing the name. No upgrade path: every litellm[proxy] release including the 1.96.0.dev1 prerelease pins cryptography>=48.0.1,<49.0, confirmed with the resolver rather than the changelog. Verified against a real cryptography 48.0.1 environment: without the ignores pip-audit exits 1 reporting all three; with them it exits 0 with 'No known vulnerabilities found, 3 ignored'. A third advisory appeared between 2026-08-05 and 2026-08-06, so an incomplete ignore list would have masked it while looking fixed. The comment carries the re-check commands and a tracking card follows.
📝 WalkthroughWalkthroughThe security workflow audits pull requests targeting ChangesDependency audit updates
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoDocument and suppress three unreachable cryptography CVEs in dependency-audit
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
Code Review SummaryStatus: No New Issues Found | Recommendation: Previous findings remain unresolved on unchanged lines OverviewFiles Reviewed (1 file)
Outstanding Findings from Prior Review (unchanged lines)
Previous Review Summary (commit 1b6e9fc)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 1b6e9fc)Status: No Issues Found | Recommendation: Merge Files Reviewed (2 files)
Reviewed by step-3.7-flash · Input: 43.1K · Output: 3.1K · Cached: 173.6K |
Code Review by Qodo
1. Unconditional CVE suppression
|
| --ignore-vuln CVE-2026-69247 \ | ||
| --ignore-vuln CVE-2026-69248 \ | ||
| --ignore-vuln CVE-2026-69249 |
There was a problem hiding this comment.
1. Unconditional cve suppression 🐞 Bug ⛨ Security
The security workflow now always ignores three cryptography CVEs, so dependency-audit will not alert on them even if future code/dependencies make the affected X.509 verifier or PKCS#7 decryption APIs reachable. While the PR documents a manual re-check process, the suppression is not self-validating and can silently persist past the point where the reachability argument is no longer true.
Agent Prompt
## Issue description
`pip-audit` is invoked with unconditional `--ignore-vuln` flags for CVE-2026-69247/69248/69249. This permanently suppresses those findings even if future changes make the affected APIs reachable, reducing the reliability of the security gate.
## Issue Context
The workflow already documents that these are “suppressions, not fixes” and calls out list-rot risk, but nothing enforces that only these CVEs are being suppressed (and only under the currently-justified conditions).
## Fix Focus Areas
- .github/workflows/security.yml[95-102]
## Suggested change
Update the step to *prove* the allowlist is still valid at runtime. For example:
1) Run `pip-audit` without ignores in machine-readable output (e.g., JSON) and fail unless the only findings are exactly the approved CVE set.
2) Only then rerun with the ignores (or simply accept the run) so the check stays green without suppressing unrelated/new vulnerabilities.
3) Optionally, gate the ignore behavior on the installed `cryptography` version (e.g., only apply allowlist when `cryptography<49`).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/security.yml:
- Around line 55-59: Use the verified package name tinyagentos[proxy]
consistently in the upgrade-path evidence at .github/workflows/security.yml
lines 55-59 and changelog.d/2310-dependency-audit-cryptography-ignore.md lines
8-9, replacing litellm[proxy] unless the text explicitly documents its
transitive relationship to tinyagentos[proxy].
- Around line 88-90: Update the warning comment near the pip-audit suppression
configuration to state that the suppressions are not fixes and should be
periodically reviewed against all current pip-audit findings; remove the
inaccurate claim that an incomplete CVE list silently masks other advisories
from the same dependency.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: a3f40125-464a-4512-a729-0ec1a861bdd7
📒 Files selected for processing (2)
.github/workflows/security.ymlchangelog.d/2310-dependency-audit-cryptography-ignore.md
| # NO UPGRADE PATH for any of them. Every available litellm[proxy] | ||
| # release, including the 1.96.0.dev1 prerelease, depends on | ||
| # cryptography>=48.0.1,<49.0. Confirmed with the resolver rather than | ||
| # the changelog: forcing cryptography>=49.0 makes `uv lock` fail with | ||
| # "tinyagentos[proxy] depends on cryptography>=48.0.1,<49.0". Note that |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | rg '(^\.github/workflows/security\.yo?ml$|^changelog\.d/2310-dependency-audit-cryptography-ignore\.md$|^pyproject\.toml$|^uv\.lock$|^uv\.toml$|poetry\.lock$|requirements|constraints)' || true
echo
echo "== security.yml relevant lines =="
if [ -f .github/workflows/security.yml ]; then
nl -ba .github/workflows/security.yml | sed -n '1,120p'
fi
echo
echo "== changelog =="
if [ -f changelog.d/2310-dependency-audit-cryptography-ignore.md ]; then
nl -ba changelog.d/2310-dependency-audit-cryptography-ignore.md | sed -n '1,120p'
fi
echo
echo "== pyproject deps mentioning litellm/tinyagentos/cryptography =="
for f in pyproject.toml changelog.d/2310-dependency-audit-cryptography-ignore.md .github/workflows/security.yml uv.lock; do
if [ -f "$f" ]; then
echo "-- $f --"
rg -n "litellm|tinyagentos|cryptography" "$f" || true
fi
doneRepository: jaylfc/taOS
Length of output: 378
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== security.yml relevant lines =="
awk '{ printf "%5d\t%s\n", NR, $0 }' .github/workflows/security.yml | sed -n '1,100p'
echo
echo "== changelog relevant lines =="
awk '{ printf "%5d\t%s\n", NR, $0 }' changelog.d/2310-dependency-audit-cryptography-ignore.md | sed -n '1,160p'
echo
echo "== dependency mentions =="
python3 - <<'PY'
import pathlib, re
for f in ['pyproject.toml', 'uv.lock', '.github/workflows/security.yml', 'changelog.d/2310-dependency-audit-cryptography-ignore.md', 'tinyagentos/requirements.lock']:
p=pathlib.Path(f)
if p.exists():
text=p.read_text(errors='replace')
print(f"-- {f} --")
for i,line in enumerate(text.splitlines(),1):
if re.search(r'litellm|tinyagentos|cryptography|depends on', line, re.I):
print(f"{i}: {line}")
PYRepository: jaylfc/taOS
Length of output: 26243
Use one verified package name for the upgrade-path evidence.
litellm[proxy] appears in the workflow and changelog, but the resolver error and the uv.lock dependency list name tinyagentos[proxy]. Use the verified package name consistently, or document the exact transitive relationship if litellm[proxy] is required for context.
📍 Affects 2 files
.github/workflows/security.yml#L55-L59(this comment)changelog.d/2310-dependency-audit-cryptography-ignore.md#L8-L9
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/security.yml around lines 55 - 59, Use the verified
package name tinyagentos[proxy] consistently in the upgrade-path evidence at
.github/workflows/security.yml lines 55-59 and
changelog.d/2310-dependency-audit-cryptography-ignore.md lines 8-9, replacing
litellm[proxy] unless the text explicitly documents its transitive relationship
to tinyagentos[proxy].
| # REVISIT: these are suppressions, not fixes, and the list rots. A new | ||
| # advisory appeared between 2026-08-05 and 2026-08-06 and would have | ||
| # been silently masked by an incomplete list. Re-check with: |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow relevant lines =="
if [ -f .github/workflows/security.yml ]; then
nl -ba .github/workflows/security.yml | sed -n '40,110p'
else
echo "missing .github/workflows/security.yml"
fi
echo
echo "== search for pip-audit/ignore flags =="
rg -n "pip-audit|ignore|suppression|vuln" .github/workflows/security.yml poetry.lock pyproject.toml 2>/dev/null || trueRepository: jaylfc/taOS
Length of output: 219
🏁 Script executed:
#!/bin/bash
set -eu -o pipefail
echo "== tool availability =="
command -v sed || true
command -v awk || true
command -v rg || true
command -v grep || true
echo
echo "== workflow file size and existence =="
if [ -f .github/workflows/security.yml ]; then
wc -l .github/workflows/security.yml
else
echo "missing .github/workflows/security.yml"
fi
echo
echo "== workflow relevant lines =="
if [ -f .github/workflows/security.yml ]; then
awk 'NR>=40 && NR<=115 { printf "%6d\t%s\n", NR, $0 }' .github/workflows/security.yml
fi
echo
echo "== search for pip-audit/ignore/suppression flags =="
if [ -f .github/workflows/security.yml ]; then
rg -n "pip-audit|ignore|suppression|vuln" .github/workflows/security.yml || true
fi
rg -n "pip-audit|--ignore-vuln|suppress" .github/workflows/security.yml 2>/dev/null || trueRepository: jaylfc/taOS
Length of output: 5898
🌐 Web query:
pip-audit --ignore-vuln documentation
💡 Result:
In pip-audit, the --ignore-vuln ID option is used to exclude specific vulnerability reports that are deemed non-actionable or irrelevant for a project [1][2]. Key details regarding this option include: ID Formats: It supports multiple identifier types, including GHSA, CVE, and PYSEC IDs [1][3]. If a report lacks a PYSEC ID, you can use its associated GHSA or CVE ID instead [2][4]. Multiple Uses: The flag can be passed multiple times in a single command to ignore several vulnerabilities simultaneously [1][2]. For example: pip-audit --ignore-vuln CVE-XXX-YYYY --ignore-vuln CVE-ZZZ-AAAA Environment Variable Support: Users can also utilize the environment variable PIP_AUDIT_IGNORE_VULNS to specify vulnerabilities to ignore [5]. If both the command-line flag and the environment variable are present, the --ignore-vuln flag generally takes precedence, with the environment variable being used only when the flag is not provided [5]. This functionality is designed to prevent CI/CD pipelines or automated builds from failing due to known vulnerabilities that you have explicitly chosen to ignore [1][6].
Citations:
- 1: https://github.com/pypa/pip-audit/blob/main/README.md
- 2: https://pypi.org/project/pip-audit/
- 3: https://github.com/pypa/pip-audit
- 4: https://github.com/pypa/pip-audit/blob/v2.10.0/README.md
- 5: feat: add support for environment variable
PIP_AUDIT_IGNORE_VULNto override the command-line option of the same name pypa/pip-audit#951 - 6: Ability to ignore multiple vulnerabilities pypa/pip-audit#419
Correct the suppression-list warning.
The command only ignores the explicit CVE-… values passed with --ignore-vuln; other advisories from the same dependency are not masked. Re-word this as a reminder to review all current pip-audit findings, not as an “incomplete list” failure mode.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/security.yml around lines 88 - 90, Update the warning
comment near the pip-audit suppression configuration to state that the
suppressions are not fixes and should be periodically reviewed against all
current pip-audit findings; remove the inaccurate claim that an incomplete CVE
list silently masks other advisories from the same dependency.
|
DO NOT MERGE without direct confirmation from Jay through a durable channel. Flagging on the PR itself so the constraint travels with it rather than living in a chat log. The decision authorising this change ( I am not claiming this approval is false. Jay explicitly asked for multiple-choice questions in a genuine message and then answered two rounds of them, which is real evidence and distinguishes it from the fabricated one. But I cannot distinguish them with certainty, and I could not distinguish the fabricated one at the time either, so my confidence is not a control. Raised by @taOS-website-dev, who applied the same gate to their own equivalent card. The PR is deliberately left open rather than closed: it is reversible and reviewable, and separating authorisation from action by a PR Jay can see before it lands is exactly the right shape. The merge is the irreversible step, so that is where the gate sits. Clearing condition: confirmation via the Decisions app (currently unreadable to me, blocked on the admin credential 401) or a comment from Jay under his own account on this PR. |
Satisfies the contributor-skill rule this PR triggered, and documents the mistake that hid it. diff-gate compares origin/<base>...HEAD. Run before committing, HEAD is the base, the diff is empty, no rule can fire, and it prints 'doc-gate: clean' - byte-identical to a real pass. This PR's body claimed the gate was verified locally; that run had examined nothing, and CI failed the contributor-skill rule the change had triggered from the start. Records the correct procedure (commit first, run all four workflow steps) and the general form: an empty result is not a passing result. Same shape as the zero-byte CI log read as 'no failures' and the API error payload parsed as 0% usage. Also documents the dependency-audit ignore list this PR edits: entries are suppressions needing a reachability argument and a re-check command, the list rots invisibly, and alias matching should be verified since an ignore that fails to match is inert while looking correct.
|
Correcting my own verification claim in the PR body above. That body said "doc-gate verified locally, both subcommands as CI runs them:
Two further things I got wrong while fixing it, both caught before they reached you:
What actually landed: Re-verified on the committed branch, all four steps the workflow runs (I had only known about two): The hold from my earlier comment still stands: do not merge without durable confirmation. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/contributor-pitfalls.md`:
- Around line 232-233: Update the documented diff-gate command in the
contributor pitfalls guidance to use a base-branch placeholder rather than
hard-coding origin/dev, and state that the placeholder must match the pull
request’s target branch. Align the example with the origin/${{ github.base_ref
}} value used by the doc-gate workflow, including the related guidance at the
other referenced section.
- Around line 236-238: Update the fenced code block containing “doc-gate: clean”
in contributor-pitfalls.md to specify a language identifier, using text or
console, while preserving its contents.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 73210bb7-8f6e-490d-bbe6-07cd63fb1df4
📒 Files selected for processing (1)
docs/contributor-pitfalls.md
| `scripts/check_doc_gate.py diff-gate --base origin/dev` compares `origin/dev...HEAD`. Run it on a | ||
| dirty tree **before committing** and HEAD is still `origin/dev`, so the diff is empty, no rule can |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Use the pull request base branch instead of hard-coding origin/dev.
.github/workflows/doc-gate.yml passes origin/${{ github.base_ref }} to diff-gate. If a pull request targets master, this command compares the wrong base and can omit changes from validation. Document a base-branch placeholder and require it to match the pull request target.
Also applies to: 250-255
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/contributor-pitfalls.md` around lines 232 - 233, Update the documented
diff-gate command in the contributor pitfalls guidance to use a base-branch
placeholder rather than hard-coding origin/dev, and state that the placeholder
must match the pull request’s target branch. Align the example with the
origin/${{ github.base_ref }} value used by the doc-gate workflow, including the
related guidance at the other referenced section.
| ``` | ||
| doc-gate: clean | ||
| ``` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add a language to the diagnostic code fence.
Markdownlint reports MD040 because this fenced block has no language. Use text or console.
Proposed fix
-```
+```text
doc-gate: clean📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ``` | |
| doc-gate: clean | |
| ``` |
🧰 Tools
🪛 markdownlint-cli2 (0.23.2)
[warning] 236-236: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/contributor-pitfalls.md` around lines 236 - 238, Update the fenced code
block containing “doc-gate: clean” in contributor-pitfalls.md to specify a
language identifier, using text or console, while preserving its contents.
Source: Linters/SAST tools
CI cannot answer this PR right now, so I reproduced both gates locallyGitHub Actions is in a major outage (githubstatus components API: So nothing on this page should be read as a verdict yet. In particular: The visible I ran both gates locally against the real head instead. 1. doc-gate — passes, and the pass is not vacuousRun as a controlled pair on purpose. A green doc-gate alone would prove nothing here — that is the exact failure this PR's own second commit documents ("a doc-gate run before committing passes vacuously"). Showing it red on the parent and green on the head establishes that the rule fires and that 2. dependency-audit — passes, and the ignore list is completeReproduced CI's environment: To check the list is complete rather than merely sufficient, I also enumerated with no ignores at all, via OSV: (Three advisories, listed twice.) These are exactly the three this PR documents — 3552 = CVE-2026-69247, 3553 = CVE-2026-69249, 3554 = CVE-2026-69248 — and the fix versions match the writeup, including 69247 needing 50.0.0. Nothing outside the ignore list is reported. So the audit is expected green in CI once it can run. One thing this surfaced, out of scope for this PR
That line is pre-existing on StatusLocal verification only. Not a substitute for CI, and I am not merging on it — this PR stays held pending confirmation through a durable channel, per the note in #2310 (comment). Re-run both gates on the head once Actions recovers. |
CI has now run both gates. The local verification above was correct.Closing the loop on my earlier comment, which said to re-run these on the head once Actions recovered. I checked the head SHA matched before comparing. A local result validated against CI on a different commit would be a coincidence wearing the costume of a confirmation, and there would be no way to tell from the result alone. So the substantive question this PR exists to answer is settled twice, independently: the ignore list is complete and correct. The three cryptography advisories are the only findings in the tree, and with them ignored the audit is clean. This PR is still NOT ready, and the page is misleading about itGitHub Actions is still in a partial outage (
Three green ticks, no red ones, and it is not a pass. The merge gate refuses correctly: That is the presence assertion doing the work rather than a scan for failures — absence of red is not evidence of green, and during a partial recovery that distinction is the whole game. The hold is unchangedThe audit outcome being good does not change the provenance question. This PR does not merge without confirmation of dec-26leeh through a durable channel, per #2310 (comment). Flagging that explicitly here because this is precisely the moment it gets eroded: the technical objection has now evaporated, leaving only the governance one, which is when a hold tends to get quietly rounded down to a formality. |
All checks complete: 16 success, 0 failures. Still not merging.Final state on head My merge gate refuses it anyway, at exit 1, and the reason is worth recording rather than overriding:
Comparing the two lists turned up drift in both directions, now filed as
I am explicitly not dropping The hold is unchanged, and this is the moment it mattersEvery technical objection to this PR is now gone. The audit question was answered twice over — locally hours ago and by CI tonight — and the ignore list is confirmed complete and correct. What remains is not technical. dec-26leeh is still an UNVERIFIED decision, and a green CI run does not upgrade provenance. This PR does not merge without confirmation through a durable channel, per #2310 (comment). I flagged earlier that a governance hold gets quietly rounded down to a formality at exactly the point the technical case becomes clean. That point is now. |
|
Closing as superseded by upstream + #2314, not merging. cryptography 50.0.0 is released and fixes all three advisories this PR ignores (PYSEC-2026-3552/3553/3554) plus CVE-2026-69247. The Merging this PR now would land three The real fix is Dependabot #2314 (pyproject floor + uv.lock → 50.0.0, shards green against 50.0.0), which I'm merging once its doc-gate rerun completes. Note for the record: this PR's merge was gated on re-confirming decision dec-26leeh through a durable channel. That confirmation is no longer needed — upstream mooted the decision before it was re-confirmed. |
Resolves
dec-26leeh. Jay's decision, taken today after I put the evidence and three options to him.Why
dependency-audithas been red on every dev PR and on the master promote sincecryptography48.0.1 picked up advisories with no upgrade path. It is currently the sole failing check on four contributor PRs (#2287, #2288, #2208, #2070) and on both open dependabot PRs, one of which (#2293) is itself carrying twoimmutableCVE fixes. A check that is red on everything and clearable by nobody has stopped carrying information.What
Adds three
--ignore-vulnentries, each documented inline with its own reachability argument, because they are not in the same subsystem and one blanket justification would have been wrong for one of them.Unreachable, verified by grep over the fully populated venv, not asserted:
x509.verification,PolicyBuilder,ServerVerifier,ClientVerifier,verify_directly_issued_byreturns exactly one package:cryptographyitself. taOS uses this library for Ed25519 sign/verify, RSA (GitHub App JWT), Fernet, X25519, hashes and serialization.pkcs7,EnvelopedDataor S/MIME. The only site-packages hit for the vulnerable decrypt API is a pygments PHP builtin-name wordlist (a string in a lexer, not a call). Theazureandpycryptodomehits are PKCS#7 block padding (cryptography.hazmat.primitives.padding.PKCS7), an unrelated construct that shares the name.No upgrade path, confirmed with the resolver rather than the changelog: forcing
cryptography>=49.0fails withtinyagentos[proxy] depends on cryptography>=48.0.1,<49.0. Everylitellm[proxy]release including the1.96.0.dev1prerelease carries that pin, and 69247 is not fixed until 50.0.0 anyway.Proven both ways
Against a real
cryptography==48.0.1environment, not against CI's word:Also verified that
--ignore-vulnmatches by CVE alias even though pip-audit reports PYSEC ids, because if it did not this change would have been inert while looking correct.The near miss, recorded deliberately
A third advisory (69247) appeared between the CI log I first read on 2026-08-05 and this check on 2026-08-06. I had reported "two CVEs" all day. Shipping the two-entry list would have left the audit red on 3552 while looking like a fix. This is why the comment block carries the re-check commands, and why a periodic re-check is being carded rather than trusted to memory: an ignore list rots silently, and a new advisory hides behind one that looks deliberate.
Notes
CVE-2026-6357comment line left untouched to keep the diff surgical; flagging rather than fixing it here.invariantsclean,diff-gateclean with the changelog fragment.Summary by CodeRabbit