From 81fbbc1ca3dc8a0f026d95392e335c613c51003b Mon Sep 17 00:00:00 2001 From: Daniel Wright Date: Mon, 7 Aug 2023 13:10:53 +1000 Subject: [PATCH] fix: update the base commit trufflehog starts checking from --- action.yaml | 4 + index.js | 223 +++++++++++++--------------- node_modules/jsonparse/package.json | 23 +-- 3 files changed, 122 insertions(+), 128 deletions(-) diff --git a/action.yaml b/action.yaml index cf53cd0..6716b38 100644 --- a/action.yaml +++ b/action.yaml @@ -1,6 +1,10 @@ name: Trufflehog PR Commenter description: Take trufflehog JSON output and comment violations on a PR inputs: + commit: + description: The commit from which to check + required: true + default: ${{ github.event.repository.default_branch }} secrets-file: description: Path to save Trufflehog JSON output required: true diff --git a/index.js b/index.js index 2febff5..01cb740 100644 --- a/index.js +++ b/index.js @@ -1,13 +1,14 @@ const axios = require("axios"); const core = require("@actions/core"); const exec = require("@actions/exec"); -const fs = require('fs'); +const fs = require("fs"); const tar = require("tar"); const { Octokit } = require("@octokit/rest"); const token = process.env["GITHUB_TOKEN"]; const octokit = new Octokit({ auth: `token ${token}` }); +const commit = core.getInput("commit"); const filePath = core.getInput("secrets-file"); async function downloadFile(url, outputPath) { @@ -20,6 +21,79 @@ async function downloadFile(url, outputPath) { }); } +async function checkForSecrets() { + let secretsDetected = false; + + const data = await fs.promises.readFile(filePath, "utf8"); + if (!data || data.trim().length === 0) { + console.log("No data or empty file found, skipping processing..."); + return secretsDetected; + } + + const jsonData = JSON.parse(data); + + if ( + jsonData && + jsonData.SourceMetadata && + jsonData.SourceMetadata.Data && + jsonData.SourceMetadata.Data.Git && + jsonData.SourceMetadata.Data.Git.file + ) { + secretsDetected = true; + + const repoData = getRepoData(jsonData.SourceMetadata.Data.Git.repository); + if (!repoData) { + console.log("No repo data found, skipping processing..."); + return secretsDetected; + } + + const commentBody = `🚨 Secret Detected 🚨\nSecret detected at line ${jsonData.SourceMetadata.Data.Git.line} in file ${jsonData.SourceMetadata.Data.Git.file}. Please review.`; + + const prs = await octokit.pulls.list({ + owner: repoData.owner, + repo: repoData.repo, + }); + + for (const pr of prs.data) { + if (pr.state === "open") { + const commitId = await octokit.repos.getCommit({ + owner: repoData.owner, + repo: repoData.repo, + ref: pr.head.sha, + }); + + await octokit.pulls.createReviewComment({ + owner: repoData.owner, + repo: repoData.repo, + pull_number: pr.number, + body: commentBody, + commit_id: commitId.data.sha, + path: jsonData.SourceMetadata.Data.Git.file, + line: jsonData.SourceMetadata.Data.Git.line, + side: "RIGHT", // assuming the secret was added, not removed + }); + } + } + } + return secretsDetected; +} + +function getRepoData(repoUrl) { + const regex = + /(?:git@github\.com:|https:\/\/github.com\/)(.+)\/(.+)(?:\.git)?/i; + const match = regex.exec(repoUrl); + + if (!match) { + console.log(`No match found for repoUrl: ${repoUrl}`); + return null; + } + + return { + owner: match[1], + repo: match[2], + }; +} + async function run() { try { const tarballPath = "./trufflehog.tar.gz"; @@ -27,135 +101,48 @@ async function run() { "https://github.com/trufflesecurity/trufflehog/releases/download/v3.40.0/trufflehog_3.40.0_linux_amd64.tar.gz", tarballPath ); - - // Extract TruffleHog tarball await tar.x({ file: tarballPath }); - // Get the path for the output file from the action's inputs const secretsFilePath = core.getInput("secrets-file"); - let output = ''; - let errorOutput = ''; - - const options = {}; - options.listeners = { + let output = ""; + const options = { + listeners: { stdout: (data) => { - output += data.toString(); + fs.appendFileSync(secretsFilePath, data.toString()); }, stderr: (data) => { - errorOutput += data.toString(); - } + console.error(data.toString()); + }, + }, }; - await exec.exec(`./trufflehog`, [ - "git", - "file://./", - "--since-commit", - `${process.env.GITHUB_SHA}`, - "--branch", - "HEAD", - "--fail", - "--no-update", - "--json", - "--no-verification" - ], options); - - if (errorOutput) { - // Handle the error output if necessary - console.error(errorOutput); + try { + await exec.exec( + `./trufflehog`, + [ + "git", + "file://./", + "--since-commit", + `${commit}`, + "--branch", + "HEAD", + "--fail", + "--no-update", + "--json", + "--no-verification", + ], + options + ); + fs.writeFileSync(secretsFilePath, output); + } catch (error) { + console.error(`Error executing trufflehog: ${error}`); } - fs.writeFileSync(secretsFilePath, output); - - fs.readFile(filePath, "utf8", async (err, data) => { - if (err) { - if (!data) { - console.log("No data found, skipping processing..."); - } else { - console.log(`Error reading file from disk: ${err}`); - } - return; - } - - if (data.trim().length === 0) { - console.log("Empty file found, skipping processing..."); - return; - } - - try { - const jsonData = JSON.parse(data); - - const repoData = getRepoData( - jsonData.SourceMetadata.Data.Git.repository - ); - if (!repoData) { - console.log("No repo data found, skipping processing..."); - return; - } - - const commentBody = `🚨 Secret Detected 🚨\nSecret detected at line ${jsonData.SourceMetadata.Data.Git.line} in file ${jsonData.SourceMetadata.Data.Git.file}. Please review.`; - - try { - const prs = await octokit.pulls.list({ - owner: repoData.owner, - repo: repoData.repo, - }); - - for (const pr of prs.data) { - if (pr.state === "open") { - const commitId = await octokit.repos.getCommit({ - owner: repoData.owner, - repo: repoData.repo, - ref: pr.head.sha, - }); - - await octokit.pulls.createReviewComment({ - owner: repoData.owner, - repo: repoData.repo, - pull_number: pr.number, - body: commentBody, - commit_id: commitId.data.sha, - path: jsonData.SourceMetadata.Data.Git.file, - line: jsonData.SourceMetadata.Data.Git.line, - side: "RIGHT", // assuming the secret was added, not removed - }); - } - } - } catch (e) { - if ( - e.status === 422 && - e.message.includes("PullRequestReviewComment") && - e.message.includes("pull_request_review_thread.path") && - e.message.includes("pull_request_review_thread.diff_hunk") - ) { - // Ignore the specific error relating to pull_request_review_thread.diff_hunk - } else if (e.status) { - console.log(`GitHub returned an error: ${e.status}`); - console.log(e.message); - } else { - console.log("Error occurred", e); - } - } - } catch (e) { - console.log("Error parsing JSON:", e); - } - }); - - function getRepoData(repoUrl) { - // This regex will handle both SSH and HTTPS URLs - const regex = - /(?:git@github\.com:|https:\/\/github.com\/)(.+)\/(.+)(?:\.git)?/i; - const match = regex.exec(repoUrl); - - if (!match) { - console.log(`No match found for repoUrl: ${repoUrl}`); - return null; - } + const secretsFound = await checkForSecrets(); - return { - owner: match[1], - repo: match[2], - }; + if (secretsFound) { + core.setFailed("Secrets detected in the repository."); } } catch (error) { core.setFailed(`Action failed with error: ${error}`); diff --git a/node_modules/jsonparse/package.json b/node_modules/jsonparse/package.json index cdeb6eb..371a747 100644 --- a/node_modules/jsonparse/package.json +++ b/node_modules/jsonparse/package.json @@ -1,27 +1,32 @@ { - "_from": "jsonparse@^1.2.0", + "_args": [ + [ + "jsonparse@1.3.1", + "/Users/danielwright/source/therealdwright/trufflehog-secrets-detector" + ] + ], + "_from": "jsonparse@1.3.1", "_id": "jsonparse@1.3.1", "_inBundle": false, "_integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "_location": "/jsonparse", "_phantomChildren": {}, "_requested": { - "type": "range", + "type": "version", "registry": true, - "raw": "jsonparse@^1.2.0", + "raw": "jsonparse@1.3.1", "name": "jsonparse", "escapedName": "jsonparse", - "rawSpec": "^1.2.0", + "rawSpec": "1.3.1", "saveSpec": null, - "fetchSpec": "^1.2.0" + "fetchSpec": "1.3.1" }, "_requiredBy": [ "/JSONStream" ], "_resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "_shasum": "3f4dae4a91fac315f71062f8521cc239f1366280", - "_spec": "jsonparse@^1.2.0", - "_where": "/Users/danielwright/source/therealdwright/trufflehog-secrets-detector/node_modules/JSONStream", + "_spec": "1.3.1", + "_where": "/Users/danielwright/source/therealdwright/trufflehog-secrets-detector", "author": { "name": "Tim Caswell", "email": "tim@creationix.com" @@ -29,8 +34,6 @@ "bugs": { "url": "http://github.com/creationix/jsonparse/issues" }, - "bundleDependencies": false, - "deprecated": false, "description": "This is a pure-js JSON streaming parser for node.js", "devDependencies": { "tap": "~0.3.3",