Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/samples/calling/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,6 @@ async function initCalling(e) {
kmsInitialTimeout: 8000,
kmsMaxTimeout: 40000,
batcherMaxCalls: 30,
caroots: null,
},
dss: {},
},
Expand Down
10 changes: 10 additions & 0 deletions packages/@webex/internal-plugin-encryption/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
*/

import DEFAULT_KMS_CAROOTS from './kms-default-caroots';

export default {
encryption: {
/**
* PEM (base64 DER) encoded CA certificates trusted to sign the KMS
* static-key certificate chain. KMS validation fails closed when this
* list is empty; deployments MUST provide the Webex KMS issuing roots.
* @type {Array<string>}
*/
caroots: DEFAULT_KMS_CAROOTS,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve explicit CA-root overrides

When a consumer supplies config.encryption.caroots: [], WebexCore.initialize() combines it with these defaults using lodash merge, which retains both default array entries; a one-element custom root similarly retains the second GoDaddy root. Consequently, the new empty-root guard never fails closed for an explicit empty array, and private-KMS deployments cannot restrict trust to a single custom CA. Ensure this array is replaced rather than index-merged during configuration normalization.

Useful? React with 👍 / 👎.


joseOptions: {
compact: true,
contentAlg: 'A256GCM',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,14 @@ const validateKMS =
validateCommonName(certificates, jwt);
validatePublicCertificate(certificates, jwt);

// Skip validating signatures if no CA roots were provided
const promise = caroots
? validateCertificatesSignature(certificates, caroots)
: Promise.resolve();
// Fail closed: without trusted CA roots the x5c chain cannot be
// authenticated, and an attacker-supplied self-signed certificate
// would satisfy every other check above.
if (!isArray(caroots) || caroots.length === 0) {
throwError('no trusted CA roots configured; cannot validate KMS certificate chain');
}

return promise.then(() => jwt);
return validateCertificatesSignature(certificates, caroots).then(() => jwt);
});

export default validateKMS;

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {assert} from '@webex/test-helper-chai';

import config from '../../../src/config';
import validateCert, {KMSError, validateCommonName, X509_SUBJECT_ALT_NAME_KEY} from '../../../src/kms-certificate-validation';

const caroots = [
Expand Down Expand Up @@ -152,14 +153,29 @@ describe('internal-plugin-encryption', () => {
return assert.isRejected(validate(jwt), KMSError);
});

it('accepts self signed certificate if no CA roots.', () => {
it('rejects self-signed certificate when no CA roots are configured', () => {
const jwt = {
...VALID_JWT,
x5c: x5cSelfSigned,
n: x5cSelfSignedModulus,
};

return validateCert()(jwt).then((results) => assert.equal(results, jwt));
return assert.isRejected(validateCert([])(jwt), KMSError);
});

it('rejects self-signed certificate with default config caroots', () => {
const jwt = {
...VALID_JWT,
x5c: x5cSelfSigned,
n: x5cSelfSignedModulus,
};

return assert.isRejected(validateCert(config.encryption.caroots)(jwt), KMSError);
});

it('ships default trusted CA roots in encryption config', () => {
assert.isArray(config.encryption.caroots);
assert.isAbove(config.encryption.caroots.length, 0);
});
});
});
Expand Down
Loading