Skip to content

Commit a431aaa

Browse files
authored
Emit SARIF output for Code Scanning (#4547)
Adds a new --sarif PATH option to write a SARIF v2.1.0 report for verification results. - Failed properties are reported as error; undetermined/unknown properties as warning - CBMC timeout/OOM is reported as error - Artifact paths are made repo-relative when possible - Docs and tests included Example: cargo kani --sarif kani.sarif GitHub Actions upload: - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: kani.sarif Co-authored-by: KAMIYO <kamiyo-ai@users.noreply.github.com>
1 parent 91c6843 commit a431aaa

File tree

5 files changed

+458
-0
lines changed

5 files changed

+458
-0
lines changed

docs/src/install-github-ci.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,28 @@ The action takes the following optional parameters:
4141
See `cargo kani --help` for a full list of options.
4242
Useful options include:
4343
- `--output-format=terse` to generate terse output.
44+
- `--sarif <path>` to write a SARIF report that can be uploaded to GitHub Code Scanning.
4445
- `--tests` to run on proofs inside the `test` module (needed for running Bolero).
4546
- `--workspace` to run on all crates within your repository.
4647

48+
### Uploading SARIF to GitHub Code Scanning
49+
50+
If you run Kani with `--sarif`, you can upload the report so results show up as Code Scanning alerts.
51+
52+
```yaml
53+
- name: 'Run Kani on your code.'
54+
uses: model-checking/kani-github-action@v<MAJOR>.<MINOR>
55+
with:
56+
args: --sarif kani.sarif
57+
58+
- name: 'Upload SARIF'
59+
uses: github/codeql-action/upload-sarif@v3
60+
with:
61+
sarif_file: kani.sarif
62+
```
63+
64+
Your workflow must grant `security-events: write` permissions to upload SARIF results.
65+
4766
## FAQ
4867
- **Kani takes too long for my CI**: Try running Kani on a
4968
[schedule](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule)

docs/src/verification-results.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,19 @@ SUMMARY:
159159
160160
VERIFICATION:- SUCCESSFUL
161161
```
162+
163+
## SARIF output
164+
165+
Kani can emit SARIF (Static Analysis Results Interchange Format) for integration with tools such as GitHub Code Scanning.
166+
167+
Generate a SARIF report:
168+
```bash
169+
cargo kani --sarif kani.sarif
170+
```
171+
172+
In GitHub Actions, upload the SARIF file:
173+
```yaml
174+
- uses: github/codeql-action/upload-sarif@v3
175+
with:
176+
sarif_file: kani.sarif
177+
```

kani-driver/src/args/mod.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,10 @@ pub struct VerificationArgs {
351351
#[arg(long, hide_short_help = true)]
352352
pub run_sanity_checks: bool,
353353

354+
/// Write SARIF output (Static Analysis Results Interchange Format) to the given path.
355+
#[arg(long, value_name = "PATH")]
356+
pub sarif: Option<PathBuf>,
357+
354358
/// Specify the CBMC solver to use. Overrides the harness `solver` attribute.
355359
/// If no solver is specified (with --solver or harness attribute), Kani will use CaDiCaL.
356360
#[arg(long, value_parser = CbmcSolverValueParser::new(CbmcSolver::VARIANTS))]
@@ -767,13 +771,25 @@ impl ValidateArgs for VerificationArgs {
767771
--output-format=old.",
768772
));
769773
}
774+
if self.sarif.is_some() && self.output_format == OutputFormat::Old {
775+
return Err(Error::raw(
776+
ErrorKind::ArgumentConflict,
777+
"Conflicting options: --sarif isn't compatible with --output-format=old.",
778+
));
779+
}
770780
if self.concrete_playback.is_some() && self.jobs().will_multithread() {
771781
// Concrete playback currently embeds a lot of assumptions about the order in which harnesses get called.
772782
return Err(Error::raw(
773783
ErrorKind::ArgumentConflict,
774784
"Conflicting options: --concrete-playback isn't compatible with --jobs specifying multiple threads.",
775785
));
776786
}
787+
if self.sarif.is_some() && self.only_codegen {
788+
return Err(Error::raw(
789+
ErrorKind::ArgumentConflict,
790+
"Conflicting options: --sarif isn't compatible with --only-codegen.",
791+
));
792+
}
777793
if self.jobs().will_multithread() && self.output_format != OutputFormat::Terse {
778794
// More verbose output formats make it hard to interpret output right now when run in parallel.
779795
// This can be removed when we change up how results are printed.
@@ -853,6 +869,18 @@ impl ValidateArgs for VerificationArgs {
853869
),
854870
));
855871
}
872+
if let Some(out_file) = &self.sarif
873+
&& out_file.exists()
874+
&& out_file.is_dir()
875+
{
876+
return Err(Error::raw(
877+
ErrorKind::InvalidValue,
878+
format!(
879+
"Invalid argument: `--sarif` argument `{}` is a directory",
880+
out_file.display()
881+
),
882+
));
883+
}
856884

857885
Ok(())
858886
}
@@ -1138,6 +1166,24 @@ mod tests {
11381166
);
11391167
}
11401168

1169+
#[test]
1170+
fn check_sarif_parsing() {
1171+
let args = parse_unstable_disabled("--sarif out.sarif").unwrap();
1172+
assert_eq!(args.verify_opts.sarif, Some(PathBuf::from("out.sarif")));
1173+
}
1174+
1175+
#[test]
1176+
fn check_sarif_conflicts() {
1177+
expect_validation_error(
1178+
"kani file.rs --sarif out.sarif --output-format=old",
1179+
ErrorKind::ArgumentConflict,
1180+
);
1181+
expect_validation_error(
1182+
"kani file.rs --sarif out.sarif --only-codegen",
1183+
ErrorKind::ArgumentConflict,
1184+
);
1185+
}
1186+
11411187
#[test]
11421188
fn check_enable_stubbing() {
11431189
let res = parse_unstable_disabled("--harness foo").unwrap();

kani-driver/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ mod harness_runner;
3636
mod list;
3737
mod metadata;
3838
mod project;
39+
mod sarif;
3940
mod session;
4041
mod util;
4142
mod version;
@@ -159,6 +160,7 @@ fn verify_project(project: Project, session: KaniSession) -> Result<()> {
159160
session.save_coverage_results(&project, &results, &timestamp)?;
160161
}
161162

163+
session.write_sarif(&results)?;
162164
session.print_final_summary(&results)
163165
}
164166

0 commit comments

Comments
 (0)