Skip to content

Commit 64287d7

Browse files
committed
Merge branch 'release/13.5.3' into release/13.6
# Conflicts: # version.json
2 parents 800c169 + c7d157b commit 64287d7

File tree

3 files changed

+34
-7
lines changed

3 files changed

+34
-7
lines changed

src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Globalization;
12
using Microsoft.AspNetCore.Authorization;
23
using Microsoft.AspNetCore.Mvc;
34
using Microsoft.AspNetCore.Mvc.ViewEngines;
@@ -130,6 +131,11 @@ public async Task<JavaScriptResult> Application()
130131
[Authorize(Policy = AuthorizationPolicies.BackOfficeAccess)]
131132
public ActionResult Frame(int id, string culture)
132133
{
134+
if (ValidateProvidedCulture(culture) is false)
135+
{
136+
throw new InvalidOperationException($"Could not recognise the provided culture: {culture}");
137+
}
138+
133139
EnterPreview(id);
134140

135141
// use a numeric URL because content may not be in cache and so .Url would fail
@@ -138,6 +144,28 @@ public ActionResult Frame(int id, string culture)
138144
return RedirectPermanent($"../../{id}{query}");
139145
}
140146

147+
private static bool ValidateProvidedCulture(string culture)
148+
{
149+
if (string.IsNullOrEmpty(culture))
150+
{
151+
return true;
152+
}
153+
154+
// We can be confident the backoffice will have provided a valid culture in linking to the
155+
// preview, so we don't need to check that the culture matches an Umbraco language.
156+
// We are only concerned here with protecting against XSS attacks from a fiddled preview
157+
// URL, so we can just confirm we have a valid culture.
158+
try
159+
{
160+
CultureInfo.GetCultureInfo(culture, true);
161+
return true;
162+
}
163+
catch (CultureNotFoundException)
164+
{
165+
return false;
166+
}
167+
}
168+
141169
public ActionResult? EnterPreview(int id)
142170
{
143171
IUser? user = _backofficeSecurityAccessor.BackOfficeSecurity?.CurrentUser;

src/Umbraco.Web.Common/Views/UmbracoViewPage.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,10 @@ public void WriteUmbracoContent(TagHelperOutput tagHelperOutput)
141141
string.Format(
142142
ContentSettings.PreviewBadge,
143143
HostingEnvironment.ToAbsolute(GlobalSettings.UmbracoPath),
144-
Context.Request.GetEncodedUrl(),
144+
System.Web.HttpUtility.HtmlEncode(Context.Request.GetEncodedUrl()), // Belt and braces - via a browser at least it doesn't seem possible to have anything other than
145+
// a valid culture code provided in the querystring of this URL.
146+
// But just to be sure of prevention of an XSS vulnterablity we'll HTML encode here too.
147+
// An expected URL is untouched by this encoding.
145148
UmbracoContext.PublishedRequest?.PublishedContent?.Id);
146149
}
147150
else

tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/SyntaxProvider/SqlServerSyntaxProviderTests.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,8 @@ string c(string x)
6868
}
6969

7070
Assert.AreEqual(
71-
@$"DELETE FROM {t("cmsContentNu")} WHERE {c("nodeId")} IN (SELECT {c("nodeId")} FROM (SELECT DISTINCT cmsContentNu.nodeId
72-
FROM {t("cmsContentNu")}
73-
INNER JOIN {t("umbracoNode")}
74-
ON {t("cmsContentNu")}.{c("nodeId")} = {t("umbracoNode")}.{c("id")}
75-
WHERE (({t("umbracoNode")}.{c("nodeObjectType")} = @0))) x)".Replace(Environment.NewLine, " ").Replace("\n", " ")
76-
.Replace("\r", " "),
71+
@$"DELETE FROM {t("cmsContentNu")} WHERE {c("nodeId")} IN (SELECT {c("nodeId")} FROM (SELECT DISTINCT cmsContentNu.nodeId FROM {t("cmsContentNu")} INNER JOIN {t("umbracoNode")} ON {t("cmsContentNu")}.{c("nodeId")} = {t("umbracoNode")}.{c("id")} WHERE (({t("umbracoNode")}.{c("nodeObjectType")} = @0))) x)".Replace(Environment.NewLine, " ")
72+
.Replace("\n", " ").Replace("\r", " "),
7773
sqlOutput.SQL.Replace(Environment.NewLine, " ").Replace("\n", " ").Replace("\r", " "));
7874

7975
Assert.AreEqual(1, sqlOutput.Arguments.Length);

0 commit comments

Comments
 (0)