cygrunsrv CWE-428

James Warnock via Cygwin <[email protected]> Tue, 21 Apr 2026 08:57:31 -0600
Newsgroups gmane.os.cygwin
Message-ID <[email protected]>
We use cygwin including installing some services via cygrunsrv. We have 
had some users run vulnerability scans which flag the installed services 
due to an unquoted service path (CWE-428 [1]). I haven't been able to 
find any discussion of this in the archives except for the "cygrunsrv -L 
outputs nothing if service paths are quoted" [2]. In that message, 
another user manually added quotes to resolve the vulnerability scan but 
then 'cygrunsrv -L' no longer listed installed services. That issue was 
fixed.

I did come up with a simple patch (attached) that worked for my limited 
use case. But there may be considerations for global usage of which I am 
unaware.

Should cygrunsrv be updated to automatically include the quotes?

Thanks,
James

[1] https://cwe.mitre.org/data/definitions/428.html
[2] https://cygwin.com/pipermail/cygwin/2023-February/252998.html


-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple
cwe-428.patch (text/x-patch, 1.9 KB)
diff --git a/cygrunsrv.cc b/cygrunsrv.cc
index dab8790..c3b04ee 100644
--- a/cygrunsrv.cc
+++ b/cygrunsrv.cc
@@ -810,6 +810,7 @@ install_service (const char *name, const char *crspath, const char *disp,
 		 int interactive)
 {
   char mypath[MAX_PATH];
+  char* mypath_p = mypath;
   SC_HANDLE sm = (SC_HANDLE) 0;
   SC_HANDLE sh = (SC_HANDLE) 0;
   char userbuf[INTERNET_MAX_HOST_NAME_LENGTH + UNLEN + 2];
@@ -824,28 +825,31 @@ install_service (const char *name, const char *crspath, const char *disp,
   if (!san.server ())
     check_system_mounts ();
 
+  mypath[0] = '"';
+  mypath_p++;
   if (crspath)		  /* Got path, nothing to do. */
     {
-      cygwin_conv_path (CCP_POSIX_TO_WIN_A, crspath, mypath, MAX_PATH);
+      cygwin_conv_path (CCP_POSIX_TO_WIN_A, crspath, mypath_p, MAX_PATH-2);
       if (strcasecmp (mypath + strlen (mypath) - 4, ".exe") != 0)
         strcat (mypath, ".exe");
     }
   else if (san.server ()) /* Figure out cygrunsrv path on remote server. */
     {
-      DWORD ret, type, size = MAX_PATH - 20;
+      DWORD ret, type, size = MAX_PATH - 22;
       if ((ret = RegOpenKeyEx (san.hklm (), (PCHAR) CYG_ROOT, 0,
 			       KEY_READ, &cyg_root_key)) != ERROR_SUCCESS)
 	err_out_set_error (RegOpenKeyEx, ret);
       if ((ret = RegQueryValueEx (cyg_root_key, (PCHAR) CYG_ROOT_VAL, 0, &type,
-				  (BYTE *) mypath, &size)) != ERROR_SUCCESS)
+				  (BYTE *) mypath_p, &size)) != ERROR_SUCCESS)
 	err_out_set_error (RegQueryValueEx, ret);
-      strcat (mypath, "\\bin\\cygrunsrv.exe");
+      strcat (mypath_p, "\\bin\\cygrunsrv.exe");
     }
   else			  /* Get own full path. */
     {
-      if (!GetModuleFileName (NULL, mypath, MAX_PATH))
+      if (!GetModuleFileName (NULL, mypath_p, MAX_PATH-2))
 	err_out (GetModuleFileName);
     }
+  strcat (mypath_p, "\"");
   /* Open service manager database. */
   if (!(sm = OpenSCManager (san.server (), NULL,
 			    SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE)))