diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/jdbc/JDBCConnectionUrlParser.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/jdbc/JDBCConnectionUrlParser.java index 2eaccd81400..0f08e5019b7 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/jdbc/JDBCConnectionUrlParser.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/jdbc/JDBCConnectionUrlParser.java @@ -36,9 +36,16 @@ DBInfo.Builder doParse(final String jdbcUrl, final DBInfo.Builder builder) { populateStandardProperties(builder, splitQuery(uri.getQuery(), '&')); - final String user = uri.getUserInfo(); - if (user != null) { - builder.user(user); + final String rawUserInfo = uri.getRawUserInfo(); + if (rawUserInfo != null) { + // rawUserInfo keeps %3A encoded, so indexOf(':') only matches the password separator + final int colonLoc = rawUserInfo.indexOf(':'); + final String rawUser = colonLoc >= 0 ? rawUserInfo.substring(0, colonLoc) : rawUserInfo; + try { + builder.user(URLDecoder.decode(rawUser, "UTF-8")); + } catch (final UnsupportedEncodingException e) { + builder.user(rawUser); + } } String path = uri.getPath(); diff --git a/dd-java-agent/agent-bootstrap/src/test/java/datadog/trace/bootstrap/instrumentation/jdbc/JDBCConnectionUrlParserPasswordLeakTest.java b/dd-java-agent/agent-bootstrap/src/test/java/datadog/trace/bootstrap/instrumentation/jdbc/JDBCConnectionUrlParserPasswordLeakTest.java new file mode 100644 index 00000000000..2da05fd7846 --- /dev/null +++ b/dd-java-agent/agent-bootstrap/src/test/java/datadog/trace/bootstrap/instrumentation/jdbc/JDBCConnectionUrlParserPasswordLeakTest.java @@ -0,0 +1,23 @@ +package datadog.trace.bootstrap.instrumentation.jdbc; + +import static datadog.trace.bootstrap.instrumentation.jdbc.JDBCConnectionUrlParser.extractDBInfo; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.tabletest.junit.TableTest; + +class JDBCConnectionUrlParserPasswordLeakTest { + + @TableTest({ + "scenario | url | type | host | user ", + "PostgreSQL userinfo with password | jdbc:postgresql://myuser:secret123@pg.host/mydb | postgresql | pg.host | myuser ", + "PostgreSQL userinfo without password | jdbc:postgresql://myuser@pg.host/mydb | postgresql | pg.host | myuser ", + "PostgreSQL userinfo with percent-encoded colon | jdbc:postgresql://tenant%3Aalice@pg.host/mydb | postgresql | pg.host | tenant:alice", + "SAP userinfo with password | jdbc:sap://myuser:secret@sap.host/sapdb | sap | sap.host | myuser " + }) + void passwordShouldNotLeakIntoUserTag(String url, String type, String host, String user) { + DBInfo info = extractDBInfo(url, null); + assertEquals(type, info.getType()); + assertEquals(host, info.getHost()); + assertEquals(user, info.getUser()); + } +}