A Leiningen plugin responsible for finding possible vulnerabilities. Totally inspired on borkdude's grasp.
You can define your own set of rules just by writting a edn like the following one.
{:name :shell-injection
:description "Detect usage of bash -c on clojure.java.shell/sh invoke."
:checks [{:type :import-and-usage
:ns-name "clojure.java.shell"
:function-name "sh"
:function-spec-builder (fn [namespaced-fn]
(s/* (s/cat :before (s/* any?)
:fn-name (fn [symbol] (= namespaced-fn symbol))
:bash-args (fn [bash-arg]
(->> bash-arg
(re-matches (re-pattern "sh|bash"))
nil?
not))
:bash-c-arg (fn [bash-c-arg]
(= "-c" bash-c-arg))
:args (s/* any?))))}]}
Which one of them needs to specify the rule name, a description and the steps to check if the code is vulnerable. There are two types of checks.
Both of them needs to define in the checks a namespace, function name and optionally a fn which returns a spec representing the function usage.
in order to use your custom rules just save then as an edn file on a directory and specify it on the plugin usage.
Use this for user-level plugins:
Put [inspector-gadget "0.1.0-SNAPSHOT"]
into the :plugins
vector of your :user
profile.
Use this for project-level plugins:
Put [inspector-gadget "0.1.0-SNAPSHOT"]
into the :plugins
vector of your project.clj.
Execute it on your project directory.
$ lein inspector-gadget
or with a custom directory for rules.
$ lein inspector-gadget /tmp/rules/
({:filename "/home/user/dev/projects/test/src/shit/vulnerable-code.clj",
:findings
({:name :clojure-xml-xxe,
:description
"Detect usage of vulnerable XML parser on clojure.xml.",
:checks
[{:type :import-and-usage,
:ns-name "clojure.xml",
:function-name "parse"}],
:findings
({:dependency {:alias "xml", :code [clojure.xml :as xml]},
:findings
[{:line 16, :column 7, :code (xml/parse istream)}
{:line 21,
:column 1,
:code (-> "/home/user/image.svg" slurp xml/parse)}],
:type :import-and-usage})}
{:name :read-string,
:description "Detect usage of vulnerable read-string function.",
:checks
[{:type :usage,
:ns-name "clojure.core",
:function-name "read-string"}],
:findings
({:dependency "clojure.core",
:findings
[{:line 8, :column 3, :code (read-string "a")}
{:line 9, :column 3, :code (-> b read-string (+ 1))}],
:type :usage})}
{:name :shell-injection,
:description
"Detect usage of bash -c on clojure.java.shell/sh invoke.",
:checks
[{:type :import-and-usage,
:ns-name "clojure.java.shell",
:function-name "sh",
:function-spec-builder
(fn
[namespaced-fn]
(s/*
(s/cat
:before
(s/* any?)
:fn-name
(fn [symbol] (= namespaced-fn symbol))
:bash-args
(fn
[bash-arg]
(->> bash-arg (re-matches (re-pattern "sh|bash")) nil? not))
:bash-c-arg
(fn [bash-c-arg] (= "-c" bash-c-arg))
:args
(s/* any?))))}],
:findings
({:dependency
{:alias "shell", :code [clojure.java.shell :as shell]},
:findings [{:line 25, :column 8, :code (shell/sh "bash" "-c")}],
:type :import-and-usage})})})
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close