diff --git a/README.md b/README.md index 36eb40939..6f63c5651 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@

Bearer CLI is a static application security testing (SAST) tool that scans your source code and analyzes your data flows to discover, filter and prioritize security and privacy risks.

- Currently supporting: JavaScript/TypeScript (GA), Ruby (GA), Java (Beta), PHP (Beta), Go (Alpha), Python (Alpha) - Learn more + Currently supporting: JavaScript/TypeScript (GA), Ruby (GA), Java (Beta), PHP (Beta), Go (Beta), Python (Alpha) - Learn more

@@ -259,17 +259,17 @@ Bearer CLI currently supports: - + - + - + -
GAJavaScript/TypeScript, RubyJavaScript/TypeScript, Ruby
BetaJava, PHPJava, PHP
AlphaGo, PythonGo, Python
+ [Learn more](https://docs.bearer.com/reference/supported-languages/) about language support. diff --git a/docs/.eleventy.js b/docs/.eleventy.js index 1553593ff..c478660b0 100644 --- a/docs/.eleventy.js +++ b/docs/.eleventy.js @@ -51,10 +51,10 @@ module.exports = function (eleventyConfig) { return now }) eleventyConfig.addShortcode("sectionLinks", function (sectionName) { - const section = nav.find(item => item.name == sectionName) + const section = nav.find((item) => item.name == sectionName) let out = "" - if(section){ - section.items.forEach(item => { + if (section) { + section.items.forEach((item) => { out += `- [${item.name}](${item.url})\n` }) } @@ -63,19 +63,24 @@ module.exports = function (eleventyConfig) { }) // {% yamlExample "ci/gitlab/basic" %} - eleventyConfig.addShortcode('yamlExample', function (exampleName) { - const example = fs.readFileSync(`./_data/examples/${exampleName}.yaml`, 'utf8') - return '```yaml\n' + example + '\n```'; - }); + eleventyConfig.addShortcode("yamlExample", function (exampleName) { + const example = fs.readFileSync( + `./_data/examples/${exampleName}.yaml`, + "utf8" + ) + return "```yaml\n" + example + "\n```" + }) - eleventyConfig.addShortcode('githubAction', function(data){ + eleventyConfig.addShortcode("githubAction", function (data) { out = "| Option | Description | Default |\n" out += "| - | - | - |\n" - Object.keys(data).sort().forEach(key => { - const item = data[key] - const default_val = item.default ? "`"+item.default+"`" : "" - out += `| **${key}** | ${item.description} | ${default_val} |\n` - }); + Object.keys(data) + .sort() + .forEach((key) => { + const item = data[key] + const default_val = item.default ? "`" + item.default + "`" : "" + out += `| **${key}** | ${item.description} | ${default_val} |\n` + }) return out }) @@ -178,8 +183,7 @@ module.exports = function (eleventyConfig) { const target = parent.split(path.sep).slice(1, -1) const check = child.split(path.sep).slice(1, -1) // handles individual rule pages highlighting "rule" in side nav - const isRule = - target.includes("rules") && check[check.length - 2] === "rules" + const isRule = target.includes("rules") if (child === parent || isRule) { return true } else { diff --git a/docs/_data/rules.js b/docs/_data/rules.js index b9eaede57..f2f9d0002 100644 --- a/docs/_data/rules.js +++ b/docs/_data/rules.js @@ -1,31 +1,33 @@ -const { readFile, readdir } = require("node:fs/promises"); -const { statSync } = require("fs"); -const EleventyFetch = require("@11ty/eleventy-fetch"); -const path = require("path"); -const yaml = require("js-yaml"); -const cweList = require("./cweList.json"); -const gitly = require("gitly"); -const source = "bearer/bearer-rules"; -const rulesPath = "_tmp/rules-data"; -const excludeDirectories = [".github", "scripts"]; +const { readFile, readdir } = require("node:fs/promises") +const { statSync } = require("fs") +const EleventyFetch = require("@11ty/eleventy-fetch") +const path = require("path") +const yaml = require("js-yaml") +const cweList = require("./cweList.json") +const gitly = require("gitly") +const source = "bearer/bearer-rules" +const rulesPath = "_tmp/rules-data" +const excludeDirectories = [".github", "scripts"] let counts = { languages: {}, -}; +} function updateCounts(lang, framework = null, id = null) { if (framework !== null) { if (counts.languages[lang].frameworks[framework]) { - counts.languages[lang].frameworks[framework].count++; - counts.languages[lang].frameworks[framework].rules.push(id); + counts.languages[lang].frameworks[framework].count++ + counts.languages[lang].frameworks[framework].rules.push(id) + } else if (framework === "gosec") { + newFramework(lang, framework) } else if (framework !== "lang") { - newFramework(lang, framework); + newFramework(lang, framework) } else if (framework === "lang") { - counts.languages[lang].baseRules.push(id); + counts.languages[lang].baseRules.push(id) } - counts.languages[lang].count++; + counts.languages[lang].count++ } else { - newLang(lang); + newLang(lang) } } @@ -34,7 +36,7 @@ function newFramework(lang, name) { name, count: 1, rules: [], - }; + } } function newLang(name) { @@ -43,16 +45,16 @@ function newLang(name) { count: 0, baseRules: [], frameworks: {}, - }; + } } function isDirectory(dir) { - const result = statSync(dir); - return result.isDirectory(); + const result = statSync(dir) + return result.isDirectory() } async function fetchRelease() { - let latest = {}; + let latest = {} try { latest = await EleventyFetch( `https://api.github.com/repos/${source}/releases/latest`, @@ -60,76 +62,102 @@ async function fetchRelease() { duration: "60m", type: "json", } - ); + ) } catch (e) { - console.error(e); + console.error(e) } try { - let src = await gitly.download(`${source}#${latest.tag_name}`); - await gitly.extract(src, rulesPath); + let src = await gitly.download(`${source}#${latest.tag_name}`) + await gitly.extract(src, rulesPath) } catch (e) { - throw console.error(e); + throw console.error(e) } } async function fetchData(location) { - let rules = []; + let rules = [] try { - const dirs = await readdir(location); + const dirs = await readdir(location) // ex: looping through rules [ruby, gitleaks, sql] dirs.forEach(async (dir) => { - const dirPath = path.join(location, dir); + const dirPath = path.join(location, dir) if (isDirectory(dirPath) && !excludeDirectories.includes(dir)) { - const subDirs = await readdir(dirPath); - updateCounts(dir); + const subDirs = await readdir(dirPath) + updateCounts(dir) // ex. looping through rules/ruby [lang, rails] subDirs.forEach(async (subDir) => { - const subDirPath = path.join(dirPath, subDir); - if (isDirectory(subDirPath) && subDir !== "shared") { - const files = await readdir(subDirPath); + const subDirPath = path.join(dirPath, subDir) + if ( + isDirectory(subDirPath) && + subDir !== "shared" && + subDir !== "gosec" + ) { + const files = await readdir(subDirPath) const children = await fetchAllFiles( subDirPath, path.join(dir, subDir), files - ); - rules.push(...children); + ) + rules.push(...children) + } else if (isDirectory(subDirPath) && subDir === "gosec") { + const groupDirs = await readdir(subDirPath) + + groupDirs.forEach(async (groupDir) => { + const groupDirPath = path.join(dirPath, subDir, groupDir) + if (isDirectory(groupDirPath)) { + const files = await readdir(groupDirPath) + const children = await fetchAllFiles( + groupDirPath, + path.join(dir, subDir, groupDir), + files + ) + rules.push(...children) + } + }) } - }); + }) } - }); - return { counts, rules }; + }) + return { counts, rules } } catch (err) { - throw err; + throw err } } async function fetchAllFiles(directory, breadcrumb, files) { let result = await Promise.all( files.reduce((all, file) => { - const location = path.join(directory, file); + const location = path.join(directory, file) if (path.extname(location) === ".yml") { - return [...all, fetchFile(path.join(directory, file), breadcrumb)]; + return [...all, fetchFile(path.join(directory, file), breadcrumb)] } else { - return all; + return all } }, []) - ); - return result; + ) + return result } async function fetchFile(location, breadcrumb) { return readFile(location, { encoding: "utf8" }).then((file) => { - let out = yaml.load(file); - let owasps = new Set(); - let subdir = breadcrumb.split("/"); - let framework = subdir[subdir.length - 1]; - updateCounts(subdir[subdir.length - 2], framework, out.metadata.id); + let out = yaml.load(file) + let owasps = new Set() + let subdir = breadcrumb.split("/") + let groupId = subdir[subdir.length - 2] + let framework = subdir[subdir.length - 1] + let lang = subdir[subdir.length - 2] + if (groupId === "gosec") { + framework = groupId + lang = subdir[subdir.length - 3] + } + + updateCounts(lang, framework, out.metadata.id) if (out.metadata.cwe_id) { out.metadata.cwe_id.forEach((i) => { - if (cweList[i].owasp) { - owasps.add(cweList[i].owasp.id); + if (cweList[i] && cweList[i].owasp) { + owasps.add(cweList[i].owasp.id) } - }); + }) } return { name: path.basename(location, ".yml"), @@ -137,11 +165,11 @@ async function fetchFile(location, breadcrumb) { owasp_ids: [...owasps].sort(), framework, ...out, - }; - }); + } + }) } module.exports = async function () { - await fetchRelease(); - return await fetchData(path.join(rulesPath, "rules")); -}; + await fetchRelease() + return await fetchData(path.join(rulesPath, "rules")) +}