{"id":13546063,"url":"https://github.com/trailofbits/siderophile","last_synced_at":"2025-10-06T06:04:16.737Z","repository":{"id":36426323,"uuid":"187245932","full_name":"trailofbits/siderophile","owner":"trailofbits","description":"Find the ideal fuzz targets in a Rust codebase","archived":false,"fork":false,"pushed_at":"2025-03-24T11:18:33.000Z","size":3619,"stargazers_count":213,"open_issues_count":23,"forks_count":12,"subscribers_count":31,"default_branch":"master","last_synced_at":"2025-04-07T21:13:52.226Z","etag":null,"topics":["fuzzing","program-analysis","rust","security-testing"],"latest_commit_sha":null,"homepage":"https://blog.trailofbits.com/2019/07/01/siderophile-expose-your-crates-unsafety/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trailofbits.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-17T16:05:57.000Z","updated_at":"2025-04-04T04:44:51.000Z","dependencies_parsed_at":"2024-02-02T01:28:11.736Z","dependency_job_id":"21ab7a6c-806a-415c-a620-374bcebead2e","html_url":"https://github.com/trailofbits/siderophile","commit_stats":{"total_commits":176,"total_committers":15,"mean_commits":"11.733333333333333","dds":0.7102272727272727,"last_synced_commit":"23b58bf82df381a7ec039d607c2042ccc1cf6757"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fsiderophile","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fsiderophile/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fsiderophile/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trailofbits%2Fsiderophile/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trailofbits","download_url":"https://codeload.github.com/trailofbits/siderophile/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254374410,"owners_count":22060610,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fuzzing","program-analysis","rust","security-testing"],"created_at":"2024-08-01T12:00:30.908Z","updated_at":"2025-10-06T06:04:11.691Z","avatar_url":"https://github.com/trailofbits.png","language":"Rust","readme":"# Siderophile\n\n[![CI](https://github.com/trailofbits/siderophile/actions/workflows/ci.yml/badge.svg)](https://github.com/trailofbits/siderophile/actions/workflows/ci.yml)\n[![Crates.io](https://img.shields.io/crates/v/siderophile)](https://crates.io/crates/siderophile)\n\nSiderophile finds the \"most unsafe\" functions in your Rust codebase, so you can\nfuzz them or refactor them out entirely.\n\nIt checks the callgraph of each function in the codebase, estimates how many\n`unsafe` expressions are called in an evalutation of that function, then\nproduces a list sorted by this value. Here's what Siderophile's output format\nlooks like:\n\n```\nBadness  Function\n    092  \u003cmyProject::myThing as my_project::myThing\u003e::tempt_fate\n    064  \u003cmyProject::myOtherThing::whatever as my_project::myThing\u003e::defy_death\n    [...]\n```\n\n\"Badness\" of a function is simply an approximation of how many unsafe\nexpressions are evaluated during an evaluation of that function. For instance,\nmarking unsafe functions with a `*`, suppose your function `f` calls functions\n`g*` and `h`. Furthermore, `h` calls `i*`. Then the badness of `f` is 2.\nFunctions with high badness have a lot of opportunities to be memory unsafe.\n\n## Installation\n\nSiderophile is [available via crates.io](https://crates.io/crates/siderophile),\nand can be installed with `cargo`:\n\n```console\ncargo install siderophile\n```\n\nWhen you run that step, you *may* see an error from the `llvm-sys` crate:\n\n```console\nerror: No suitable version of LLVM was found system-wide or pointed\n              to by LLVM_SYS_190_PREFIX.\n\n              Consider using `llvmenv` to compile an appropriate copy of LLVM, and\n              refer to the llvm-sys documentation for more information.\n\n              llvm-sys: https://crates.io/crates/llvm-sys\n              llvmenv: https://crates.io/crates/llvmenv\n\nerror: could not compile `llvm-sys` due to previous error\n```\n\nThis indicates that the build was unable to automatically find a copy of LLVM to link against.\n\nYou can fix it by setting the `LLVM_SYS_190_PREFIX`. For example, for macOS with LLVM via\nHomebrew, you might do:\n\n```console\nLLVM_SYS_190_PREFIX=$(brew --prefix)/opt/llvm@19/ cargo install siderophile\n```\n\nYou _may_ run into other linker errors as well, e.g.:\n\n```\n  = note: ld: library not found for -lzstd\n          clang: error: linker command failed with exit code 1 (use -v to see invocation)\n```\n\nYou can fix this by setting the `LIBRARY_PATH`. For example, for macOS with\nHomebrew:\n\n```console\nLIBRARY_PATH=$(brew --prefix)/lib cargo install siderophile\n```\n\nTo tie it all together:\n\n```console\nLIBRARY_PATH=$(brew --prefix)/lib \\\n    LLVM_SYS_190_PREFIX=$(brew --prefix)/opt/llvm@19/\n    cargo install siderophile\n```\n\n### Building and installing from source\n\nAlternatively, if you'd like to build from source:\n\n```console\ngit clone https://github.com/trailofbits/siderophile \u0026\u0026 cd siderophile\n\n# TIP: include --release for a release build\ncargo build\n\n# optionally: install the built binary to cargo's default bin path\ncargo install --path .\n```\n\nYou may need the same `LLVM_SYS_190_PATH` and `LIBRARY_PATH` overrides\nmentioned above.\n\n## How to use\n\nMake sure that you followed the above steps, then do the following:\n\n1. `cd` to the root directory of the crate you want to analyze\n\n2. Run `siderophile --crate-name CRATENAME`,\n   where `CRATENAME` is the name of the crate you want to analyze\n\nFunctions are written to `stdout`, ordered by their badness.\n\n## How it works\n\nSiderophile extends `cargo-geiger`, whose goal is to find unsafety at the crate-level.\n\nFirst, the callgraph is created by having `cargo` output the crate's bitcode,\nthen parsing it to produce a callgraph and demangle the names into things that\nwe can match with the source code.\n\nNext, Siderophile finds all the sources of the current crate, finds every\nRust file in the sources, and parses each file individually using the `syn`\ncrate. Each file is recursively combed through for unsafety occurring in\nfunctions, trait declarations, trait implementations, and submodules.\nSiderophile will output the path of these objects, along with an indication\nof what type of syntactic block they were found in. The list received from this\nstep contains every unsafe block in every dependency of the crate, regardless\nof whether it's used. To narrow this down, Siderophile needs to compare its\nlist to nodes in the callgraph of the crate.\n\nUsing the callgraph produced in the first step, Siderophile checks which elements from the\noutput are actually executed from the crate in question. This\nstep (implemented in `src/callgraph_matching`) is not guaranteed to find\neverything, but it has shown good results against manual search. It is also not\nimmune to false positives, although none have been found yet. The labels of the\nnodes that are found to be unsafe are used as input for the final step.\n\nThe final step is to trace these unsafe nodes in the callgraph. For each node\nin the list, Siderophile will find every upstream node in the callgraph, and\nincrement their badness by one, thus indicating that they use unsafety at some\npoint in their execution. At the end of this process, all the nodes with nonzero\nbadness are printed out, sorted in descending order by badness.\n\n## Limitations\n\nSiderophile is _not_ guaranteed to catch all the unsafety in a crate's deps.\n\nSince things are only tagged at a source-level, Siderophile does not have the ability to\ninspect macros or resolve dynamically dispatched methods. Accordingly, this tool\nshould not be used to \"prove\" that a crate contains no unsafety.\n\n## Debugging\n\nTo get debugging output from `siderophile`, set the `RUST_LOG` environment\nvariable to `siderophile=XXX` where `XXX` can be `info`, `debug`, or `trace`.\n\n## Thanks\n\nTo [`cargo-geiger`](https://github.com/anderejd/cargo-geiger) and\n[`rust-praezi`](https://github.com/praezi/rust/) for current best practices.\nThis project is mostly due to their work.\n\n## License\n\nSiderophile is licensed and distributed under the AGPLv3 license.\n\n[Contact us](opensource@trailofbits.com) if you're looking for an exception to\nthe terms.\n","funding_links":[],"categories":["Vulnerability Assessment"],"sub_categories":["Static Code Auditing"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrailofbits%2Fsiderophile","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrailofbits%2Fsiderophile","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrailofbits%2Fsiderophile/lists"}