Development
Scanning Python programs with Bandit
Using a program written in a particular language to search for problems in another program written in that same language has a certain amount of charm. High-level languages, such as Python, can actually give programmers easy access to the data structures built by the parser, so that these analysis programs can see the program exactly as the interpreter does. An OpenStack sub-project called Bandit does exactly that. It uses the Python abstract syntax tree (ast) module to seek out potential security problems in Python code.
OpenStack is a free-software cloud platform that is written in Python—over a million lines of it—so it makes sense for the project to have tools to look for problems in its code. Bandit comes from the OpenStack Security Group and is specifically targeted at finding security flaws in the OpenStack—or any other Python—code base. It is structured as a framework that reads in and parses the source code, then runs through a battery of tests, implemented as plugins, to seek out the use of dubious Python modules and functions, potentially dangerous code constructs, and more.
The README file outlines how to clone and install Bandit into a Python virtual environment, though it can also be installed without the virtual environment in the usual fashion:
$ python setup.py install
From there it is simple to run; just pass a bunch of Python files to the
Bandit program:
$ bandit examples/*.py
The examples directory contains a full set of programs that
demonstrate each of the rules that Bandit is enforcing. In fact, new tests
proposed for merging must be accompanied with an example file to
demonstrate the dubious code
that Bandit will be detecting.
Running Bandit on a moderately sized body of Python code—one that runs a nearby web site—produced an 800-line report that mostly contained false positives. That is not really a surprise for a couple of reasons. For one, the tool and tests are geared toward OpenStack and how it uses Python and its modules. For example, any strings that looked like SQL were flagged as SQL injection warnings—unless the SQLAlchemy module is imported (in which case the severity is reduced to informational). That may make sense for OpenStack, but other projects may have their own mechanisms to avoid SQL injection.
In addition, one totally unrelated string that happened to contain both "select" and "from" triggered the warning. The tests would need to be much more sophisticated to avoid that kind of false positive.
Beyond that, though, a tool of this nature needs to be pretty conservative about skipping over potential problems. That means it will alert on lots of things that aren't actually vulnerabilities, but require a human to determine that. Thus, false positives.
But the list of warnings definitely had some things to look into. For
example, there are complaints about network services that may be binding to
all interfaces on the system, which may be unexpected. Use of the
os.popen() function is generally frowned upon and its use requires some
investigation. Use of the random module "is not suitable
for security/cryptographic purposes
", which is probably not how it
is being used, but it should be looked into. And so on.
Beyond the SQL injection complaints, the most common warning was for the use of the pickle module, which can have security (and maintenance) implications. Its use in this code base should be safe (though it is something we plan to replace for other reasons at some point). Disabling those top two warning types resulted in a much shorter report, with only 14 warnings to investigate.
While disabling the pickle test was easy to do, by commenting out some lines in the bandit.yaml configuration file, turning off the SQL injection tests was not quite as straightforward. Since many of the tests are plugins, moving the injection_sql.py file aside in the install plugins directory worked well enough to disable it, but was rather inelegant. A more proper solution was to set up a profile in the configuration file that excluded the hardcoded_sql_expressions test.
Another option is to go through the source and annotate any line that causes a false positive with a "# nosec" comment. One could also filter the results based on the level of the complaint (i.e. information, warning, or error) though, in this case, that would likely mask some problems. Those with an aversion to colored output will want to use the -o file option to send the output to a file (thankfully without the color escape sequences).
Taking a spin through the examples
directory will give a good overview of the kinds of things Bandit is
looking for. As noted earlier, much of it is advisory in nature, like
complaints about calling eval() (which is a warning, though calling exec() is
considered an error), use of os.exec() and os.spawn(),
use of the MD5 hash function, or any strings from a list of often-used default
passwords.
Beyond that, there are warnings about urllib.urlopen()
("Audit url open for permitted schemes. Allowing use of file:/ or
custom schemes is often unexpected.
"), yaml.load()
(recommending yaml.safe_load() in its place), mark_safe()
(a potential cross-site scripting vector), and so on.
Any of those could be security problems or
completely innocuous, but someone needs to look to be sure.
OpenStack plans to add Bandit into its continuous integration system, and eventually may have it actually reject patches that don't pass. That is still probably a ways off based on the kinds of warnings it is producing now. Those classified as errors might be suitable, however. As with most projects, though, there is a pretty long to-do list on the web page.
For other projects, Bandit will likely take some tweaking to reduce the false positive rate based on the project's coding style and typical Python usage. That should be pretty easy to do, as the framework provides much of what is needed to write these types of tests. Adding new tests (or modifying existing ones) is straightforward, with plenty of code to look at for ideas. Bandit is well worth a look for Python-based projects.
Brief items
Quotes of the week
Wayland 1.7.0
Bryce Harrington has announced the release of Wayland 1.7.0. "The Wayland protocol may be considered "done" but that doesn't mean there's not work to be done. This release focused on major improvements to Wayland's documentation, minor improvements to the testsuite, and some scattered bugfixes to the code itself."
PulseAudio 6.0 available
Version 6.0 of the PulseAudio framework has been released. New is support for several Bluetooth audio profiles under BlueZ 5, socket activation using systemd, and improved support for multi-channel audio profiles.
cmocka 1.0 available
Version 1.0 of the cmocka unit-testing framework has been released. Notably, the 1.0 release features a new test runner that allows tests to be grouped, although there are many other updates and improvements to be found.
SystemTap 2.7 available
Version 2.7 of the SystemTap instrumentation system has been released. New in this release are several changes to the tracepoint probe behavior, speed-ups when passing string data to and from functions, and a great many changed tapsets and scripts. The new release also happens to coincide with SystemTap's 10th anniversary as a project.
Newsletters and articles
Development newsletters from the past week
- What's cooking in git.git (February 11)
- What's cooking in git.git (February 17)
- GNU Toolchain Update (February)
- LLVM Weekly (February 16)
- OCaml Weekly News (February 17)
- OpenStack Community Weekly Newsletter (February 13)
- Perl Weekly (February 16)
- PostgreSQL Weekly News (February 15)
- Python Weekly (February 12)
- Qt Weekly (February 17)
- Ruby Weekly (February 12)
- This Week in Rust (February 17)
- Tor Weekly News (February 18)
- Wikimedia Tech News (February 16)
Routing on OpenStreetMap.org
The OpenStreetMap blog announced
the roll-out of point-to-point direction routing on the main OSM
site. Historically, OSM has encouraged other developers to build this
sort of functionality on top of the OSM data set, but has presented a
limited interface on its own site. "But we have a saying: “what gets rendered, gets mapped” – meaning that often you don’t notice a bit of data that needs tweaking unless it actually shows up on the map image. Lots of things aren’t shown on our default rendering, so the feedback loop offers less incentive for people to get them correct. And that goes doubly for things that you never “see” on the map – subtle things like “no left turn” at a particular junction, or “busses only” access on a tiny bit of road, or tricky data issues like when a footpath doesn’t quite join a road that it should join on to. Now that people can see a recommended route directly on the OSM homepage, they have an incentive to quickly pop in and fix little issues like that. The end effect will be OSM’s data going up one more level in terms of its quality for routing.
"
Page editor: Nathan Willis
Next page:
Announcements>>
