diff --git a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql index 9e51b663038c..1b647457e7c8 100644 --- a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql +++ b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.ql @@ -16,6 +16,17 @@ import csharp import semmle.code.asp.WebConfig import semmle.code.csharp.frameworks.system.Web +XmlElement getAWebConfigRoot(WebConfigXml webConfig) { + result = webConfig.getARootElement() + or + result = webConfig.getARootElement().getAChild("location") and + ( + not result.hasAttribute("path") // equivalent to path="." + or + result.getAttributeValue("path") = ["", "."] + ) +} + /** * Holds if the `Web.config` file `webConfig` adds an `X-Frame-Options` header. */ @@ -30,8 +41,8 @@ predicate hasWebConfigXFrameOptions(WebConfigXml webConfig) { // // // ``` - webConfig - .getARootElement() + // This can also be in a `location` + getAWebConfigRoot(webConfig) .getAChild("system.webServer") .getAChild("httpProtocol") .getAChild("customHeaders") diff --git a/csharp/ql/src/change-notes/2025-10-17-location-in-web-config.md b/csharp/ql/src/change-notes/2025-10-17-location-in-web-config.md new file mode 100644 index 000000000000..5df97b9d28a6 --- /dev/null +++ b/csharp/ql/src/change-notes/2025-10-17-location-in-web-config.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* the `cs/web/missing-x-frame-options` query now correctly handles configuration nested in root `` elements. diff --git a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/MissingXFrameOptions.cs b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/MissingXFrameOptions.cs new file mode 100644 index 000000000000..48073a309fd7 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/MissingXFrameOptions.cs @@ -0,0 +1,18 @@ +using System; +using System.Web; + +public class AddXFrameOptions : IHttpHandler +{ + + public void ProcessRequest(HttpContext ctx) + { + } + + public bool IsReusable + { + get + { + return true; + } + } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/MissingXFrameOptions.expected b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/MissingXFrameOptions.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/MissingXFrameOptions.qlref b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/MissingXFrameOptions.qlref new file mode 100644 index 000000000000..b8a963200e57 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/MissingXFrameOptions.qlref @@ -0,0 +1 @@ +Security Features/CWE-451/MissingXFrameOptions.ql diff --git a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/Web.config b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/Web.config new file mode 100644 index 000000000000..ce837c2b9815 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/Web.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/options b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/options new file mode 100644 index 000000000000..9d05f9bf06d4 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-451/MissingXFrameOptions/WebConfigAddedHeaderInLocation/options @@ -0,0 +1,3 @@ +semmle-extractor-options: /nostdlib /noconfig +semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj +semmle-extractor-options: ${testdir}/../../../../../resources/stubs/System.Web.cs