Project

General

Profile

issue_1.txt

Sergey Ivanovskiy, 05/22/2026 04:23 PM

Download (4.34 KB)

 
1
ISSUE DESCRIPTION:
2
*[MAJOR]* _security_ @WebPageHandler@.@WebPageKeysProvider@: Admin-configured connection messages are inserted into single-quoted JS string literals in index.html (e.g. @'tryToConnectMessage' : '${tryToConnectMessage}'@) with no JS-string escaping (WebPageHandler.java:237-246, index.html:122-124). A value containing @'@, @\@, @\n@, or @</script>@ breaks out of the literal and yields arbitrary JS execution in every web client. @Utils.removeEscapedDoubleQuotes@ only strips a leading/trailing @\"...\"@ artifact and provides no XSS protection. Apply a proper JS-string encoder (or JSON-encode the value before interpolation).
3

    
4
PROPOSED FIX:
5
Introduce a dedicated `escapeJsString(String)` helper in `Utils` that escapes the characters that can break out of a single-quoted JS literal embedded in an HTML <script> block: backslash, single/double quote, CR/LF, U+2028, U+2029, and the `</` sequence (to prevent premature </script> termination). Apply it in `WebPageHandler.WebPageKeysProvider` around every admin-supplied connection message before the value is interpolated into index.html. The legacy `removeEscapedDoubleQuotes` only strips a wrapper artifact and is orthogonal to escaping, so keep stripping the wrapper first and then escape the remainder.
6

    
7
CHANGES:
8
/home/sbi/projects/10915a/src/com/goldencode/p2j/util/Utils.java
9
```java
10
   public static String removeEscapedDoubleQuotes(String text)
11
   {
12
      if (text == null)
13
      {
14
         return text;
15
      }
16

    
17
      int end = text.length();
18

    
19
      if (text.startsWith("\\\"") && end > 3 && text.endsWith("\\\""))
20
      {
21
         return text.substring(2, end - 2);
22
      }
23

    
24
      return text;
25
   }
26

    
27
   /**
28
    * Escape a string so that it can be safely embedded inside a single- or
29
    * double-quoted JavaScript string literal that itself appears inside an
30
    * HTML &lt;script&gt; block. Escapes backslash, both quote styles, CR/LF,
31
    * line/paragraph separators (U+2028/U+2029) and the &quot;&lt;/&quot;
32
    * sequence to prevent premature &lt;/script&gt; termination.
33
    *
34
    * @param    text
35
    *           The string to escape, or {@code null}.
36
    *
37
    * @return   A JS-safe representation of {@code text}, or an empty string
38
    *           if {@code text} is {@code null}.
39
    */
40
   public static String escapeJsString(String text)
41
   {
42
      if (text == null)
43
      {
44
         return "";
45
      }
46
      StringBuilder sb = new StringBuilder(text.length() + 16);
47
      for (int i = 0, n = text.length(); i < n; i++)
48
      {
49
         char c = text.charAt(i);
50
         switch (c)
51
         {
52
            case '\\': sb.append("\\\\"); break;
53
            case '\'': sb.append("\\'");  break;
54
            case '"':  sb.append("\\\""); break;
55
            case '\n': sb.append("\\n");  break;
56
            case '\r': sb.append("\\r");  break;
57
            case '\t': sb.append("\\t");  break;
58
            case '\b': sb.append("\\b");  break;
59
            case '\f': sb.append("\\f");  break;
60
            case '
': sb.append("\\u2028"); break;
61
            case '
': sb.append("\\u2029"); break;
62
            case '<':
63
               // break "</" so a stray "</script>" cannot terminate the block
64
               if (i + 1 < n && text.charAt(i + 1) == '/')
65
               {
66
                  sb.append("\\u003c");
67
               }
68
               else
69
               {
70
                  sb.append(c);
71
               }
72
               break;
73
            default:
74
               sb.append(c);
75
         }
76
      }
77
      return sb.toString();
78
   }
79
```
80

    
81
/home/sbi/projects/10915a/src/com/goldencode/p2j/ui/client/driver/web/WebPageHandler.java
82
```java
83
         add(ConfigItem.TRY_CONNECT_MSG.name(), () -> Utils.escapeJsString(
84
               Utils.removeEscapedDoubleQuotes(config.getString(
85
                  ConfigItem.TRY_CONNECT_MSG, WebConfigurationConstants.TRY_TO_CONNECT_MESSAGE))));
86

    
87
         add(ConfigItem.CONNECTION_RESTORED_MSG.name(),
88
               () -> Utils.escapeJsString(Utils.removeEscapedDoubleQuotes(config.getString(
89
                     ConfigItem.CONNECTION_RESTORED_MSG,
90
                     WebConfigurationConstants.CONNECTION_RESTORED_MESSAGE))));
91

    
92
         add(ConfigItem.SERVER_UNAVAILABLE_MSG.name(),
93
               () -> Utils.escapeJsString(Utils.removeEscapedDoubleQuotes(config.getString(
94
                     ConfigItem.SERVER_UNAVAILABLE_MSG,
95
                     WebConfigurationConstants.SERVER_UNAVAILABLE_MESSAGE))));
96
```