diff --git a/libio/fileops.c b/libio/fileops.c
index 9348d7c3a1..f42588a94f 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -355,8 +355,19 @@ _IO_new_file_fopen (FILE *fp, const char *filename, const char *mode,
 	  *((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0';
 	  strip (ccs, ccs);
 
-	  if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0'
-				   ? upstr (ccs, cs + 5) : ccs) != 0)
+	  /* If strip() reduced the specification to the empty string (leaving
+	     only the "//" that strip() always appends), fall back to the
+	     original charset name.  Bound the copy by ENDP so we do not read
+	     past the ',' delimiter and overflow CCS (CVE-2026-18374).  */
+	  if (ccs[2] == '\0')
+	    {
+	      char *wp = ccs;
+	      for (const char *rp = cs + 5; rp < endp; ++rp)
+		*wp++ = __toupper_l (*rp, _nl_C_locobj_ptr);
+	      *wp = '\0';
+	    }
+
+	  if (__wcsmbs_named_conv (&fcts, ccs) != 0)
 	    {
 	      /* Something went wrong, we cannot load the conversion modules.
 		 This means we cannot proceed since the user explicitly asked
diff --git a/libio/tst-fopenloc.c b/libio/tst-fopenloc.c
index ea3f7b5265..5ce3bc5abb 100644
--- a/libio/tst-fopenloc.c
+++ b/libio/tst-fopenloc.c
@@ -85,6 +85,54 @@ do_bz18906 (void)
   return EXIT_SUCCESS;
 }
 
+static int
+do_cve_2026_18374 (void)
+{
+  /* CVE-2026-18374 -- a ,ccs= specification that is not empty but becomes
+     empty after strip() must not make fopen read past the ',' delimiter and
+     overflow the heap buffer.  It has to fail cleanly with EINVAL.  */
+
+  const size_t sz = 8192;
+  char *ccs = xmalloc (sz);
+  strcpy (ccs, "r,ccs=/,");
+  memset (ccs + 8, 'A', sz - 8 - 1);
+  ccs[sz - 1] = '\0';
+
+  errno = 0;
+  FILE *fp = fopen (inputfile, ccs);
+  if (fp != NULL)
+    {
+      printf ("fopen with empty-after-strip ccs= unexpectedly succeeded\n");
+      free (ccs);
+      fclose (fp);
+      return 1;
+    }
+  if (errno != EINVAL)
+    {
+      printf ("expected EINVAL, got %d\n", errno);
+      free (ccs);
+      return 1;
+    }
+  free (ccs);
+
+  /* Also check the trivially empty ,ccs= case.  */
+  errno = 0;
+  fp = fopen (inputfile, "r,ccs=");
+  if (fp != NULL)
+    {
+      printf ("fopen with empty ccs= unexpectedly succeeded\n");
+      fclose (fp);
+      return 1;
+    }
+  if (errno != EINVAL)
+    {
+      printf ("expected EINVAL, got %d\n", errno);
+      return 1;
+    }
+
+  return 0;
+}
+
 static int
 do_test (void)
 {
@@ -110,6 +158,7 @@ do_test (void)
 
   TEST_COMPARE (do_bz17916 (), 0);
   TEST_COMPARE (do_bz18906 (), 0);
+  TEST_COMPARE (do_cve_2026_18374 (), 0);
 
   return EXIT_SUCCESS;
 }
