illumitech-forge-cli 1.3.0

Evidence-backed agent execution CLI
Documentation
//! Bounded, offline SARIF import. Findings and suggested fixes are untrusted data.
use anyhow::{Context, Result, ensure};
use forge_domain::digest;
use serde_json::{Value, json};
use std::{
    collections::BTreeSet,
    path::{Component, Path},
};
fn decode_uri(text: &str) -> Result<String> {
    let mut bytes = vec![];
    let input = text.as_bytes();
    let mut i = 0;
    while i < input.len() {
        if input[i] == b'%' {
            ensure!(i + 2 < input.len(), "incomplete URI escape");
            let digit = |b: u8| -> Result<u8> {
                match b {
                    b'0'..=b'9' => Ok(b - b'0'),
                    b'a'..=b'f' => Ok(b - b'a' + 10),
                    b'A'..=b'F' => Ok(b - b'A' + 10),
                    _ => anyhow::bail!("invalid URI escape"),
                }
            };
            let b = digit(input[i + 1])? * 16 + digit(input[i + 2])?;
            ensure!(b != b'/' && b != b'\\', "encoded path separator rejected");
            bytes.push(b);
            i += 3;
        } else {
            bytes.push(input[i]);
            i += 1;
        }
    }
    Ok(String::from_utf8(bytes)?)
}
fn relative_uri(uri: &str, root: &Path) -> Result<String> {
    let decoded = decode_uri(uri)?;
    let path = if let Some(local) = decoded.strip_prefix("file://") {
        ensure!(local.starts_with('/'), "remote file authorities rejected");
        let p = Path::new(local);
        ensure!(
            p.components().all(|c| !matches!(c, Component::ParentDir)),
            "URI traversal rejected"
        );
        p.strip_prefix(root)
            .context("file URI outside project")?
            .to_path_buf()
    } else {
        Path::new(decoded.trim_start_matches("./")).to_path_buf()
    };
    ensure!(
        !decoded.contains(['\\', '\0', '?', '#', '%'])
            && !path.is_absolute()
            && path.components().all(|c| matches!(c, Component::Normal(_)))
            && !path.as_os_str().is_empty()
            && !path.to_string_lossy().contains(':'),
        "unsafe SARIF artifact URI"
    );
    Ok(path.to_string_lossy().into_owned())
}
pub fn parse(v: &Value, root: &Path) -> Result<Value> {
    ensure!(v["version"] == "2.1.0", "SARIF 2.1.0 required");
    let runs = v["runs"].as_array().context("SARIF runs required")?;
    ensure!(!runs.is_empty() && runs.len() <= 20, "SARIF run limit");
    let mut rows = vec![];
    let mut seen = BTreeSet::new();
    let mut errors = vec![];
    for run in runs {
        ensure!(
            run.get("externalPropertyFileReferences").is_none(),
            "external SARIF references are not loaded"
        );
        let tool = run["tool"]["driver"]["name"]
            .as_str()
            .context("scanner identity required")?;
        if let Some(invocations) = run["invocations"].as_array() {
            for invocation in invocations {
                for field in [
                    "toolExecutionNotifications",
                    "toolConfigurationNotifications",
                ] {
                    if let Some(notifications) = invocation[field].as_array() {
                        for notification in notifications {
                            if notification["level"] == "error"
                                || notification["level"] == "warning"
                            {
                                errors.push(json!({"tool":tool,"reason":"scanner reported incomplete/error/warning coverage","notification":notification}));
                            }
                        }
                    }
                }
                if invocation["executionSuccessful"] == false {
                    errors.push(json!({"tool":tool,"reason":"scanner execution failed"}));
                }
            }
        }
        let artifacts = run["artifacts"].as_array();
        let results = run["results"]
            .as_array()
            .context("SARIF results required (empty list is valid)")?;
        ensure!(results.len() <= 10000, "SARIF finding limit");
        for result in results {
            let rule = result["ruleId"].as_str().context("ruleId required")?;
            let location = result["locations"]
                .as_array()
                .and_then(|x| x.first())
                .context("finding needs a source location")?;
            let physical = &location["physicalLocation"];
            let artifact = &physical["artifactLocation"];
            if let Some(base) = artifact["uriBaseId"].as_str() {
                if let Some(uri) = run["originalUriBaseIds"][base]["uri"].as_str() {
                    let decoded = decode_uri(uri)?;
                    ensure!(
                        decoded
                            .strip_prefix("file://")
                            .is_some_and(|p| Path::new(p) == root),
                        "SARIF URI base must equal the selected repository root"
                    );
                } else {
                    ensure!(base == "%SRCROOT%", "unresolved SARIF URI base");
                }
            }
            let uri = artifact["uri"]
                .as_str()
                .or_else(|| {
                    artifact["index"]
                        .as_u64()
                        .and_then(|n| artifacts?.get(n as usize)?["location"]["uri"].as_str())
                })
                .context("repo-relative artifact URI required")?;
            let uri = relative_uri(uri, root)?;
            let path = Path::new(&uri);
            let full = crate::guided::safe_path(&root.join(path))?;
            ensure!(full.starts_with(root), "finding outside project");
            let line = physical["region"]["startLine"].as_u64();
            let key = digest(serde_json::to_string(&(tool, rule, &uri, line))?.as_bytes());
            if seen.insert(key.clone()) {
                rows.push(json!({"id":key,"tool":tool,"tool_version":run["tool"]["driver"]["version"],"rule":rule,"path":uri,"line":line,"level":result["level"].as_str().unwrap_or("unknown"),"message":result["message"]["text"],"status":"unverified","suggested_fixes":"not_executed","severity_source":"scanner; no inferred CVSS or reachability"}));
            }
        }
    }
    Ok(
        json!({"schema_version":1,"findings_schema":1,"status":if errors.is_empty(){"imported"}else{"blocked"},"findings":rows,"scanner_errors":errors,"input_sha256":digest(&serde_json::to_vec(v)?),"resolved":false,"uri_base_binding":"Missing %SRCROOT% binds to selected repository; source revision must still be verified","mutation":false,"native_inference_calls":0,"next_action":"Select findings, review a dependency/bug workflow and require a successful rescan plus project tests. Disappearance alone is not proof of resolution."}),
    )
}
pub fn file(path: &Path, root: &Path) -> Result<Value> {
    let root = crate::guided::root(root)?;
    parse(&crate::workflow::read_json(path)?, &root)
}
#[cfg(test)]
mod tests {
    use super::*;
    pub(super) fn sarif_for_base(uri: &str) -> Value {
        json!({"version":"2.1.0","runs":[{"tool":{"driver":{"name":"OSV-Scanner"}},"results":[{"ruleId":"fixture","message":{"text":"Untrusted suggestion"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":uri},"region":{"startLine":1}}}]}]}]})
    }
    #[test]
    fn unsafe_locations_and_external_refs_fail() {
        let t = tempfile::tempdir().unwrap();
        for uri in [
            "../secret",
            "https://example.com/code",
            "/tmp/code",
            "%2e%2e/code",
            "a\\b",
        ] {
            assert!(parse(&sarif_for_base(uri), t.path()).is_err());
        }
        let mut s = sarif_for_base("Cargo.lock");
        s["runs"][0]["externalPropertyFileReferences"] = json!({});
        assert!(parse(&s, t.path()).is_err());
    }
    #[test]
    fn dedup_and_scanner_errors_do_not_resolve_findings() {
        let t = tempfile::tempdir().unwrap();
        let mut s = sarif_for_base("Cargo.lock");
        let row = s["runs"][0]["results"][0].clone();
        s["runs"][0]["results"].as_array_mut().unwrap().push(row);
        assert_eq!(
            parse(&s, t.path()).unwrap()["findings"]
                .as_array()
                .unwrap()
                .len(),
            1
        );
        s["runs"][0]["invocations"] = json!([{"executionSuccessful":false}]);
        assert_eq!(parse(&s, t.path()).unwrap()["status"], "blocked");
    }
}

#[cfg(test)]
mod uri_tests {
    use super::*;
    #[test]
    fn local_absolute_and_encoded_space_are_normalized() {
        let t = tempfile::tempdir().unwrap();
        let root = t.path();
        assert_eq!(
            relative_uri("src/file%20name.rs", root).unwrap(),
            "src/file name.rs"
        );
        assert_eq!(
            relative_uri(&format!("file://{}/src/a.rs", root.display()), root).unwrap(),
            "src/a.rs"
        );
        for value in [
            "file://evil/tmp/code",
            "file:///other/code",
            "src%2fsecret",
            "%252e%252e/private",
        ] {
            assert!(relative_uri(value, root).is_err(), "{value}");
        }
    }
}

#[cfg(test)]
mod semgrep_base_tests {
    use super::*;
    #[test]
    fn source_root_placeholder_is_bound_to_selected_repo_but_foreign_bases_fail() {
        let t = tempfile::tempdir().unwrap();
        let mut value = super::tests::sarif_for_base("package.json");
        value["runs"][0]["results"][0]["locations"][0]["physicalLocation"]["artifactLocation"]["uriBaseId"] =
            json!("%SRCROOT%");
        assert_eq!(
            parse(&value, t.path()).unwrap()["findings"][0]["path"],
            "package.json"
        );
        value["runs"][0]["originalUriBaseIds"] =
            json!({"%SRCROOT%":{"uri":"file:///foreign/project/"}});
        assert!(parse(&value, t.path()).is_err());
    }
}