@aikidosec/firewall
Version:
Zen by Aikido is an embedded Web Application Firewall that autonomously protects Node.js apps against common and critical attacks
52 lines (51 loc) • 2.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.looksLikeASecret = looksLikeASecret;
const getFileExtension_1 = require("./getFileExtension");
const LOWERCASE = "abcdefghijklmnopqrstuvwxyz".split("");
const UPPERCASE = LOWERCASE.map((char) => char.toUpperCase());
const NUMBERS = "0123456789".split("");
const SPECIAL = "!#$%^&*|;:<>".split("");
const KNOWN_WORD_SEPARATORS = ["-"];
const WHITE_SPACE = /\s+/;
const MINIMUM_LENGTH = 10;
function looksLikeASecret(str) {
if (str.length <= MINIMUM_LENGTH) {
return false;
}
const hasNumber = NUMBERS.some((char) => str.includes(char));
if (!hasNumber) {
return false;
}
const hasLower = LOWERCASE.some((char) => str.includes(char));
const hasUpper = UPPERCASE.some((char) => str.includes(char));
const hasSpecial = SPECIAL.some((char) => str.includes(char));
const charsets = [hasLower, hasUpper, hasSpecial];
// If the string doesn't have at least 2 different charsets, it's not a secret
if (charsets.filter((charset) => charset).length < 2) {
return false;
}
// If the string has white space, it's not a secret
if (WHITE_SPACE.test(str)) {
return false;
}
if (KNOWN_WORD_SEPARATORS.some((separator) => str.includes(separator))) {
return false;
}
// Ignore static assests with random file names, e.g. index.BRaz9DSe.css"
// The function shouldDiscoverRoutes already checks for this, but it's executed after this function, so the route would already be /asset/:secret
const extension = (0, getFileExtension_1.getFileExtension)(str);
if (extension && extension.length > 1 && extension.length < 6) {
return false;
}
// Check uniqueness of characters in a window of 10 characters
const windowSize = MINIMUM_LENGTH;
const ratios = [];
for (let i = 0; i <= str.length - windowSize; i++) {
const window = str.slice(i, i + windowSize);
const uniqueChars = new Set(window);
ratios.push(uniqueChars.size / windowSize);
}
const averageRatio = ratios.reduce((sum, ratio) => sum + ratio, 0) / ratios.length;
return averageRatio > 0.75;
}