Description
When using WSSecurityCert without any other SOAP headers (addSoapHeader), the <wsse:Security> block and <ds:Signature> are placed outside the <soap:Envelope> instead of inside <soap:Header>.
Root Cause
In client.ts, the <soap:Header> element is only created if this.security.toXML() returns a truthy value:
|
(decodedHeaders || (this.security && this.security.toXML()) |
|
? '<' + |
|
envelopeKey + |
|
':Header' + |
|
(this.wsdl.xmlnsInHeader ? ' ' + this.wsdl.xmlnsInHeader : '') + |
|
'>' + |
|
(decodedHeaders ? decodedHeaders : '') + |
|
(this.security && !this.security.postProcess ? this.security.toXML() : '') + |
|
'</' + |
|
envelopeKey + |
|
':Header>' |
|
: '') + |
WSSecurityCert does not implement toXML(), so the fallback () => '' is used (line 358):
|
if (this.security && typeof this.security?.toXML !== 'function') { |
|
this.security.toXML = () => ''; |
|
} |
Since '' is falsy, the Header element is never created. Then WSSecurityCert.postProcess looks for </${envelopeKey}:Header> to insert the Security block, but it doesn't exist. The indexOf returns -1 and insertStr places the content at the wrong position — outside the Envelope.
Steps to Reproduce
- Create a SOAP client with
WSSecurityCert as the only security mechanism.
- Do NOT call
addSoapHeader().
- Invoke any SOAP method.
- Inspect the raw XML request — the
<wsse:Security> block is outside <soap:Envelope>.
Expected Behavior
The <soap:Header> element should always be created when a security mechanism with postProcess is set, so that WSSecurityCert.postProcess can correctly insert the Security block inside it.
Suggested Fix
Either:
- Have
WSSecurityCert implement toXML() returning a truthy placeholder (e.g. ' ') that triggers Header creation, or
- Change the condition in client.js to also check for the presence of
postProcess:
(decodedHeaders || (this.security && (this.security.toXML() || this.security.postProcess))
? '<' + envelopeKey + ':Header>...</' + envelopeKey + ':Header>'
: '')
Workaround
const security = new soap.WSSecurityCert(privatePEM, publicPEM, password, options);
security.toXML = () => ' ';
client.setSecurity(security);
Environment
soap version: 1.9.1
- Node.js version: 22.x
- OS: Windows
Description
When using
WSSecurityCertwithout any other SOAP headers (addSoapHeader), the<wsse:Security>block and<ds:Signature>are placed outside the<soap:Envelope>instead of inside<soap:Header>.Root Cause
In
client.ts, the<soap:Header>element is only created ifthis.security.toXML()returns a truthy value:node-soap/src/client.ts
Lines 447 to 458 in 78a71cb
WSSecurityCertdoes not implementtoXML(), so the fallback() => ''is used (line 358):node-soap/src/client.ts
Lines 409 to 411 in 78a71cb
Since
''is falsy, the Header element is never created. ThenWSSecurityCert.postProcesslooks for</${envelopeKey}:Header>to insert the Security block, but it doesn't exist. TheindexOfreturns-1andinsertStrplaces the content at the wrong position — outside the Envelope.Steps to Reproduce
WSSecurityCertas the only security mechanism.addSoapHeader().<wsse:Security>block is outside<soap:Envelope>.Expected Behavior
The
<soap:Header>element should always be created when a security mechanism withpostProcessis set, so thatWSSecurityCert.postProcesscan correctly insert the Security block inside it.Suggested Fix
Either:
WSSecurityCertimplementtoXML()returning a truthy placeholder (e.g.' ') that triggers Header creation, orpostProcess:Workaround
Environment
soapversion: 1.9.1