Dhairya-007 opened a new pull request, #29705:
URL: https://github.com/apache/camel/pull/29705

   ## Problem
   
   Four classes write credentials into their `toString()` in clear:
   
   | component | class | leaked |
   | --- | --- | --- |
   | camel-zendesk | `ZendeskConfiguration` | `password`, `token`, `oauthToken` 
|
   | camel-kubernetes | `KubernetesConfiguration` | `password`, `oauthToken`, 
`caCertData`, `clientCertData`, `clientKeyData`, `clientKeyPassphrase` |
   | camel-smpp | `SmppConfiguration` | `password`, `httpProxyPassword` |
   | camel-huaweicloud-dms | `CreateInstanceRequestBody` | `password`, 
`kafkaManagerPassword` |
   
   ```java
   // ZendeskConfiguration
   return String.format(
           "ZendeskConfiguration:[methodName=%s, serverUrl=%s, username=%s, 
password=%s, token=%s, oauthToken=%s]",
           methodName, serverUrl, username, password, token, oauthToken);
   ```
   
   Every one of those options is marked `secret: true` in the component's 
**own** generated metadata — I checked `zendesk.json`, `kubernetes-pods.json` 
and `smpp.json` — and `clientKeyData` is a private key. A configuration's 
`toString()` is not a private detail: it reaches a log file, a JMX attribute, a 
dev-console dump or an exception message without anyone deciding to publish it, 
so a secret flag has to hold there too.
   
   Camel already does this elsewhere, which is what makes these look like 
oversights rather than choices:
   
   ```java
   // camel-netty-http HttpPrincipal
   // do not display the password
   return "HttpPrincipal[" + username + "]";
   
   // camel-snmp SnmpEndpoint
   // only show address to avoid user and password details to be shown
   return "snmp://" + serverAddress;
   ```
   
   ## Fix
   
   Mask the credential material with `xxxxxx` — the mask `URISupport` already 
uses when it sanitizes a URI, chosen there because it also works well with JMX 
— and only when the value is non-null, so the line still says whether a 
credential was configured at all:
   
   ```java
   private static String mask(Object secret) {
       return secret != null ? "xxxxxx" : "null";
   }
   ```
   
   What *points at* the material stays readable — `masterUrl`, `serverUrl`, 
`username`, `systemId`, `caCertFile`, `clientKeyFile` — so the output is still 
useful for diagnosis. The distinction is deliberate: a path to a key file is 
not the key.
   
   `ZendeskConfiguration.hashCode()` is `toString().hashCode()`, so it becomes 
coarser: two configurations differing only in a password now hash alike. That 
is still consistent with `equals`, which keeps comparing the real values.
   
   `SmppConfigurationTest.toStringShouldListAllInstanceVariables` asserts the 
whole string with `password=null`, and still passes unchanged, because a null 
credential is still printed as `null`.
   
   ## Tests
   
   - `SmppConfigurationTest.toStringShouldNotLeakCredentials` — a set 
`password` and `httpProxyPassword` are masked, `systemId` is not.
   - `ZendeskConfigurationTest` — the three credentials are masked, `serverUrl` 
is not, and an unset credential still shows as `null`.
   - `KubernetesConfigurationTest` — the six credentials are masked, while 
`clientKeyFile` and `masterUrl` stay readable.
   
   Each asserts on the secret's literal value, so it fails on `main`.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to