32d8c9cb1c107f4bee849bdbf0db07b6bfb2a94d
max
  Wed Jul 8 05:35:07 2026 -0700
hgLogin: require new user names to be at least two characters, refs #10138

Single-character user names are now reserved ("l" is used internally for anonymous shared-session links), so signup() rejects them.  The check is only in the account-creation path, so existing accounts -- including any single-character ones -- keep working for login and sessions.

diff --git src/hg/hgLogin/hgLogin.c src/hg/hgLogin/hgLogin.c
index af0d66723a4..c10d1496378 100644
--- src/hg/hgLogin/hgLogin.c
+++ src/hg/hgLogin/hgLogin.c
@@ -989,30 +989,39 @@
 }
 
 void signup(struct sqlConnection *conn)
 /* process the signup form */
 {
 char query[1024];
 char *user = cartUsualString(cart, "hgLogin_userName", "");
 char *encUserName = cgiEncodeFull(user);
 if (!user || sameString(user,""))
     {
     freez(&errMsg);
     errMsg = cloneString("User name cannot be blank.");
     signupPage(conn);
     return;
     }
+/* Require at least two characters.  Single-character user names are reserved (e.g. "l" is used
+ * internally for anonymous shared-session links). */
+if (strlen(user) < 2)
+    {
+    freez(&errMsg);
+    errMsg = cloneString("User name must be at least two characters long.");
+    signupPage(conn);
+    return;
+    }
 /* Make sure the escaped usrename is less than 32 characters */
 if (strlen(encUserName) > 32)
     {
     char buf[1024];
     safef(buf,sizeof(buf), "Encoded user name: '%s' is %d characters.  Please use a shorter name: less than 32 characters after URL encoding.", encUserName, (int)strlen(encUserName));
     freez(&errMsg);
     errMsg = cloneString(buf);
     signupPage(conn);
     return;
     }
 
 sqlSafef(query,sizeof(query), "SELECT password FROM gbMembers WHERE userName='%s'", user);
 
 char *password = sqlQuickString(conn, query);
 if (password)