When dealing with WSO2 ESB projects, you have to be especially careful with headers, for a lot of sensitive data might leak through them. Let’s take an example. Here we have a typical usage of the ESB: expose a REST API to interface some services with a legacy SOAP back-end after some mapping.

        | ==========> |      | ===========> |
Client  |             | ESB  |              | SOAP backend
        | <========== |      | <=========== |

The backend access is protected with a Basic authentication. Basically, it requires to add Base64(name_or_the_user:his_password) to the Authorization header; like so:

<api context="/constructionSite" 
name="crm4sap-constructionSiteApi" 
statistics="enable" 
trace="enable" 
xmlns="http://ws.apache.org/ns/synapse">
    <resource faultSequence="crm4sap-errors" methods="POST">
        <inSequence>
            <sequence key="crm4sap-readEnvVars"/>
            <datamapper config="gov:datamapper/map-constructionSite.dmc" 
            inputSchema="gov:datamapper/map-constructionSite_inputSchema.json" 
            inputType="JSON" 
            outputSchema="gov:datamapper/map-constructionSite_outputSchema.json" 
            outputType="XML" 
            xsltStyleSheet="gov:datamapper/map-constructionSite_xsltStyleSheet.xml"/>
            <log level="full"/>
            <header description="Authorization" 
            expression="fn:concat('Basic ', base64Encode(fn:concat($ctx:sap_user,':',$ctx:sap_password)))" 
            name="Authorization" 
            scope="transport"/>
            <send>
                <endpoint key="gov:endpoints/sap_constructionSite.xml"/>
            </send>
        </inSequence>
        <outSequence>
            <property name="messageType" scope="axis2" type="STRING" value="application/json"/>
            <respond/>
        </outSequence>
    </resource>
</api>

Now, let’s have a look at the answer

curl -X POST "http://127.0.0.1:8280/constructionSite" --data @env_dev/inputs/input_rsa1.json \ 
-H "Content-Type: application/json" -v
Note: Unnecessary use of -X or --request, POST is already inferred.
  Trying 127.0.0.1...
TCP_NODELAY set
Connected to 127.0.0.1 (127.0.0.1) port 8280 (#0)
POST /constructionSite HTTP/1.1
Host: 127.0.0.1:8280
User-Agent: curl/7.55.1
Accept: */*
Content-Type: application/json
Content-Length: 1306
Expect: 100-continue
HTTP/1.1 100 Continue
We are completely uploaded and fine
HTTP/1.1 200 OK
Authorization: Basic YnRjaF9jcm06c29tZV9wYXNzd29yZA==  # DANGER ZONE
activityid: 8370fee1-6189-400e-a28e-2c29bfbd654e
Accept: */*
Expect: 100-continue
Host: 127.0.0.1:8280
Content-Type: application/json; charset=UTF-8
Date: Fri, 05 Jun 2020 08:40:52 GMT
Transfer-Encoding: chunked
{"response":"some response"}* Connection #0 to host 127.0.0.1 left intact

As you can see, headers of the request send to the back-end are implicitly inherited by the out sequence. This is how we end up with the back-end credentials in the Authorization This sucks! Unfortunately, you explicitly have to remove those headers before sending anything back to the client (same goes with transport.vfs variables that can be even more tricky), like so

<api context="/constructionSite" 
name="crm4sap-constructionSiteApi" 
statistics="enable" 
trace="enable" 
xmlns="http://ws.apache.org/ns/synapse">
    <resource faultSequence="crm4sap-errors" methods="POST">
        <inSequence>
            <sequence key="crm4sap-readEnvVars"/>
            <log level="full"/>
            <datamapper config="gov:datamapper/map-constructionSite.dmc" 
            inputSchema="gov:datamapper/map-constructionSite_inputSchema.json" 
            inputType="JSON" 
            outputSchema="gov:datamapper/map-constructionSite_outputSchema.json" 
            outputType="XML" 
            xsltStyleSheet="gov:datamapper/map-constructionSite_xsltStyleSheet.xml"/>
            <log level="full"/>
            <header description="Authorization" 
            expression="fn:concat('Basic ', base64Encode(fn:concat($ctx:sap_user,':',$ctx:sap_password)))" 
            name="Authorization" 
            scope="transport"/>
            <send>
                <endpoint key="gov:endpoints/sap_constructionSite.xml"/>
            </send>
        </inSequence>
        <outSequence>
            <property name="Authorization" scope="transport" action="remove"/> #HERE
            <property name="messageType" scope="axis2" type="STRING" value="application/json"/>
            <respond/>
        </outSequence>
    </resource>
</api>

This way, the back-end’s credentials are safe

curl -X POST "http://127.0.0.1:8280/constructionSite" --data @env_dev/inputs/input_rsa1.json \
-H "Content-Type: application/json" -v
Note: Unnecessary use of -X or --request, POST is already inferred.
  Trying 127.0.0.1...
TCP_NODELAY set
Connected to 127.0.0.1 (127.0.0.1) port 8280 (#0)
POST /constructionSite HTTP/1.1
Host: 127.0.0.1:8280
User-Agent: curl/7.55.1
Accept: */*
Content-Type: application/json
Content-Length: 1306
Expect: 100-continue
HTTP/1.1 100 Continue
We are completely uploaded and fine
HTTP/1.1 200 OK
activityid: 532851ed-1763-45b2-84fb-1b07b4983512
Accept: */*
Expect: 100-continue
Host: 127.0.0.1:8280
Content-Type: application/json; charset=UTF-8
Date: Fri, 05 Jun 2020 12:51:35 GMT
Transfer-Encoding: chunked
{"response":"some response"}* Connection #0 to host 127.0.0.1 left intact