live · scanning repos
Scanrepo
github.com
github.com / vastsa

vastsa/pi-desktop

TypeScript·2349 files·commit 0598be2·scanned 1h ago·cached ✓
25/100
LOW RISK
Minor findings consistent with the project type. Nothing reachable from install hooks.

score capped at 25 — 5,615 stars — findings likely legitimate code patterns

verdict accurate?
Partial architecture graph
Electron app detected
threat-state: lowlive

FINDINGS ░▒▓

warningRust unsafe blockunsafe blocks bypass Rust's memory safety guarantees. Malware uses them for raw pointer manipulation, shellcode injection, or calling dangerous foreign functions.crates/host-core/src/agent_capabilities.rs
        // Safety: test-only process env mutation, serialized by the lock above.
        unsafe { std::env::set_var(super::AGENTS_DIR_ENV, dir) };
        let outcome = f();
        unsafe { std::env:...
+3
criticalRust process Command usagestd::process::Command can execute arbitrary shell commands. Malware uses it to drop payloads, exfiltrate data, or establish persistence.crates/host-core/src/config_sync/engine.rs
        let agents_dir = tempfile::tempdir()?;
        let output = std::process::Command::new(std::env::current_exe()?)
            .args(["--exact", test_name, "--nocapture"])
            .env(ISOLA...
+8
warningRust unsafe blockunsafe blocks bypass Rust's memory safety guarantees. Malware uses them for raw pointer manipulation, shellcode injection, or calling dangerous foreign functions.crates/host-core/src/keyboard.rs
            .name("pi-host-global-shortcut".into())
            .spawn(|| unsafe {
                let module = GetModuleHandleW(std::ptr::null());
                let hook = SetWindowsHookExW(WH_KEYB...
+3
warningRust unsafe blockunsafe blocks bypass Rust's memory safety guarantees. Malware uses them for raw pointer manipulation, shellcode injection, or calling dangerous foreign functions.crates/host-core/src/plugins/device.rs
    let mut size = std::mem::size_of_val(&buffer) as u32;
    let status = unsafe {
        RegGetValueW(
            HKEY_LOCAL_MACHINE,
+3
criticalRust process Command usagestd::process::Command can execute arbitrary shell commands. Malware uses it to drop payloads, exfiltrate data, or establish persistence.crates/host-core/src/plugins/install.rs

    let spawned = std::process::Command::new("curl")
        .args(&args)
        .stdout(std::process::Stdio::piped())
+8
criticalRust process Command usagestd::process::Command can execute arbitrary shell commands. Malware uses it to drop payloads, exfiltrate data, or establish persistence.crates/host-core/src/plugins/resolve.rs

    let outcome = std::process::Command::new("curl").args(&args).output();
    let result = match outcome {
        Ok(output) if output.status.success() => {
+8
criticaleval() usage detectedeval() executes arbitrary code and is commonly used in malware to run obfuscated payloads fetched from remote servers.scripts/e2e-provider-recovery.mjs
const evaluate = async (expression) => {
  const retained = `globalThis.__cdpPromise699 = (async () => { return eval(${JSON.stringify(expression)}); })()`;
  const result = await send("Runtime.evaluat...
+8
criticalFunction() constructor detectednew Function() is equivalent to eval() and can execute arbitrary code strings.apps/desktop/test/chat-context-menu-items.test.mjs
  const module = { exports: {} };
  new Function("require", "exports", "module", outputText)(
    (id) => {
      assert.ok(Object.hasOwn(imports, id), `unmocked menu-item dependency: ${id}`);
+5
criticalFunction() constructor detectednew Function() is equivalent to eval() and can execute arbitrary code strings.apps/desktop/test/composer-paste-files.test.mjs
  ].join("\n");
  const nextChipToken = new Function(snippet)();

  const seen = new Set();
+5
criticalFunction() constructor detectednew Function() is equivalent to eval() and can execute arbitrary code strings.apps/desktop/test/composer-send-state.test.mjs
  );
  const promptAttachmentsFromDraft = new Function(
    `${executable}; return promptAttachmentsFromDraft;`,
  )();
+5
infoSuspicious files are not reachable from entry pointsFlagged files exist but are not imported by any entry point. They may be dead code, tests, or attack payloads triggered by another mechanism.+2
infoBase64 encoding usedatob() or Buffer.from with base64. Common in legitimate code but also used to hide malicious URLs.packages/agent-runtime/src/image-generation/index.ts
  ) {
    bytes = Buffer.from(item.b64_json, "base64");
  } else if (typeof item.url === "string") {
    bytes = await downloadGeneratedImage(item.url, signal, {
+2
warningHardcoded IP address in network callFetching data from hardcoded IP addresses instead of domain names is suspicious and may indicate C2 communication.packages/shared/src/mcp-registry.test.ts
      mapRegistryServer({
        server: { name: "io.github.example/private", remotes: [{ type: "streamable-http", url: "https://127.0.0.1/mcp" }] },
      }),
    ).toBeNull();
+5
warningHardcoded IP address in network callFetching data from hardcoded IP addresses instead of domain names is suspicious and may indicate C2 communication.packages/shared/src/skill-catalog.test.ts
  it("accepts a source the user runs on loopback or the LAN", () => {
    expect(isSafeSkillSourceUrl("https://127.0.0.1/catalog.json")).toBe(true);
    expect(isSafeSkillSourceUrl("https://192.168.1....
+5
infoBase64 encoding usedatob() or Buffer.from with base64. Common in legitimate code but also used to hide malicious URLs.scripts/e2e-image-chat.mjs
      const result = await send("Page.captureScreenshot", { format: "png" });
      writeFileSync(join(evidence, name), Buffer.from(result.data, "base64"));
    }
  };
+2
infoBase64 encoding usedatob() or Buffer.from with base64. Common in legitimate code but also used to hide malicious URLs.scripts/e2e-provider-recovery.mjs
  const shot = await send("Page.captureScreenshot", { format: "png" });
  await writeFile(join(artifacts, `${name}.png`), Buffer.from(shot.data, "base64"));
}
const bodyText = () => evaluate("document...
+2
warningSSH/credential path accessAccessing .ssh, .aws/credentials, or .env files to steal authentication credentials.packages/plugin-sdk/src/fs-policy.test.ts
      "certs/server.pem",
      ".ssh/id_rsa",
      "backup/.ssh/config",
      "id_ed25519",
+5
warningSSH/credential path accessAccessing .ssh, .aws/credentials, or .env files to steal authentication credentials.packages/plugin-sdk/src/fs-policy.ts
  ".aws",
  ".gnupg",
  ".kube",
  ".docker",
+5
warningSSH/credential path accessAccessing .ssh, .aws/credentials, or .env files to steal authentication credentials.apps/desktop/electron/main/agent-extensions.ts
  ".aws",
  ".gnupg",
  ".kube",
  ".docker",
+5
warningExtremely long lines (>1000 chars)Very long lines in source files (not minified bundles) can hide malicious code.apps/desktop/resources/plugins/pi.file-manager/manifest.json+4
warningFlattened or dead control flowDetected switch(true), dead if branches, or deeply nested ternaries — patterns used by obfuscators to hide execution order.apps/desktop/resources/plugins/pi.browser/main.js+3
warningHigh-entropy string literalsFound 9 long strings with high Shannon entropy. This is common in obfuscated payloads that hide URLs, keys, or bytecode.apps/desktop/resources/plugins/pi.file-manager/main.js+3
warningFlattened or dead control flowDetected switch(true), dead if branches, or deeply nested ternaries — patterns used by obfuscators to hide execution order.apps/desktop/resources/plugins/pi.file-manager/main.js+3
warningFlattened or dead control flowDetected switch(true), dead if branches, or deeply nested ternaries — patterns used by obfuscators to hide execution order.apps/pi-host/src/app.ts+3
warningHigh-entropy string literalsFound 27 long strings with high Shannon entropy. This is common in obfuscated payloads that hide URLs, keys, or bytecode.packages/i18n/src/locales/de/index.ts+3
warningHigh-entropy string literalsFound 5 long strings with high Shannon entropy. This is common in obfuscated payloads that hide URLs, keys, or bytecode.packages/i18n/src/locales/fr/index.ts+3
warningLarge base64-encoded blobA 92-character base64 blob was found. May hide a remote payload or encoded executable code.packages/agent-runtime/src/image-generation/image-generation.test.ts
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8...
+3
warningLarge base64-encoded blobA 92-character base64 blob was found. May hide a remote payload or encoded executable code.packages/agent-runtime/src/image-generation/openai-images-contract.test.ts
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8...
+3
infoSuspicious file in repoVery large source file (4809KB) — could contain obfuscated payloadapps/desktop/resources/models.dev/api.json+2
infoSuspicious file in repoVery large source file (1314KB) — could contain obfuscated payloadapps/desktop/resources/plugins/pi.file-manager/views/assets/index.js+2
warningDependency runs install scripts"<root>/postinstall" executes code during installation. Malicious packages use this to drop payloads before the app even runs.package.json+3

Scores are heuristics. A “safe” verdict means no known-malicious patterns were found — clever malware can look boring. Wrong verdict? Flag it above; confirmed false positives become regression tests.

1546 files scanned @ 0598be2 | 9/25/2026 | heuristic scan — always review manually

risk by category
code execution25
network & exfiltration22
file system access20
obfuscation15
supply chain7
owasp / injection0
telemetry
files 1546/2349rules hit 31engine v6commit 0598be2

github

vastsa/pi-desktop

Local-first AI coding agent desktop: Electron + Rust host core + pi Agent Harness + user-installable plugins

TypeScript
5615
488
1283d
2349 files
1546 scanned(66%)
0598be2

architecture░▒▓

entry (0) flagged (297) pkg (103)
503 nodes · 1670 edgesscroll to zoom · click node to jump to finding
LOW (25/100) — vastsa/pi-desktop — ScanRepo