UNPKG

@microsoft/eslint-plugin-sdl

Version:

ESLint plugin focused on common security issues and misconfigurations discoverable during static testing as part of Microsoft Security Development Lifecycle (SDL)

97 lines (86 loc) 2.89 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. /** * @fileoverview Rule to disallow call to Math.random and crypto.pseudoRandomBytes functions * @author Antonios Katopodis */ "use strict"; const astUtils = require("../ast-utils"); const path = require("path"); const bannedRandomLibraries = [ "chance", "random-number", "random-int", "random-float", "random-seed", "unique-random" ]; module.exports = { meta: { type: "suggestion", fixable: "code", schema: [], docs: { description: `Methods such as Math.random or crypto.pseudoRandomBytes do not produce cryptographically-secure random numbers and must not be used for security purposes such as generating tokens, passwords or keys. Use crypto.randomBytes() or window.crypto.getRandomValues() instead. `, url: "https://github.com/microsoft/eslint-plugin-sdl/blob/master/docs/rules/no-insecure-random.md" }, messages: { default: "Do not use pseudo-random number generators for generating secret values such as tokens, passwords or keys." } }, create: function (context) { const fullTypeChecker = astUtils.getFullTypeChecker(context); return { "CallExpression > MemberExpression[property.name='pseudoRandomBytes']"(node) { var notFalsePositive = false; if (fullTypeChecker) { const type = astUtils.getNodeTypeAsString(fullTypeChecker, node.object, context); notFalsePositive = type === "any" || type === "Crypto"; } else { notFalsePositive = node.object.name === "crypto"; } if (notFalsePositive) { context.report({ node: node, messageId: "default" }); } }, "CallExpression > MemberExpression[property.name='random']"(node) { var notFalsePositive = false; if (fullTypeChecker) { const type = astUtils.getNodeTypeAsString(fullTypeChecker, node.object, context); notFalsePositive = type === "any" || type === "Math"; } else { notFalsePositive = node.object.name === "Math"; } if (notFalsePositive) { context.report({ node: node, messageId: "default" }); } }, ImportDeclaration(node) { if (bannedRandomLibraries.includes(path.basename(node.source.value))) { context.report({ node: node, messageId: "default" }); } }, "CallExpression[callee.name='require'][arguments.length=1]"(node) { var requireName = path.parse(path.basename(node.arguments[0].value)).name; if (bannedRandomLibraries.includes(requireName)) { context.report({ node: node, messageId: "default" }); } } }; } };