Firefox · Networking
CVE-2025-10536
Logic Error in Networking
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifnetwerk/test/unit/test_cache2_nostore.js |
modified | |
add_tasknetwerk/test/unit/test_cache2_nostore.js |
modified | |
fornetwerk/test/unit/test_cache2_nostore.js |
modified |
Files Changed
netwerk/protocol/http/nsHttpResponseHead.cppnetwerk/test/gtest/TestCacheControlParser.cppnetwerk/test/gtest/TestHttpResponseHead.cppnetwerk/test/unit/test_cache2_nostore.jsnetwerk/test/unit/xpcshell.toml
Patch
diff --git a/netwerk/protocol/http/nsHttpResponseHead.cpp b/netwerk/protocol/http/nsHttpResponseHead.cpp
index aa0e1662996..f457ac7e23a 100644
--- a/netwerk/protocol/http/nsHttpResponseHead.cpp
+++ b/netwerk/protocol/http/nsHttpResponseHead.cpp
@@ -496,7 +496,7 @@ nsresult nsHttpResponseHead::ParseHeaderLine_locked(
LOG(("ParseContentType [input=%s, type=%s, charset=%s]\n", val.get(),
mContentType.get(), mContentCharset.get()));
} else if (hdr == nsHttp::Cache_Control) {
- ParseCacheControl(val.get());
+ ParseCacheControl(mHeaders.PeekHeader(hdr));
} else if (hdr == nsHttp::Pragma) {
ParsePragma(val.get());
}
diff --git a/netwerk/test/gtest/TestCacheControlParser.cpp b/netwerk/test/gtest/TestCacheControlParser.cpp
index 40ce3d153a9..8b6613a9a7c 100644
--- a/netwerk/test/gtest/TestCacheControlParser.cpp
+++ b/netwerk/test/gtest/TestCacheControlParser.cpp
@@ -98,3 +98,10 @@ TEST(TestCacheControlParser, CaseInsensitive)
ASSERT_TRUE(cc2.StaleWhileRevalidate(&stale_while_revalidate));
ASSERT_EQ(stale_while_revalidate, 8U);
}
+
+TEST(TestCacheControlParser, NoCacheAfterNoStore)
+{
+ CacheControlParser cc("no-store, no-cache"_ns);
+ ASSERT_TRUE(cc.NoCache());
+ ASSERT_TRUE(cc.NoStore());
+}
diff --git a/netwerk/test/gtest/TestHttpResponseHead.cpp b/netwerk/test/gtest/TestHttpResponseHead.cpp
index c38f24c1eab..b7df9a66ade 100644
--- a/netwerk/test/gtest/TestHttpResponseHead.cpp
+++ b/netwerk/test/gtest/TestHttpResponseHead.cpp
@@ -199,5 +199,18 @@ TEST(TestHttpResponseHead, MoveConstructor)
ASSERT_FALSE(originalHead.HasHeader(nsHttp::Content_Length));
}
+TEST(TestHttpResponseHead, MultipleCacheControl)
+{
+ nsHttpResponseHead originalHead;
+ Unused << originalHead.ParseStatusLine("HTTP/1.1 200 OK"_ns);
+ Unused << originalHead.ParseHeaderLine("content-type: text/plain"_ns);
+ Unused << originalHead.ParseHeaderLine("content-length: 1408"_ns);
+ Unused << originalHead.ParseHeaderLine("cache-control: no-cache"_ns);
+ Unused << originalHead.ParseHeaderLine("cache-control: no-store"_ns);
+
+ ASSERT_EQ(originalHead.NoStore(), true);
+ ASSERT_EQ(originalHead.NoCache(), true);
+}
+
} // namespace net
} // namespace mozilla
diff --git a/netwerk/test/unit/test_cache2_nostore.js b/netwerk/test/unit/test_cache2_nostore.js
new file mode 100644
index 00000000000..77b41ed147a
--- /dev/null
+++ b/netwerk/test/unit/test_cache2_nostore.js
@@ -0,0 +1,88 @@
+/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 sw=2 sts=2 et: */
+
+/**
+ * @fileoverview
+ * Unit test to verify that resources with Cache-Control: no-store, no-cache
+ * and Cache-Control: no-cache, no-store headers are not saved in the cache.
+ */
+
+const { HttpServer } = ChromeUtils.importESModule(
+ "resource://testing-common/httpd.sys.mjs"
+);
+
+let httpServer = null;
+
+function startServer() {
+ httpServer = new HttpServer();
+ httpServer.registerPathHandler("/test1", (request, response) => {
+ response.setHeader("Cache-Control", "no-cache, no-store", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("OK");
+ });
+ httpServer.registerPathHandler("/test2", (request, response) => {
+ response.setHeader("Cache-Control", "no-cache, no-store", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("OK");
+ });
+ httpServer.registerPathHandler("/test3", (request, response) => {
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Cache-Control", "no-store", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("OK");
+ });
+ httpServer.registerPathHandler("/test4", (request, response) => {
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Cache-Control", "no-store", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("OK");
+ });
+ httpServer.start(-1);
+ registerCleanupFunction(async () => {
+ if (httpServer) {
+ await httpServer.stop();
+ }
+ });
+ return httpServer.identity.primaryPort;
+}
+
+add_task(async function test_no_cache_no_store() {
+ const port = startServer();
+ const baseURI = `http://localhost:${port}`;
+ let tests = ["/test1", "/test2", "/test3", "/test4"];
+
+ for (let test of tests) {
+ let uri = baseURI + test;
+ let channel = NetUtil.newChannel({
+ uri,
+ loadUsingSystemPrincipal: true,
+ });
+
+ let buffer = await new Promise(resolve => {
+ channel.asyncOpen(
+ new ChannelListener(
+ (request, buffer) => resolve(buffer),
+ null,
+ CL_ALLOW_UNKNOWN_CL
+ )
+ );
+ });
+
+ Assert.equal(buffer, "OK", `Received expected content for ${test}`);
+
+ let entry = await new Promise(resolve => {
+ asyncOpenCacheEntry(
+ uri,
+ "disk",
+ Ci.nsICacheStorage.OPEN_READONLY,
+ null,
+ (status, entry) => resolve(entry)
+ );
+ });
+ Assert.equal(
+ entry.persistent,
+ false,
+ `${test} should not be persistently cached`
+ );
+ }
+});
diff --git a/netwerk/test/unit/xpcshell.toml b/netwerk/test/unit/xpcshell.toml
index a43502024ca..1b73868f64c 100644
--- a/netwerk/test/unit/xpcshell.toml
+++ b/netwerk/test/unit/xpcshell.toml
@@ -467,6 +467,8 @@ run-sequentially = "httpd server"
["test_cache2_clear_with_usercontext_oa.js"]
run-sequentially = "httpd server"
+["test_cache2_nostore.js"]
+
["test_cache_204_response.js"]
["test_cache_jar.js"]
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/netwerk/test/gtest/TestCacheControlParser.cpp b/netwerk/test/gtest/TestCacheControlParser.cpp
index 40ce3d153a9..8b6613a9a7c 100644
--- a/netwerk/test/gtest/TestCacheControlParser.cpp
+++ b/netwerk/test/gtest/TestCacheControlParser.cpp
@@ -98,3 +98,10 @@ TEST(TestCacheControlParser, CaseInsensitive)
ASSERT_TRUE(cc2.StaleWhileRevalidate(&stale_while_revalidate));
ASSERT_EQ(stale_while_revalidate, 8U);
}
+
+TEST(TestCacheControlParser, NoCacheAfterNoStore)
+{
+ CacheControlParser cc("no-store, no-cache"_ns);
+ ASSERT_TRUE(cc.NoCache());
+ ASSERT_TRUE(cc.NoStore());
+}
diff --git a/netwerk/test/gtest/TestHttpResponseHead.cpp b/netwerk/test/gtest/TestHttpResponseHead.cpp
index c38f24c1eab..b7df9a66ade 100644
--- a/netwerk/test/gtest/TestHttpResponseHead.cpp
+++ b/netwerk/test/gtest/TestHttpResponseHead.cpp
@@ -199,5 +199,18 @@ TEST(TestHttpResponseHead, MoveConstructor)
ASSERT_FALSE(originalHead.HasHeader(nsHttp::Content_Length));
}
+TEST(TestHttpResponseHead, MultipleCacheControl)
+{
+ nsHttpResponseHead originalHead;
+ Unused << originalHead.ParseStatusLine("HTTP/1.1 200 OK"_ns);
+ Unused << originalHead.ParseHeaderLine("content-type: text/plain"_ns);
+ Unused << originalHead.ParseHeaderLine("content-length: 1408"_ns);
+ Unused << originalHead.ParseHeaderLine("cache-control: no-cache"_ns);
+ Unused << originalHead.ParseHeaderLine("cache-control: no-store"_ns);
+
+ ASSERT_EQ(originalHead.NoStore(), true);
+ ASSERT_EQ(originalHead.NoCache(), true);
+}
+
} // namespace net
} // namespace mozilla
diff --git a/netwerk/test/unit/test_cache2_nostore.js b/netwerk/test/unit/test_cache2_nostore.js
new file mode 100644
index 00000000000..77b41ed147a
--- /dev/null
+++ b/netwerk/test/unit/test_cache2_nostore.js
@@ -0,0 +1,88 @@
+/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ts=2 sw=2 sts=2 et: */
+
+/**
+ * @fileoverview
+ * Unit test to verify that resources with Cache-Control: no-store, no-cache
+ * and Cache-Control: no-cache, no-store headers are not saved in the cache.
+ */
+
+const { HttpServer } = ChromeUtils.importESModule(
+ "resource://testing-common/httpd.sys.mjs"
+);
+
+let httpServer = null;
+
+function startServer() {
+ httpServer = new HttpServer();
+ httpServer.registerPathHandler("/test1", (request, response) => {
+ response.setHeader("Cache-Control", "no-cache, no-store", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("OK");
+ });
+ httpServer.registerPathHandler("/test2", (request, response) => {
+ response.setHeader("Cache-Control", "no-cache, no-store", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("OK");
+ });
+ httpServer.registerPathHandler("/test3", (request, response) => {
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Cache-Control", "no-store", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("OK");
+ });
+ httpServer.registerPathHandler("/test4", (request, response) => {
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setHeader("Cache-Control", "no-store", false);
+ response.setHeader("Content-Type", "text/plain", false);
+ response.write("OK");
+ });
+ httpServer.start(-1);
+ registerCleanupFunction(async () => {
+ if (httpServer) {
+ await httpServer.stop();
+ }
+ });
+ return httpServer.identity.primaryPort;
+}
+
+add_task(async function test_no_cache_no_store() {
+ const port = startServer();
+ const baseURI = `http://localhost:${port}`;
+ let tests = ["/test1", "/test2", "/test3", "/test4"];
+
+ for (let test of tests) {
+ let uri = baseURI + test;
+ let channel = NetUtil.newChannel({
+ uri,
+ loadUsingSystemPrincipal: true,
+ });
+
+ let buffer = await new Promise(resolve => {
+ channel.asyncOpen(
+ new ChannelListener(
+ (request, buffer) => resolve(buffer),
+ null,
+ CL_ALLOW_UNKNOWN_CL
+ )
+ );
+ });
+
+ Assert.equal(buffer, "OK", `Received expected content for ${test}`);
+
+ let entry = await new Promise(resolve => {
+ asyncOpenCacheEntry(
+ uri,
+ "disk",
+ Ci.nsICacheStorage.OPEN_READONLY,
+ null,
+ (status, entry) => resolve(entry)
+ );
+ });
+ Assert.equal(
+ entry.persistent,
+ false,
+ `${test} should not be persistently cached`
+ );
+ }
+});
diff --git a/netwerk/test/unit/xpcshell.toml b/netwerk/test/unit/xpcshell.toml
index a43502024ca..1b73868f64c 100644
--- a/netwerk/test/unit/xpcshell.toml
+++ b/netwerk/test/unit/xpcshell.toml
@@ -467,6 +467,8 @@ run-sequentially = "httpd server"
["test_cache2_clear_with_usercontext_oa.js"]
run-sequentially = "httpd server"
+["test_cache2_nostore.js"]
+
["test_cache_204_response.js"]
["test_cache_jar.js"]
Loading diff…
References
On This Page