Add initial implementation of PolinRider malware scanner
- Introduced core files including Dockerfile, action.yml, and entry point script (bin/polinrider.js) for the PolinRider malware scanner. - Created configuration files: .env.example, .gitignore, and .npmrc for environment setup and dependency management. - Added CI workflows for testing, building, and releasing the action, along with examples for usage in GitHub Actions. - Implemented a README.md to provide documentation on usage, features, and setup instructions. - Included necessary scripts for building the action and handling security measures during execution. - Established a structured directory for reports and workspace management within Docker. - Ensured all files are set up for a secure and efficient scanning process of GitHub repositories for PolinRider malware.
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { buildRunJson, buildRunMarkdown } from "../src/report.js";
|
||||
|
||||
function sampleRun(overrides = {}) {
|
||||
return {
|
||||
scannedAt: "2026-06-01T12:00:00.000Z",
|
||||
scannedAtHuman: "Mon Jun 01 2026 12:00:00",
|
||||
account: { kind: "org", owner: "RMSoft-ltd" },
|
||||
dryRun: false,
|
||||
autoMerge: true,
|
||||
mergeMethod: "squash",
|
||||
totals: {
|
||||
total: 4,
|
||||
clean: 1,
|
||||
infected: 3,
|
||||
remediated: 2,
|
||||
merged: 1,
|
||||
prOpened: 2,
|
||||
manualOnly: 1,
|
||||
errors: 1,
|
||||
},
|
||||
repos: [
|
||||
{
|
||||
repo: "RMSoft-ltd/clean-app",
|
||||
severity: "clean",
|
||||
findings: [],
|
||||
deleted: [],
|
||||
modified: [],
|
||||
notes: [],
|
||||
manualReview: [],
|
||||
pr: null,
|
||||
error: null,
|
||||
},
|
||||
{
|
||||
repo: "RMSoft-ltd/web",
|
||||
severity: "infected",
|
||||
findings: [
|
||||
{
|
||||
file: ".vscode",
|
||||
action: "remove-dir",
|
||||
confidence: "high",
|
||||
contentConfirmed: true,
|
||||
description: "malicious task",
|
||||
},
|
||||
],
|
||||
deleted: [".vscode", "public/fonts"],
|
||||
modified: ["vite.config.js"],
|
||||
notes: ["removed malware-injected entries from .gitignore"],
|
||||
manualReview: [],
|
||||
pr: {
|
||||
url: "https://github.com/RMSoft-ltd/web/pull/7",
|
||||
merged: true,
|
||||
mergeError: null,
|
||||
},
|
||||
error: null,
|
||||
},
|
||||
{
|
||||
repo: "RMSoft-ltd/api",
|
||||
severity: "infected",
|
||||
findings: [],
|
||||
deleted: [],
|
||||
modified: ["postcss.config.mjs"],
|
||||
notes: [],
|
||||
manualReview: [],
|
||||
pr: {
|
||||
url: "https://github.com/RMSoft-ltd/api/pull/3",
|
||||
merged: false,
|
||||
mergeError: "required status checks have not passed",
|
||||
},
|
||||
error: null,
|
||||
},
|
||||
{
|
||||
repo: "RMSoft-ltd/mob",
|
||||
severity: "infected",
|
||||
findings: [],
|
||||
deleted: [],
|
||||
modified: [],
|
||||
notes: [],
|
||||
manualReview: ["package.json: impostor dependency"],
|
||||
pr: null,
|
||||
error: null,
|
||||
},
|
||||
],
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
test("buildRunMarkdown renders clickable PR links and merge status", () => {
|
||||
const md = buildRunMarkdown(sampleRun());
|
||||
assert.match(md, /\[#7\]\(https:\/\/github\.com\/RMSoft-ltd\/web\/pull\/7\)/);
|
||||
assert.match(md, /✅ merged/);
|
||||
assert.match(md, /⚠️ merge blocked/);
|
||||
assert.match(md, /\| Repository \| Pull request \| Status \| Changes \|/);
|
||||
assert.match(md, /removed: \.vscode, public\/fonts/);
|
||||
});
|
||||
|
||||
test("buildRunMarkdown surfaces a Needs attention section", () => {
|
||||
const md = buildRunMarkdown(sampleRun());
|
||||
assert.match(md, /## Needs attention/);
|
||||
assert.match(md, /auto-merge blocked: required status checks/);
|
||||
assert.match(md, /manual review: package\.json: impostor dependency/);
|
||||
});
|
||||
|
||||
test("buildRunMarkdown reflects account, mode, and totals", () => {
|
||||
const md = buildRunMarkdown(sampleRun());
|
||||
assert.match(md, /\*\*Account:\*\* org `RMSoft-ltd`/);
|
||||
assert.match(md, /auto-merge: on \(squash\)/);
|
||||
assert.match(md, /\| PRs merged \| 1 \|/);
|
||||
});
|
||||
|
||||
test("dry-run mode is labeled and omits the merged row", () => {
|
||||
const md = buildRunMarkdown(sampleRun({ dryRun: true, autoMerge: false }));
|
||||
assert.match(md, /DRY RUN/);
|
||||
assert.match(md, /auto-merge: off/);
|
||||
assert.ok(!md.includes("PRs merged"));
|
||||
});
|
||||
|
||||
test("buildRunJson tags a schema and preserves the repos array", () => {
|
||||
const run = sampleRun();
|
||||
const json = buildRunJson(run);
|
||||
assert.equal(json.schema, "polinrider-run/1");
|
||||
assert.equal(json.repos.length, 4);
|
||||
assert.equal(json.totals.merged, 1);
|
||||
// round-trips through JSON
|
||||
assert.deepEqual(JSON.parse(JSON.stringify(json)).account, {
|
||||
kind: "org",
|
||||
owner: "RMSoft-ltd",
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user