VYPR
High severityNVD Advisory· Published Dec 24, 2020· Updated Aug 4, 2024

Template Injection in BrowserUp Proxy

CVE-2020-26282

Description

BrowserUp Proxy allows you to manipulate HTTP requests and responses, capture HTTP content, and export performance data as a HAR file. BrowserUp Proxy works well as a standalone proxy server, but it is especially useful when embedded in Selenium tests. A Server-Side Template Injection was identified in BrowserUp Proxy enabling attackers to inject arbitrary Java EL expressions, leading to unauthenticated Remote Code Execution (RCE) vulnerability. This has been patched in version 2.1.2.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
com.browserup:browserup-proxyMaven
< 2.1.22.1.2

Affected products

1

Patches

1
4b38e7a3e209

Fix Critical Java EL Injection RCE vulnerability from GHSL-2020-213

https://github.com/browserup/browserup-proxykirill.turutinDec 14, 2020via ghsa
5 files changed · +52 9
  • browserup-proxy-rest/src/main/java/com/browserup/bup/rest/validation/LongPositiveConstraint.java+6 3 modified
    @@ -8,6 +8,7 @@
     import javax.validation.ConstraintValidatorContext;
     import javax.validation.Payload;
     
    +import com.browserup.bup.rest.validation.util.MessageSanitizer;
     import org.slf4j.Logger;
     import org.slf4j.LoggerFactory;
     
    @@ -41,12 +42,14 @@ public boolean isValid(String value, ConstraintValidatorContext context) {
             longValue = Long.parseLong(value);
           } catch (NumberFormatException ex) {
             failed = true;
    -        errorMessage = String.format("Invalid integer value: '%s'", value);
    +        String escapedValue = MessageSanitizer.escape(value);
    +        errorMessage = String.format("Invalid integer value: '%s'", escapedValue);
           }
     
           if (!failed && longValue < 0) {
             failed = true;
    -        errorMessage = String.format("Expected positive integer value, got: '%s'", value);
    +        String escapedValue = MessageSanitizer.escape(value);
    +        errorMessage = String.format("Expected positive integer value, got: '%s'", escapedValue);
           }
     
           if (!failed) {
    @@ -59,4 +62,4 @@ public boolean isValid(String value, ConstraintValidatorContext context) {
           return false;
         }
       }
    -}
    \ No newline at end of file
    +}
    
  • browserup-proxy-rest/src/main/java/com/browserup/bup/rest/validation/NotBlankConstraint.java+5 2 modified
    @@ -8,6 +8,7 @@
     import javax.validation.ConstraintValidatorContext;
     import javax.validation.Payload;
     
    +import com.browserup.bup.rest.validation.util.MessageSanitizer;
     import org.apache.commons.lang3.StringUtils;
     import org.slf4j.Logger;
     import org.slf4j.LoggerFactory;
    @@ -36,11 +37,13 @@ public boolean isValid(Object value, ConstraintValidatorContext context) {
           if (value != null && StringUtils.isNotEmpty(String.valueOf(value))) {
             return true;
           }
    -      String errorMessage = String.format("Expected not empty value, got '%s'", value);
    +
    +      String escapedValue = MessageSanitizer.escape(value == null ? null : value.toString());
    +      String errorMessage = String.format("Expected not empty value, got '%s'", escapedValue);
           LOG.warn(errorMessage);
     
           context.buildConstraintViolationWithTemplate(errorMessage).addConstraintViolation();
           return false;
         }
       }
    -}
    \ No newline at end of file
    +}
    
  • browserup-proxy-rest/src/main/java/com/browserup/bup/rest/validation/PatternConstraint.java+4 2 modified
    @@ -9,6 +9,7 @@
     import javax.validation.ConstraintValidatorContext;
     import javax.validation.Payload;
     
    +import com.browserup.bup.rest.validation.util.MessageSanitizer;
     import org.apache.commons.lang3.StringUtils;
     import org.slf4j.Logger;
     import org.slf4j.LoggerFactory;
    @@ -42,12 +43,13 @@ public boolean isValid(String value, ConstraintValidatorContext context) {
             Pattern.compile(value);
             return true;
           } catch (Exception ex) {
    -        String errorMessage = String.format("URL parameter '%s' is not a valid regexp", value);
    +        String escapedValue = MessageSanitizer.escape(value);
    +        String errorMessage = String.format("URL parameter '%s' is not a valid regexp", escapedValue);
             LOG.warn(errorMessage);
     
             context.buildConstraintViolationWithTemplate(errorMessage).addConstraintViolation();
           }
           return false;
         }
       }
    -}
    \ No newline at end of file
    +}
    
  • browserup-proxy-rest/src/main/java/com/browserup/bup/rest/validation/PortWithExistingProxyConstraint.java+4 2 modified
    @@ -11,6 +11,7 @@
     
     import com.browserup.bup.proxy.ProxyManager;
     
    +import com.browserup.bup.rest.validation.util.MessageSanitizer;
     import org.slf4j.Logger;
     import org.slf4j.LoggerFactory;
     
    @@ -47,11 +48,12 @@ public boolean isValid(Integer value, ConstraintValidatorContext context) {
             return true;
           }
     
    -      String errorMessage = String.format("No proxy server found for specified port %d", value);
    +      String escapedValue = MessageSanitizer.escape(value.toString());
    +      String errorMessage = String.format("No proxy server found for specified port %s", escapedValue);
           LOG.warn(errorMessage);
     
           context.buildConstraintViolationWithTemplate(errorMessage).addPropertyNode(PARAM_NAME).addConstraintViolation();
           return false;
         }
       }
    -}
    \ No newline at end of file
    +}
    
  • browserup-proxy-rest/src/main/java/com/browserup/bup/rest/validation/util/MessageSanitizer.java+33 0 added
    @@ -0,0 +1,33 @@
    +package com.browserup.bup.rest.validation.util;
    +/*
    + * Modifications Copyright (c) 2019 BrowserUp, Inc.
    + * Original from:
    + * https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/util/InterpolationHelper.java
    + */
    +/*
    + * License: Apache License, Version 2.0
    + * See the license file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
    + */
    +
    +import java.util.regex.Matcher;
    +import java.util.regex.Pattern;
    +
    +public class MessageSanitizer {
    +
    +  public static final char BEGIN_CHAR = '{';
    +  public static final char END_CHAR = '}';
    +  public static final char EL_DESIGNATOR = '$';
    +  public static final char ESCAPE_CHARACTER = '\\';
    +
    +  private static final Pattern ESCAPE_PATTERN = Pattern.compile( "([\\" + ESCAPE_CHARACTER + BEGIN_CHAR + END_CHAR + EL_DESIGNATOR + "])" );
    +
    +  private MessageSanitizer() {
    +  }
    +
    +  public static String escape(String message) {
    +    if ( message == null ) {
    +      return null;
    +    }
    +    return ESCAPE_PATTERN.matcher( message ).replaceAll( Matcher.quoteReplacement( String.valueOf( ESCAPE_CHARACTER ) ) + "$1" );
    +  }
    +}
    

Vulnerability mechanics

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

References

6

News mentions

0

No linked articles in our index yet.