Skip to content

Release v1.17.0 - #398

Merged
erikdarlingdata merged 10 commits into
mainfrom
dev
Jul 25, 2026
Merged

Release v1.17.0#398
erikdarlingdata merged 10 commits into
mainfrom
dev

Conversation

@erikdarlingdata

Copy link
Copy Markdown
Owner

Release v1.17.0. Merging this triggers release.yml: builds and publishes win-x64, linux-x64, osx-x64, and osx-arm64, signs the Windows build via SignPath, packs and uploads Velopack, builds the SSMS VSIX, and publishes it to the SSMS Gallery.

Security

CVE-2025-6965 (High, GHSA-2m69-gcr7-jv3q) - server/PlanShare pulled SQLitePCLRaw.lib.e_sqlite3 2.1.11 transitively (SQLite < 3.50.2 memory corruption). Pinned to 2.1.12.

This does not remediate the running PlanShare server. PlanShare is excluded from CI by paths-ignore, is not in PlanViewer.sln, and no workflow deploys it. The fix is in source only; the deployed instance needs a separate manual deploy.

MCP DNS rebinding. ListenLocalhost does not prevent a malicious web page from rebinding a DNS name it controls to 127.0.0.1 and reaching the MCP server same-origin (CORS never applies), then calling get_connections / get_query_store_top / get_plan_xml to exfiltrate saved server names, query text, and plan XML. Added a Host/Origin loopback guard ahead of MapMcp(). Runtime-verified against the running app: rebound Host 403, hostile Origin 403, legitimate loopback handshake 200.

Generated T-SQL hardened. Untrusted plan XML could splice statements into the sp_executesql batch the app executes (ReproScriptBuilder), and scripted DDL did not double embedded ] in identifiers, so an object named x] ; <T-SQL> -- produced a script that ran attacker SQL when copied and executed (DdlScripter). Both closed, with tests.

Maintenance

  • 9 patch/minor dependency bumps; dotnet list package --deprecated is now empty (removed the unused, deprecated Avalonia.Diagnostics)
  • Zero-warning build restored - drag/drop migrated to Avalonia's DataTransfer API after 11.3.18 obsoleted the old one
  • 5 GitHub Actions bumped to current majors
  • Tests 182 -> 202

Tooling

Adds Claude Code PR review workflows (#396). These activate with this merge: the action refuses to run unless the workflow file is byte-identical on the default branch, so they have been inert until now.

Not included

PR #388 (Repl pilot) remains open and is deliberately not part of this release.

Verification

  • Clean Release build of the merged result: 0 warnings
  • 202/202 tests pass in Release
  • Version at 1.17.0 in all of Directory.Build.props, source.extension.vsixmanifest, AssemblyInfo.cs, CITATION.cff
  • vsixmanifest matches, so the VSIX version-mismatch warning in release.yml will not fire
  • vpk CLI pin (1.2.0) matches the Velopack PackageReference
  • main is at 1.16.0, so check-version-bump passes

🤖 Generated with Claude Code

erikdarlingdata and others added 10 commits July 25, 2026 10:37
Dependencies:
- PlanShare: Microsoft.Data.Sqlite 10.0.9 -> 10.0.10, add direct
  SQLitePCLRaw.bundle_e_sqlite3 2.1.12 to clear CVE-2025-6965
  (GHSA-2m69-gcr7-jv3q, High) - Microsoft.Data.Sqlite still floors
  the transitive at the vulnerable 2.1.11
- Avalonia 11.3.17 -> 11.3.18 (in-line; ScottPlot.Avalonia stays 5.1.58,
  the last Avalonia 11 build - 5.1.59+ requires Avalonia 12)
- Microsoft.Data.SqlClient 7.0.1 -> 7.0.2, Extensions.Azure 1.0.0 -> 7.0.2
  (version-scheme alignment with SqlClient)
- ScriptDom 180.37.3 -> 180.59.2, ModelContextProtocol 1.4.0 -> 1.4.1,
  System.CommandLine 2.0.9 -> 2.0.10, AspNetCore WASM 10.0.9 -> 10.0.10,
  Test.Sdk 18.6.0 -> 18.8.1
- Remove redundant Microsoft.Win32.Registry (in-box on net10.0, NU1510)

Warnings (restore zero-warning build):
- Migrate drag/drop to the DataTransfer API (DragEventArgs.Data and
  DataFormats.Files are obsolete in Avalonia 11.3.18, CS0618 x6)

CI:
- actions/checkout v5 -> v7, setup-dotnet v5 -> v6, upload-artifact
  v6 -> v7, upload-pages-artifact v3 -> v5, deploy-pages v4 -> v5

Validated: clean Debug build 0 warnings, 182/182 tests pass,
linux-x64 + osx-arm64 publish smoke OK (SkiaSharp natives present).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
From the maintenance pass security review of the diff since the last
pass (f57fad8). Findings triaged against the single-user-laptop
calibration: fixes the one remotely-reachable vector and the two
generated-SQL escaping gaps.

HIGH - MCP DNS rebinding (McpHostService.cs):
Kestrel listens on loopback, but nothing validated Host/Origin, so a
malicious page could rebind a DNS name it controls to 127.0.0.1 and
reach the server same-origin (CORS never applies), then call
get_connections / get_query_store_top / get_plan_xml to exfiltrate
saved server names, query text, and plan XML. Added middleware ahead
of MapMcp that 403s any non-loopback Host, and any present Origin
that is not a loopback origin.
Verified at runtime: rebound Host -> 403, hostile Origin -> 403,
legitimate loopback initialize -> 200 with full server handshake.

MEDIUM - plan-derived parameters spliced into an executed batch
(ReproScriptBuilder.cs): parameter names, types, and compiled values
come straight off untrusted plan XML and landed raw in the generated
EXECUTE sys.sp_executesql, which the app runs and the get_repro_script
MCP tool serves. A crafted .sqlplan with
ParameterCompiledValue="1; <T-SQL> --" escaped the parameterization.
Now names/types must match a plain identifier/type pattern or the
parameter is dropped, and values must be a single self-contained
literal (NULL, number, 0x binary, or a fully-quoted string) or they
fall through to the existing ? placeholder.

MEDIUM - identifier escaping in scripted DDL (DdlScripter.cs,
SchemaQueryService.cs): BracketName did not double embedded ']' and
passed through anything already starting with '[', and index key/
include column lists were never bracketed at all. An object named
'x] ; <T-SQL> --' produced a script that ran attacker SQL when copied
and executed - which is that output's entire purpose. BracketName now
doubles ']' (mirroring ReproScriptBuilder), and the FOR XML PATH
column lists use QUOTENAME.

LOW (mechanical): permissions: {} on the pull_request_target workflow
and contents: read on ci/check-version-bump; Uri.EscapeDataString on
share id and delete token in the web client.

Tests: 190 pass (8 new covering both injection paths). The
FormatIndexes_AlreadyBracketedName test pinned the passthrough that
was the bypass, so it now asserts correct escaping instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
It was the only deprecated package in the solution (NuGet "Legacy",
superseded by AvaloniaUI.DiagnosticsSupport), and nothing referenced
it: there is no AttachDevTools() call anywhere in the tree, so the
DevTools inspector it provides was never reachable. Upstream says the
old package "can be safely removed, as it is not used by new Developer
Tools." The parked Avalonia 12 branch already dropped it for the same
reason.

Verified: Debug and Release both build clean (0 warnings), 190 tests
pass, app launches and paints its window. dotnet list package
--deprecated is now empty across every project.

Kept the AVLN3001 suppression in Directory.Build.props - confirmed it
still fires on 4 controls when cleared, so its documented reason is
still accurate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Self-review of the previous commit: a value rejected as unsafe, or a
parameter dropped for a bad name/type, silently became ? (or vanished)
with no explanation. The existing warning only covered values that were
missing from the plan, so the output read as a tool bug rather than a
deliberate refusal. Both cases now produce a warning naming the
affected parameters.

Also added 10 real-world compiled-value cases as a Theory so the filter
cannot quietly get strict enough to degrade ordinary repro scripts:
parenthesized and negative integers, bit, decimal, scientific-notation
float, money, binary, quoted date literals, doubled quotes inside a
string, and NULL.

Tests: 202 pass (12 new).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
claude-code-review.yml runs automatically on every non-draft PR
(opened/synchronize/ready_for_review) and posts a top-level comment plus
inline comments. The prompt encodes the repo conventions CI cannot check:
zero-warning standard, the hand-maintained PlanViewer.Ssms version pair,
the linked-source requirement in PlanViewer.Web.csproj, TRY_CAST over
TRY_CONVERT, and the security severity calibration for a single-user
local install so it does not file loopback issues as High.

claude.yml is the on-demand @claude mention workflow.

Fork PRs are deliberately excluded from the automatic review: GitHub
withholds repository secrets from pull_request runs on forks and issues
a read-only token, so the job would fail rather than review. The job is
skipped instead of failing a contributor's PR with a red X. The fix is
NOT pull_request_target, which would expose a writable token and this
repo's secrets to an agent running untrusted fork code. claude.yml
covers fork PRs instead - comment events run in the base-repo context,
and the action checks the commenter has write access first.

Cost/noise controls: concurrency cancels an in-flight review when a
second push lands, docs-only changes are filtered out via paths-ignore
mirroring ci.yml, drafts are skipped, and --max-turns is capped at 20.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Quarterly maintenance: CVE-2025-6965 fix, dependency bumps, zero-warning build, CI action bumps
Add Claude Code automatic PR review workflows
All three version sources, kept in sync:
- src/Directory.Build.props (single source for SDK-style projects)
- src/PlanViewer.Ssms/source.extension.vsixmanifest
- src/PlanViewer.Ssms/Properties/AssemblyInfo.cs

The two SSMS files are not covered by Directory.Build.props because
PlanViewer.Ssms is a legacy non-SDK project; they have drifted on past
releases, so they are bumped by hand here.

Verified: clean Release build 0 warnings, 202/202 tests pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Its software `version` had been left at 1.2.0 since the file was added
in #111 (2026-03-18), 15 minor versions behind. It likely went unnoticed
because it happened to match the `cff-version: 1.2.0` schema version on
line 1, which is a different field and correctly stays at 1.2.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@erikdarlingdata
erikdarlingdata merged commit f34a3d2 into main Jul 25, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant