mirror of
https://github.com/KeygraphHQ/shannon.git
synced 2026-08-29 06:20:44 +02:00
fix(report): emit SARIF by default for exploit runs (#431)
* fix(report): emit SARIF by default for exploit runs, opt out with report.sarif: false * docs: describe SARIF as on-by-default for exploit runs
This commit is contained in:
@@ -164,7 +164,7 @@
|
||||
"sarif": {
|
||||
"type": "string",
|
||||
"enum": ["true", "false"],
|
||||
"description": "Emit a SARIF 2.1.0 log (report.sarif) beside the report. Requires exploit=true; ignored otherwise."
|
||||
"description": "Emit a SARIF 2.1.0 log (report.sarif) beside the report. On by default for exploit runs; set \"false\" to opt out. Ignored when exploit=false."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -96,8 +96,9 @@ rules:
|
||||
# Report filters applied by the report agent when assembling the final report (optional).
|
||||
# Example below is illustrative; edit, remove, or add sections as needed.
|
||||
# report:
|
||||
# # Emit a SARIF 2.1.0 log (report.sarif) beside the report. Requires exploit: "true".
|
||||
# sarif: "true"
|
||||
# # SARIF 2.1.0 log (report.sarif) beside the report. On by default for exploit runs;
|
||||
# # set "false" to opt out. Ignored when exploit is "false".
|
||||
# sarif: "false"
|
||||
# min_severity: low
|
||||
# min_confidence: low
|
||||
# guidance: |
|
||||
|
||||
@@ -679,7 +679,8 @@ export const distributeConfig = (config: Config | null): DistributedConfig => {
|
||||
const exploit = config?.exploit !== undefined ? config.exploit === 'true' : true;
|
||||
|
||||
const report = {
|
||||
sarif: config?.report?.sarif === 'true',
|
||||
// Default on; only an explicit "false" opts out.
|
||||
sarif: config?.report?.sarif !== 'false',
|
||||
...(config?.report?.min_severity && { min_severity: config.report.min_severity }),
|
||||
...(config?.report?.min_confidence && { min_confidence: config.report.min_confidence }),
|
||||
...(config?.report?.guidance && { guidance: config.report.guidance.trim() }),
|
||||
|
||||
@@ -43,7 +43,7 @@ export const FINAL_REPORT_MD_FILENAME = 'Security-Assessment-Report.md';
|
||||
/** Structured findings the report agent emits; the markdown report is rendered from it. */
|
||||
export const REPORT_JSON_FILENAME = 'report.json';
|
||||
|
||||
/** SARIF 2.1.0 log, written only for exploit=true runs when report.sarif is enabled. */
|
||||
/** SARIF 2.1.0 log, written for exploit=true runs unless report.sarif is set to false. */
|
||||
export const SARIF_FILENAME = 'report.sarif';
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ export function getAgentGitPaths(agentName: AgentName): string[] {
|
||||
paths.push(queueFilename);
|
||||
}
|
||||
// The report agent also emits the structured findings the markdown is rendered from, and the
|
||||
// SARIF log when enabled. Listing the log unconditionally is harmless when it was not written,
|
||||
// SARIF log when produced. Listing the log unconditionally is harmless when it was not written,
|
||||
// and keeps a stale one from surviving the rollback of a failed attempt.
|
||||
if (agentName === 'report') {
|
||||
paths.push(REPORT_JSON_FILENAME);
|
||||
|
||||
@@ -181,7 +181,7 @@ export async function injectModelIntoReport(
|
||||
*
|
||||
* The SARIF log is surfaced beside it when present, since a CI step consuming it needs a stable
|
||||
* path and cannot be expected to reach into the internals directory. It is absent whenever the
|
||||
* run was analysis-only or `report.sarif` was not enabled.
|
||||
* run was analysis-only or `report.sarif` was set to false.
|
||||
*/
|
||||
export async function copyReportToRunRoot(
|
||||
repoPath: string,
|
||||
|
||||
@@ -450,13 +450,14 @@ export async function runAuthzExploitAgent(input: ActivityInput): Promise<AgentM
|
||||
}
|
||||
|
||||
/**
|
||||
* Write report.sarif when the run is exploitative and the operator asked for it.
|
||||
* Write report.sarif for exploitative runs unless the operator opted out with report.sarif: false.
|
||||
*
|
||||
* Skipped entirely for analysis-only runs. The original reason was that those findings carried
|
||||
* no severity, so every `result.level` would have been invented; since severity is recorded in
|
||||
* both modes an analysis run could now populate `level`, but it would report an assessed
|
||||
* severity as a measured one, so the gate stays. Failures are logged and swallowed — the SARIF
|
||||
* log is a secondary artifact and must not fail a run whose report is already written.
|
||||
* On by default so a CI step consuming the log always finds one. Skipped for analysis-only runs.
|
||||
* The original reason was that those findings carried no severity, so every `result.level` would
|
||||
* have been invented; since severity is recorded in both modes an analysis run could now populate
|
||||
* `level`, but it would report an assessed severity as a measured one, so the gate stays. Failures
|
||||
* are logged and swallowed — the SARIF log is a secondary artifact and must not fail a run whose
|
||||
* report is already written.
|
||||
*/
|
||||
async function writeSarifIfEnabled(
|
||||
input: ActivityInput,
|
||||
@@ -469,7 +470,8 @@ async function writeSarifIfEnabled(
|
||||
|
||||
const container = getOrCreateContainer(input.workflowId, buildSessionMetadata(input), buildContainerConfig(input));
|
||||
const configResult = await container.configLoader.loadOptional(input.configPath, undefined, input.configYAML);
|
||||
if (isErr(configResult) || configResult.value?.report?.sarif !== true) return;
|
||||
// Only an explicit false opts out; a missing config keeps the default on.
|
||||
if (isErr(configResult) || configResult.value?.report?.sarif === false) return;
|
||||
|
||||
try {
|
||||
const { renderSarif } = await import('../services/sarif-renderer.js');
|
||||
|
||||
@@ -32,7 +32,10 @@ export interface ReportConfig {
|
||||
min_severity?: Severity;
|
||||
min_confidence?: Confidence;
|
||||
guidance?: string;
|
||||
/** Emit report.sarif alongside the markdown report. Ignored when exploit is false. */
|
||||
/**
|
||||
* Emit report.sarif alongside the markdown report. On by default for exploit runs; set 'false'
|
||||
* to opt out. Ignored when exploit is false.
|
||||
*/
|
||||
sarif?: 'true' | 'false';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user