Named Credential – Merge fields in managed package

I’m working on a managed package where a requirement, out of our hands, is to authenticate to a SOAP API via WS-Security. I was hoping we’d take the strategy of using Named Credentials. This would require us to use merge fields (as documented here https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_named_credentials_merge_fields.htm). Since the WS-Security XML header is in the HTTP request body, the named credential needs to have the “Allow Merge Fields in HTTP Body” option ticked.

It’s occurred to me though, there could be a security risk here. These API calls will contain data mapped by an administrator to send from records in their org. If user were to include the text {!$Credential.Password} somewhere in a text field of a record, oops, now that password would be substituted somewhere it shouldn’t be.

Would it be wisest to sanitize the rest of the request body to avoid this? Any user data would definitely come after the XML header so I could, for example, check if xmlString.countMatches('$Credential') > 2. And if so, either throw an error or replace it with something safe.

And for that matter, would it be a Security Review concern if our package will only work when the Named Credential “Allow Merge Fields in HTTP Body” is ticked?

Answer

I don’t know if it’s “best”, and I can’t speak for the security review process, but if I were in your shoes, I would escape all merge syntax entirely. It’s hard to see a valid reason to support it.

Below is a simple example of what I would do, posted as an anonymous script.

public static String escapeMergeSyntax(String input)
{
    return input == null ? input : input.replaceAll('\\{!(.+?)\\}', '[$1]');
}

String body = 'Some content {!Credential.Password} and other {!mergeFields}';
// assume body is untrusted subscriber input

body = escapeMergeSyntax(body);
// now the subscribe input should be unable to expose your credentials

system.debug(body);

One note about regular expressions, you need to set the single-line flag or users can inject whitespace to work around your escaping. I’m not certain, but I think the compiler would just ignore these newline characters and proceed with merging in the sensitive data. Try this input with and without the flag set:

public static String escapeMergeSyntax(String input)
{
    return input == null ? input : input.replaceAll('(?s)\\{!(.+?)\\}', '[$1]');
}

String body = 'Some content {!\nCredential.Password\n} and other {!mergeFields}';
//                            ^^ clever users may try to inject whitespace

body = escapeMergeSyntax(body);
// setting the (?s) single-line flag will make sure dot matches newline

system.debug(body);

Attribution
Source : Link , Question Author : Charles T , Answer Author : Adrian Larson

Leave a Comment