Configured Commerce Upgrade Watch: April 2026
sts 5.2.2604.558+sts Covers April 2026
Written by Lance Farquhar May 14, 2026
Release 5.2.2604.558+sts, published May 12, 2026. Each month we read what Optimizely says shipped, then go verify it against the actual source — frontend and backend — so you get more than a changelog recap.
The 30-Second Version
- Headline feature: A hardening pass across every sign-in redirect path — standard sign-in, external-provider sign-in, and customer-context switching all now route through a new
safeRedirect()utility that blocksjavascript:,data:, andvbscript:URLs before the browser ever acts on them. - Worth knowing: Promotions got real feature work this cycle — bulk product assignment with Excel import, a configurable max discount cap, a new Discount Product List result, and an Ordered Product List rule — backed by a new database table, a new controller, and a new capping method, not just UI relabels.
- Also notable: The Spire frontend toolchain moved to TypeScript 6.0, dropping several now-default compiler options and switching module resolution from
nodetobundler— worth a look if you carry customtsconfigoverrides. - Verdict: A solid, workmanlike release. The promotions feature set and the sign-in hardening are the two things worth your attention; most of the rest is incremental cleanup and quality-of-life polish.
The Headline: Sign-In Redirect Hardening
Optimizely's release notes list "Security enhancements for sign-ins" as a single line under Enhancements. The source tells a fuller story: this is a coordinated hardening pass across every place in the storefront that redirects the browser after an authentication event.
A new utility, safeRedirect.ts, was added to client-framework. It builds on the existing removeAbsoluteUrl() logic in PageSelectors.ts, adding an explicit check for dangerous URL protocols before anything gets assigned to window.location.href:
const dangerousProtocolPattern = /^\s*(javascript|data|vbscript)\s*:/i;
...
if (dangerousProtocolPattern.test(decodedUrl)) {
return "";
}
Three call sites were updated to route through it: SignIn.ts, SignInExternalProvider.ts, and ChangeCustomerContext.ts. That's standard sign-in, the external-identity-provider approval flow, and the customer-context switch — every place in the authentication surface that previously assigned a return URL directly now passes it through the same shared check first.
The practical effect: a return URL crafted to execute script via a javascript: or data: URI is blocked before the redirect happens, across all three flows, through one shared utility rather than three separate patches.
What Else Shipped
Breaking changes (low risk)
- Commerce Search v3:
ISearchRequest<T>gained a newCanonicalFilterproperty, and thePerformCompleteQuery/ProcessCompleteQueryResponseclasses moved into the namespace matching their actual folder location (...CompleteQuery.Pipelines.Pipes.RunCompleteQuery), picking up new try/catch error handling along the way. - SX.e connector: V11 support is available on the .NET 8 build target. (There's a bit more to this one — see "What We Actually Found" below.)
- Code cleanup:
IEntityTranslationServicegained a newGetPropertyTranslationsmethod with a complete caching implementation behind it. Several long-unused classes were removed outright, includingNaturalSortComparerand a handful of methods fromHttpContextBaseExtensionsandWebsiteRepository.
Enhancements
Promotions carried the bulk of this release's feature work. Bulk product assignment for promotion Rules and Results now has a real backing store — a new PromotionResultProduct table (migration 2026.03.24.01.AddPromotionResultProductTable.sql) and a 449-line PromotionResultsController.editable.cs that adds an OData CreateTemporaryAsync action plus Excel-based import via Sylvan.Data.Excel, reporting products imported, not found, and errored on. Max Discount Amount is enforced through a new ApplyMaxValueCap method on the promotions amount provider, applied to both percent-off-order and product-discount calculations, converted through the order's currency conversion rate before the cap is applied. Discount Product List and Ordered Product List round out the promotions work, the latter backed by a new CriteriaTypeOrderedProductList and a matching OrderedProductListManager.tsx Admin Console component.
On the search side, the new Canonical Filter setting is fully wired into the Google Cloud Retail Search pipeline via two new pipes, 1500_FormCanonicalFilter.cs and 2660_ApplyCanonicalFilter.cs. Commerce Search Service rate limiting is now handled gracefully — a TooManyRequestsException triggers an automatic fallback to Elasticsearch rather than a failed search (see "Under the Hood" for the actual catch block).
Application Insights page-view tracking for Spire is a complete feature this cycle: a new getAppInsightsHeadScript() function in tracking.ts, a SetAppInsightsScript handler wired into the tracking chain, and a call to appInsights.trackPageView({ uri: url }) on every page change, all keyed off a new applicationInsightsConnectionString website setting.
Elsewhere: the Spire frontend toolchain moved to TypeScript 6.0 (dropping several now-default compiler options and switching moduleResolution from node to bundler), Proxima Nova was replaced by Google Fonts' Montserrat across both the Barriston and HeroTools themes (with the old webfont files removed entirely), TinyMCE picked up anchor and visual-blocks formatting plugins, and a new PaymentServiceLogger implementation backs the optional Payment Service Request/Response Logging setting. A new AuthenticationCookieDomain setting (website-specific, default empty, scoped to system/implementer roles) with domain-mismatch warning logic appears to be the source-level implementation behind the documented "Use Top Level Domain For Authentication Cookie" option.
Bug fixes
Two fixes trace cleanly to source: the Website Cross Sell widget now excludes restriction-group-blocked styled children from its visible set (a new GetRestrictedProductIds call added to 1400_GetSiteCrossSells.cs), and the Admin Console's Criteria Object inconsistency is fixed by a genuine rename — CriteriaTypeDto gained a CriteriaObject property, and the rules UI now reads criterias[0].criteriaObject instead of the old lookupObject field.
A number of the remaining bug-fix items in this release — including several fixes to payment parsing, sitemap generation, and Admin Console indicators — are worth testing directly against a running instance; the reference repo's diff is large enough (1,325 files) that a keyword search doesn't reliably surface every fix.
What We Actually Found: The .NET 8 SX.e Connector Boundary
Away from promotions and sign-in security, the SX.e connector code got real attention this cycle. The .NET 8 build target's V11 support is untouched — it's been in place since a build from spring of last year and keeps working exactly as it has. What's genuinely new in this diff is a version boundary: V10 and V61, the two older SX.e wire-protocol implementations, are now wrapped in a single #if !NET6_0_OR_GREATER conditional, cleanly excluding them from .NET 8 builds while leaving every other target untouched.
It's a narrow, single-purpose change — one conditional-compilation flag, two legacy code paths gated off, zero risk to V11 or to any other build target. If you're running SX.e integration on .NET 8 and still depend on V10 or V61, this is the line in the diff worth knowing about before your next upgrade.
Under the Hood
Canonical Filter setting (Search Query Expansion)
[SettingsField(DisplayName = "Canonical Filter", Description = "A special purpose filter used exclusively by the query expansion decision module ...")]
[SettingsFieldDependency(typeof(SearchGeneralSettings), nameof(SearchQueryExpansion), "true")]
public virtual bool CanonicalFilter => this.GetValue(false);
The setting is gated behind SearchQueryExpansion via SettingsFieldDependency — it can't be turned on until query expansion itself is, which keeps the admin UI from exposing a control that would otherwise do nothing.
Graceful fallback on search rate limiting
catch (TooManyRequestsException)
when (parameter.ProductSearchParameter.Relevancy
&& searchGeneralSettings.SearchProviderName == "Commerce Search v3")
{
LogHelper.For(this).Error("Google Cloud Retail Search Quota limits may have been exceeded...");
parameter.ProductSearchParameter.Relevancy = false;
result.ProductSearchResult = productSearchProvider.GetSearchResults(...);
}
The when clause scopes the catch precisely to relevancy-mode searches on Commerce Search v3 — it won't swallow rate-limit errors from any other search path — and the fallback flips Relevancy off and re-runs the search through the standard provider rather than surfacing an error page to the shopper.
What This Means for You
- Audit any custom code in your storefront that assigns
window.location.hrefdirectly from user-controlled input — this release's hardening coversSignIn.ts,SignInExternalProvider.ts, andChangeCustomerContext.ts, not every possible redirect in a customized codebase. - If you're building on promotions, note that Discount Product List and Ordered Product List both depend on the new
PromotionResultProducttable and Excel-import path — check any custom promotion admin UI you've layered on top. - Test Max Discount Amount caps against your catalog before enabling them, especially on multi-currency storefronts — the cap is applied after conversion through the order's currency rate.
- If you're running SX.e integration on a .NET 8 build and still depend on connector V10 or V61, confirm your build target before upgrading; those versions are no longer part of .NET 8 builds.
- Review any custom TypeScript build configuration in your storefront extensions against the TypeScript 6.0 upgrade, particularly the switch to
moduleResolution: "bundler". - If you use Application Insights, the new
applicationInsightsConnectionStringwebsite setting is what turns on Spire page-view tracking. - Re-test any custom Admin Console rules widgets that reference Criteria Object values against the renamed
criteriaObjectproperty. - Nothing here requires urgent action beyond the SX.e .NET 8 boundary check — most of this cycle's other changes are additive and off by default.
Upgrading a Configured Commerce storefront and want a second set of eyes on what actually changed under a release before you take it? That's exactly the kind of review Nishtech does for clients every month — reach out and we'll walk through it with you.