From 3003d91452006b2933d8abd93eb4b4dcaf9c51c4 Mon Sep 17 00:00:00 2001 From: Rayan-and-beyond Date: Tue, 15 Sep 2026 20:44:33 +0000 Subject: [PATCH] fix: report skipped files in SARIF --- CHANGELOG.md | 2 ++ package.json | 2 +- src/report.js | 6 ++++++ test/skill-audit.test.js | 10 ++++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70144b9..cf7e805 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ All notable changes to this project are documented here, following ### Fixed +- Include skipped files in SARIF output as tool execution notifications. + - Report scannable files that exceed the 2 MB size limit or cannot be read instead of skipping them silently; include them in text and JSON output, log warnings on stderr, and exit with code 1 when any file was skipped. diff --git a/package.json b/package.json index 117b5ea..3b2a83c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@royalpinto007/skill-audit", - "version": "0.1.7", + "version": "0.1.8", "description": "Security scanner for agent skills. Scan a Claude/agent Skill for prompt-injection, dangerous shell, secret access, and exfiltration before you trust it. Zero dependencies, SARIF output, npx skill-audit .", "type": "module", "bin": { diff --git a/src/report.js b/src/report.js index c9761a2..cf7483d 100644 --- a/src/report.js +++ b/src/report.js @@ -93,6 +93,11 @@ export function sarifReport(result) { properties: { category: f.category, severity: f.severity }, }; }); + const notifications = (result.skipped ?? []).map((s) => ({ + level: "warning", + message: { text: `Skipped ${s.file}: file was not scanned (${s.reason})` }, + locations: [{ physicalLocation: { artifactLocation: { uri: s.file } } }], + })); const results = findings.map((f) => ({ ruleId: f.rule, level: SARIF_LEVEL[f.severity], @@ -111,6 +116,7 @@ export function sarifReport(result) { runs: [{ tool: { driver: { name: "skill-audit", informationUri: "https://github.com/AgentPostmortem/skill-audit", rules } }, results, + invocations: [{ executionSuccessful: true, toolExecutionNotifications: notifications }], }], }, null, 2); } diff --git a/test/skill-audit.test.js b/test/skill-audit.test.js index 90aaefe..34b589c 100644 --- a/test/skill-audit.test.js +++ b/test/skill-audit.test.js @@ -205,6 +205,16 @@ test("sarif and json output are valid and well-formed", () => { assert.ok(j.findings.length > 0); }); +test("sarif output reports skipped files as tool notifications", () => { + const result = { findings: [], skipped: [{ file: "big.sh", reason: "oversized", size: 2_000_001 }] }; + const sarif = JSON.parse(sarifReport(result)); + const notifications = sarif.runs[0].invocations[0].toolExecutionNotifications; + assert.equal(notifications.length, 1); + assert.equal(notifications[0].level, "warning"); + assert.match(notifications[0].message.text, /big\.sh/); + assert.equal(notifications[0].locations[0].physicalLocation.artifactLocation.uri, "big.sh"); +}); + test("every rule has the required fields and a matcher", () => { for (const r of RULES) { assert.ok(r.id && r.severity && r.category && r.title && r.remediation, `rule missing fields: ${r.id}`);