VYPR
High severityNVD Advisory· Published May 3, 2023· Updated Feb 12, 2025

Cross-site Scripting in OpenTSDB

CVE-2023-25827

Description

Reflected XSS vulnerability in OpenTSDB legacy HTTP query API and logging endpoint allows injection of arbitrary JavaScript via insufficient validation of parameters in error messages.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Reflected XSS vulnerability in OpenTSDB legacy HTTP query API and logging endpoint allows injection of arbitrary JavaScript via insufficient validation of parameters in error messages.

CVE-2023-25827 is a reflected cross-site scripting (XSS) vulnerability affecting OpenTSDB, a time series database. The flaw arises from insufficient validation of user-supplied parameters that are reflected in error messages generated by the legacy HTTP query API (/q endpoint) and the logging endpoint (/logs endpoint). This issue shares the same root cause as CVE-2018-13003, a reflected XSS vulnerability in the suggestion endpoint [1][4].

An attacker can exploit this by crafting a malicious URL containing JavaScript code in specific parameters. For the /q endpoint, the vulnerable parameters are start, end, m, and key; for the /logs endpoint, the level parameter is affected [4]. When a victim visits such a URL, the injected JavaScript is reflected in the resulting error page and executes within the victim's browser. No authentication is required to trigger the vulnerability, as the error responses are generated before any authentication checks [4].

Successful exploitation allows arbitrary JavaScript execution in the context of the OpenTSDB user's browser. This could enable an attacker to steal session cookies, perform actions on behalf of the victim, or deface the application interface, potentially leading to further compromise of the OpenTSDB instance [4].

The vulnerability has been addressed in a pull request (#2274) on the OpenTSDB GitHub repository [2]. Users are advised to update to the latest fixed version as soon as possible. This issue highlights the need for careful input validation and output encoding, especially when error messages include user input [1][2].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
net.opentsdb:opentsdbMaven
<= 2.4.1

Affected products

2

Patches

1
fa88d3e4b536

Fix for #2269 and #2267 XSS vulnerability.

https://github.com/OpenTSDB/opentsdbChris LarsenApr 11, 2023via ghsa-ref
3 files changed · +36 4
  • src/tsd/HttpQuery.java+11 2 modified
    @@ -25,6 +25,7 @@
     import java.util.HashSet;
     import java.util.List;
     
    +import com.google.common.html.HtmlEscapers;
     import net.opentsdb.core.Const;
     import net.opentsdb.core.TSDB;
     import net.opentsdb.graph.Plot;
    @@ -373,14 +374,18 @@ public void internalError(final Exception cause) {
           buf.append("\"}");
           sendReply(HttpResponseStatus.INTERNAL_SERVER_ERROR, buf);
         } else {
    +      String response = "";
    +      if (pretty_exc != null) {
    +        response = HtmlEscapers.htmlEscaper().escape(pretty_exc);
    +      }
           sendReply(HttpResponseStatus.INTERNAL_SERVER_ERROR,
                     makePage("Internal Server Error", "Houston, we have a problem",
                              "<blockquote>"
                              + "<h1>Internal Server Error</h1>"
                              + "Oops, sorry but your request failed due to a"
                              + " server error.<br/><br/>"
                              + "Please try again in 30 seconds.<pre>"
    -                         + pretty_exc
    +                         + response
                              + "</pre></blockquote>"));
         }
       }
    @@ -420,14 +425,18 @@ public void badRequest(final BadRequestException exception) {
           buf.append("\"}");
           sendReply(HttpResponseStatus.BAD_REQUEST, buf);
         } else {
    +      String response = "";
    +      if (exception.getMessage() != null) {
    +        response = HtmlEscapers.htmlEscaper().escape(exception.getMessage());
    +      }
           sendReply(HttpResponseStatus.BAD_REQUEST,
                     makePage("Bad Request", "Looks like it's your fault this time",
                              "<blockquote>"
                              + "<h1>Bad Request</h1>"
                              + "Sorry but your request was rejected as being"
                              + " invalid.<br/><br/>"
                              + "The reason provided was:<blockquote>"
    -                         + exception.getMessage()
    +                         + response
                              + "</blockquote></blockquote>"));
         }
       }
    
  • test/tsd/TestHttpQuery.java+23 0 modified
    @@ -795,6 +795,18 @@ public void internalErrorDeprecated() {
             query.response().getContent().toString(Charset.forName("UTF-8"))
             .substring(0, 15));
       }
    +
    +  @Test
    +  public void internalErrorDeprecatedHTMLEscaped() {
    +    HttpQuery query = NettyMocks.getQuery(tsdb, "");
    +    query.internalError(new Exception("<script>alert(document.cookie)</script>"));
    +
    +    assertEquals(HttpResponseStatus.INTERNAL_SERVER_ERROR,
    +        query.response().getStatus());
    +    assertTrue(query.response().getContent().toString(Charset.forName("UTF-8")).contains(
    +        "&lt;script&gt;alert(document.cookie)&lt;/script&gt;"
    +    ));
    +  }
       
       @Test
       public void internalErrorDeprecatedJSON() {
    @@ -849,6 +861,17 @@ public void badRequestDeprecated() {
             query.response().getContent().toString(Charset.forName("UTF-8"))
             .substring(0, 15));
       }
    +
    +  @Test
    +  public void badRequestDeprecatedHTMLEscaped() {
    +    HttpQuery query = NettyMocks.getQuery(tsdb, "/");
    +    query.badRequest(new BadRequestException("<script>alert(document.cookie)</script>"));
    +
    +    assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
    +    assertTrue(query.response().getContent().toString(Charset.forName("UTF-8")).contains(
    +        "The reason provided was:<blockquote>&lt;script&gt;alert(document.cookie)&lt;/script&gt;"
    +    ));
    +  }
       
       @Test
       public void badRequestDeprecatedJSON() {
    
  • test/tsd/TestQueryRpc.java+2 2 modified
    @@ -518,7 +518,7 @@ public void postQueryNoMetricBadRequest() throws Exception {
         assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
         final String json =
             query.response().getContent().toString(Charset.forName("UTF-8"));
    -    assertTrue(json.contains("No such name for 'foo': 'metrics'"));
    +    assertTrue(json.contains("No such name for &#39;foo&#39;: &#39;metrics&#39;"));
       }
     
       @Test
    @@ -579,7 +579,7 @@ public void executeNSU() throws Exception {
         assertEquals(HttpResponseStatus.BAD_REQUEST, query.response().getStatus());
         final String json =
             query.response().getContent().toString(Charset.forName("UTF-8"));
    -    assertTrue(json.contains("No such name for 'foo': 'metrics'"));
    +    assertTrue(json.contains("No such name for &#39;foo&#39;: &#39;metrics&#39;"));
       }
     
       @Test
    

Vulnerability mechanics

Root cause

"User-supplied input reflected in HTTP error messages is not HTML-escaped, enabling reflected cross-site scripting (XSS)."

Attack vector

An attacker sends a crafted HTTP request to the legacy HTTP query API or logging endpoint that triggers an error whose message contains malicious JavaScript (e.g., `

Affected code

The vulnerability resides in `src/tsd/HttpQuery.java` in the `internalError()` and `badRequest()` methods. Both methods directly embed user-supplied exception messages (`pretty_exc` and `exception.getMessage()`) into HTML responses without escaping, allowing HTML/JavaScript injection.

What the fix does

The patch uses `HtmlEscapers.htmlEscaper().escape()` from the Guava library to sanitize the exception message before embedding it in the HTML response. In `internalError()`, `pretty_exc` is escaped into a `response` variable; in `badRequest()`, `exception.getMessage()` is similarly escaped. This converts characters like `

Preconditions

  • configThe OpenTSDB server must have the legacy HTTP query API or logging endpoint enabled (default configuration).
  • networkThe attacker must be able to send HTTP requests to the OpenTSDB instance (no authentication required).
  • inputThe attacker must craft a request that triggers an error whose message includes the malicious payload.

Generated on May 23, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.