Scan Rust FFI boundary security issues
Scans FFI (Foreign Function Interface) boundary security in Rust projects. This skill provides more detailed FFI checks than /jss-unsafe, which only performs brief FFI checks to avoid duplication.
If $ARGUMENTS is provided, scan only that path. Otherwise scan the entire project.
Always exclude target/ and vendor/.
Cargo.toml to determine workspace structure. Check [dependencies] for FFI-related crates: libc, bindgen, cc, cxx, pyo3, napi, wasm-bindgenextern\s*"C" — FFI function definitions#\[no_mangle\] — externally exposed functionsextern\s*\{ — external function declarations (C library bindings)CStr|CString|c_char|c_void — C type usage#\[pyfunction\]|#\[pyfn\]#\[napi\] — napi functions#\[wasm_bindgen\] — wasm-bindgen functionsextern "C" functions dereferencing *const T / *mut T parameters without null checkCStr::from_ptr(ptr) called without null check*const c_char) received and converted with to_str().unwrap() without UTF-8 validationCString::new() called with input that may contain null bytes without validationString without length limits#[no_mangle] pub extern "C" fn — causes process abortunwrap(), expect(), panic!(), index access ([])catch_unwindResult return + error code conversion, or catch_unwind + error returnScope: only checks patterns visible within a single file. Cross-file ownership tracking is reported as "manual verification required".
into_raw() called without a corresponding from_raw() deallocation path in the same file/module (Warning)Box::from_raw used on C-allocated memory — allocator mismatch (Critical)libc::free and Box::drop (Critical)free_*) (Warning)extern { fn ... } blocks with manually written signatures — recommend bindgen#[repr(C)]errno check after calling C functionsextern "C" ABISend/Sync impl, verify the justificationAdditional checks when pyo3, napi, or wasm-bindgen are used:
pyo3:
#[pyfunction] — crashes the process if not converted to a Python exceptionPython::allow_threads (accessing without GIL is UB)napi:
#[napi] — crashes the process if not converted to a JS exceptionBuffer ownership — Rust taking ownership of a JS-passed Buffer may conflict with GCwasm-bindgen:
JsValue leaks — patterns using forget() to skip explicit deallocation## FFI Statistics
- extern "C" fn (exposed): ~N
- extern { fn ... } (bindings): ~N
- #[no_mangle]: ~N
- FFI-related crates: libc, bindgen, ...
- High-level bindings: pyo3 / napi / wasm-bindgen (if applicable)
Follow suppression rules in CLAUDE.md.
Follow the common output format in CLAUDE.md.