eslint-plugin-sonarjs
Version:
SonarJS rules for ESLint
101 lines (100 loc) • 5.11 kB
JavaScript
/*
* SonarQube JavaScript Plugin
* Copyright (C) 2011-2025 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Sonar Source-Available License for more details.
*
* You should have received a copy of the Sonar Source-Available License
* along with this program; if not, see https://sonarsource.com/license/ssal/
*/
// https://sonarsource.github.io/rspec/#/rspec/S5659/javascript
Object.defineProperty(exports, "__esModule", { value: true });
exports.rule = void 0;
const index_js_1 = require("../helpers/index.js");
const meta_js_1 = require("./meta.js");
exports.rule = {
meta: (0, index_js_1.generateMeta)(meta_js_1.meta, undefined, true),
create(context) {
const SIGN_MESSAGE = 'Use only strong cipher algorithms when signing this JWT.';
const VERIFY_MESSAGE = 'Use only strong cipher algorithms when verifying the signature of this JWT.';
const SECONDARY_MESSAGE = `The "algorithms" option should be defined and should not contain 'none'.`;
function checkCallToSign(callExpression, thirdArgumentValue, secondaryLocations) {
const unsafeAlgorithmProperty = (0, index_js_1.getPropertyWithValue)(context, thirdArgumentValue, 'algorithm', 'none');
if (unsafeAlgorithmProperty) {
const unsafeAlgorithmValue = (0, index_js_1.getValueOfExpression)(context, unsafeAlgorithmProperty.value, 'Literal');
if (unsafeAlgorithmValue && unsafeAlgorithmValue !== unsafeAlgorithmProperty.value) {
secondaryLocations.push(unsafeAlgorithmValue);
}
raiseIssueOn(callExpression.callee, SIGN_MESSAGE, secondaryLocations);
}
}
function checkCallToVerify(callExpression, publicKey, thirdArgumentValue, secondaryLocations) {
const algorithmsProperty = (0, index_js_1.getProperty)(thirdArgumentValue, 'algorithms', context);
if (!algorithmsProperty) {
if ((0, index_js_1.isNullLiteral)(publicKey)) {
raiseIssueOn(callExpression.callee, VERIFY_MESSAGE, secondaryLocations);
}
return;
}
const algorithmsValue = (0, index_js_1.getValueOfExpression)(context, algorithmsProperty.value, 'ArrayExpression');
if (!algorithmsValue) {
return;
}
const algorithmsContainNone = algorithmsValue.elements.some(e => {
const value = (0, index_js_1.getValueOfExpression)(context, e, 'Literal');
return value?.value === 'none';
});
if (algorithmsContainNone) {
if (algorithmsProperty.value !== algorithmsValue) {
secondaryLocations.push(algorithmsValue);
}
raiseIssueOn(callExpression.callee, VERIFY_MESSAGE, secondaryLocations);
}
}
function raiseIssueOn(node, message, secondaryLocations) {
(0, index_js_1.report)(context, {
node,
message,
}, secondaryLocations.map(node => (0, index_js_1.toSecondaryLocation)(node, SECONDARY_MESSAGE)));
}
return {
CallExpression: (node) => {
const callExpression = node;
const fqn = (0, index_js_1.getFullyQualifiedName)(context, callExpression);
const isCallToSign = fqn === 'jsonwebtoken.sign';
const isCallToVerify = fqn === 'jsonwebtoken.verify';
if (!isCallToSign && !isCallToVerify) {
return;
}
if (callExpression.arguments.length < 3) {
// algorithm(s) property is contained in third argument of "sign" and "verify" calls
return;
}
const thirdArgument = callExpression.arguments[2];
const thirdArgumentValue = (0, index_js_1.getValueOfExpression)(context, thirdArgument, 'ObjectExpression');
if (!thirdArgumentValue) {
return;
}
const secondaryLocations = [thirdArgumentValue];
if (thirdArgumentValue !== thirdArgument) {
secondaryLocations.push(thirdArgument);
}
if (isCallToSign) {
checkCallToSign(callExpression, thirdArgumentValue, secondaryLocations);
}
const secondArgument = callExpression.arguments[1];
if (isCallToVerify) {
checkCallToVerify(callExpression, secondArgument, thirdArgumentValue, secondaryLocations);
}
},
};
},
};
;