Giter Site home page Giter Site logo

pycqa / bandit Goto Github PK

View Code? Open in Web Editor NEW
6.0K 67.0 580.0 5.54 MB

Bandit is a tool designed to find common security issues in Python code.

Home Page: https://bandit.readthedocs.io

License: Apache License 2.0

Python 99.94% Dockerfile 0.06%
linter bandit security-tools security-scanner security static-code-analysis python

bandit's Introduction

Bandit


Build Status

Docs Status

Latest Version

Python Versions

Format

License

Discord

A security linter from PyCQA

Overview

Bandit is a tool designed to find common security issues in Python code. To do this Bandit processes each file, builds an AST from it, and runs appropriate plugins against the AST nodes. Once Bandit has finished scanning all the files it generates a report.

Bandit was originally developed within the OpenStack Security Project and later rehomed to PyCQA.

Bandit Example Screen Shot

Show Your Style

Security Status

Use our badge in your project's README!

using Markdown:

[![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)

using RST:

.. image:: https://img.shields.io/badge/security-bandit-yellow.svg
    :target: https://github.com/PyCQA/bandit
    :alt: Security Status

References

Python AST module documentation: https://docs.python.org/3/library/ast.html

Green Tree Snakes - the missing Python AST docs: https://greentreesnakes.readthedocs.org/en/latest/

Documentation of the various types of AST nodes that Bandit currently covers or could be extended to cover: https://greentreesnakes.readthedocs.org/en/latest/nodes.html

Container Images

Bandit is available as a container image, built within the bandit repository using GitHub Actions. The image is available on ghcr.io:

docker pull ghcr.io/pycqa/bandit/bandit

The image is built for the following architectures:

  • amd64
  • arm64
  • armv7
  • armv8

To pull a specific architecture, use the following format:

docker pull --platform=<architecture> ghcr.io/pycqa/bandit/bandit:latest

Every image is signed with sigstore cosign and it is possible to verify the source of origin using the following cosign command:

cosign verify ghcr.io/pycqa/bandit/bandit:latest \
  --certificate-identity https://github.com/pycqa/bandit/.github/workflows/build-publish-image.yml@refs/tags/<version> \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

Where <version> is the release version of Bandit.

bandit's People

Contributors

ajaeger avatar baranpirincal avatar cjschaef avatar costaparas avatar cyrilroelandtenovance avatar daviey avatar dependabot[bot] avatar ehooo avatar elmiko avatar ericwb avatar evqna avatar finnigja avatar gecong1973 avatar ghugo avatar liujiong63 avatar ljfisher avatar lukehinds avatar mkniewallner avatar mportesdev avatar mrdolev avatar nkinder avatar pre-commit-ci[bot] avatar qinchunhua avatar rajathagasthya avatar sigmavirus24 avatar stannum-l avatar sudhiragarwal098 avatar tylerwince avatar ushyd202 avatar viraptor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bandit's Issues

Running Bandit with -v causes traceback

Running Bandit with -v (verbose mode) causes a traceback:

MacBook-Pro:bandit_json_bug travismcpeak$ bandit -v test_file2.py
[bandit] INFO using config: /usr/local/etc/bandit/bandit.yaml
[bandit] INFO running on Python 2.7.10
[node_visitor] INFO Unable to find qualified name for module: test_file2.py
Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/usr/local/lib/python2.7/site-packages/bandit/bandit.py", line 267, in main
args.output_format)
File "/usr/local/lib/python2.7/site-packages/bandit/core/manager.py", line 174, in output_results
lines=lines, out_format=output_format)
File "/usr/local/lib/python2.7/site-packages/bandit/formatters/text.py", line 67, in report
manager.scores)):
TypeError: sum_scores() takes exactly 2 arguments (1 given)

Tons of errors when running with config

When running against Keystone with the Keystone profile file (-c bandit.yaml -p gate) we get a ton of errors like:

[tester] ERROR Bandit internal error running: blacklist on file /Users/travismcpeak/Documents/projects/OpenStack_projects/keystone/keystone/common/clean.py at line 67: 'qualnames'Traceback (most recent call last):
File "/Users/travismcpeak/Documents/projects/bandit/bandit/core/tester.py", line 62, in run_tests
result = test(context, test._config)
File "/Users/travismcpeak/Documents/projects/bandit/bandit/core/blacklisting.py", line 48, in blacklist
for qn in check['qualnames']:
KeyError: 'qualnames'

Running Bandit with -v causes traceback

Running Bandit with -v (verbose mode) causes a traceback:

MacBook-Pro:bandit_json_bug travismcpeak$ bandit -v test_file2.py
[bandit] INFO using config: /usr/local/etc/bandit/bandit.yaml
[bandit] INFO running on Python 2.7.10
[node_visitor] INFO Unable to find qualified name for module: test_file2.py
Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/usr/local/lib/python2.7/site-packages/bandit/bandit.py", line 267, in main
args.output_format)
File "/usr/local/lib/python2.7/site-packages/bandit/core/manager.py", line 174, in output_results
lines=lines, out_format=output_format)
File "/usr/local/lib/python2.7/site-packages/bandit/formatters/text.py", line 67, in report
manager.scores)):
TypeError: sum_scores() takes exactly 2 arguments (1 given)

KeyError when using '-a vuln'

When using the "-a vuln" option for the bandit command line, I get a KeyError.

promd-1s-dhcp317:bandit browne$ bandit -r ../glance/glance/ -a vuln
315 [0.. 50.. 100.. 150.. 200.. 250.. 300.. ]
Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/Library/Python/2.7/site-packages/bandit/bandit.py", line 88, in main
args.output_format)
File "/Library/Python/2.7/site-packages/bandit/core/manager.py", line 112, in output_results
output_format=output_format
File "/Library/Python/2.7/site-packages/bandit/core/result_store.py", line 382, in report
level=level) # noqa
File "/Library/Python/2.7/site-packages/bandit/core/result_store.py", line 324, in report_tty
issue['lineno'],
KeyError: 'lineno'

Severity filtering is broken

When I run latest Bandit against Keystone, even if I filter for medium+ severity I still get "low" severity results:

MacBook-Pro:bandit travismcpeak$ bandit -r ~/Documents/projects/OpenStack_projects/keystone -ll
[bandit] INFO using config: /usr/local/etc/bandit/bandit.yaml
[bandit] INFO running on Python 2.7.10
[general_hardcoded_password] WARNING Using relative path for word_list: ./wordlist/default-passwords

[general_hardcoded_password] WARNING Using relative path for word_list: ./wordlist/default-passwords

[general_hardcoded_password] WARNING Using relative path for word_list: ./wordlist/default-passwords

[general_hardcoded_password] WARNING Using relative path for word_list: ./wordlist/default-passwords

[general_hardcoded_password] WARNING Using relative path for word_list: ./wordlist/default-passwords

[general_hardcoded_password] WARNING Using relative path for word_list: ./wordlist/default-passwords

[general_hardcoded_password] WARNING Using relative path for word_list: ./wordlist/default-passwords

[general_hardcoded_password] WARNING Using relative path for word_list: ./wordlist/default-passwords

Run started:
2015-09-10 16:35:12.800785

Files skipped (0):

Test results:

Issue: Try, Except, Pass detected.
Severity: Low Confidence: High
Location: /Users/travismcpeak/Documents/projects/OpenStack_projects/keystone/.tox/bandit/lib/python2.7/_abcoll.py:325
324 self.pop()
325 except KeyError:
326 pass

hardcoded_password throws a traceback when processing tuples

Running Bandit on the following produces a traceback in the hardcoded password plugin:

def sort_by_release((hash, version)):
do_something()

[tester] ERROR Bandit internal error running: hardcoded_password_default on file test_traceback.py at line 1: 'Tuple' object has no attribute 'id'Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/bandit/core/tester.py", line 73, in run_tests
result = test(context)
File "/usr/local/lib/python2.7/site-packages/bandit/plugins/general_hardcoded_password.py", line 78, in hardcoded_password_default
check = key.arg if sys.version_info.major > 2 else key.id # Py3
AttributeError: 'Tuple' object has no attribute 'id'

BanditManager instance has no attribute '_init_logger'

To recreate:

  • edit bandit.yaml and uncomment log_format
  • run bandit with this modified bandit.yaml
  • boom

ericwb@ericwb-virtual-machine:~/bandit$ .tox/py27/bin/bandit -c bandit/config/bandit.yaml -r examples/
Traceback (most recent call last):
File ".tox/py27/bin/bandit", line 10, in
sys.exit(main())
File "/home/ericwb/bandit/bandit/bandit.py", line 189, in main
verbose=args.verbose)
File "/home/ericwb/bandit/bandit/core/manager.py", line 55, in init
self.logger = self._init_logger(debug, log_format=log_format)
AttributeError: BanditManager instance has no attribute '_init_logger'

Bandit freezes when start it with key -r against directory with __init__.py file

Bandit freezes when start it with key -r against directory with init.py file

Steps to reproduce:

  1. Create dir sec_scan
  2. Create 2 files:
  • init.py - contains one string (comment - see below)
  • base.py - see content below
  1. Execute bandit -r sec_scan/

Actual result it is freezes on checking init.py file

The output of executing:

/tests/sec_scan$ ls
base.py init.py
/tests/sec_scan$ cat base.py

try:
from unittest.case import TestCase
except ImportError:
# Runing unit-tests in production environment
from unittest2.case import TestCase

from mock import patch

import logging
import os
import shutil
import subprocess
import sys
import tempfile

logging.basicConfig(stream=sys.stderr)
log = logging.getLogger("CliTest.ExecutionLog")
log.setLevel(logging.DEBUG)

class CliExectutionResult:
def init(self, process_handle, out, err):
self.return_code = process_handle.returncode
self.stdout = out
self.stderr = err

/tests/sec_scan$ cat init.py

Copyright 2013

(fuel-devops-venv)ykotko@ykotko-pc:~/FRESH-FUEL_MAIN/fuel-main/python-fuelclient/fuelclient/tests$ bandit -r sec_scan/
[bandit] INFO using config: /home/ykotko/FRESH-FUEL_MAIN/fuel-qa/fuel-devops-venv/etc/bandit/bandit.yaml
[bandit] INFO running on Python 2.7.6

----FREEZES---

/tests$ bandit -r sec_scan/
[bandit] INFO using config: /home/ykotko/FRESH-FUEL_MAIN/fuel-qa/fuel-devops-venv/etc/bandit/bandit.yaml
[bandit] INFO running on Python 2.7.6
Run started:
2016-01-27 15:32:40.661932

Run metrics:
Total lines of code: 19
Total lines skipped (#nosec): 0
Total issues (by severity):
Undefined: 0
Low: 1
Medium: 0
High: 0
Total issues (by confidence):
Undefined: 0
Low: 0
Medium: 0
High: 1

Files skipped (0):

Test results:

Issue: [blacklist_imports] Consider possible security implications associated with subprocess module.

Severity: Low Confidence: High
Location: sec_scan/base.py:13
12 import shutil
13 import subprocess
14 import sys


Incorrect line number in results

PoC code:

class InnoBackupEx(base.BackupRunner):
"""Implementation of Backup Strategy for InnoBackupEx."""
strategy_name = 'innobackupex'

@property
def cmd(self):
    cmd = ('sudo innobackupex'
           ' --stream=xbstream'
           ' %(extra_opts)s'
           ' /var/lib/mysql 2>/tmp/innobackupex.log'
           )
    return cmd + self.zip_cmd + self.encrypt_cmd

Run Bandit against this code, it reports:

Issue: Probable insecure usage of temp file/directory.
Severity: Medium Confidence: Medium
Location: examples/line_no_test.py:7
6 def cmd(self):
7 cmd = ('sudo innobackupex'
8 ' --stream=xbstream'

The actual issue is on line 10.

Bandit throws traceback when running against examples/nonsense.py

When running against the nonsense example, we get a traceback:

MacBook-Pro:bandit travismcpeak$ bandit examples/nonsense.py
[bandit] INFO using config: /usr/local/etc/bandit/bandit.yaml
[bandit] INFO running on Python 2.7.10
Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/usr/local/lib/python2.7/site-packages/bandit/bandit.py", line 267, in main
args.output_format)
File "/usr/local/lib/python2.7/site-packages/bandit/core/manager.py", line 174, in output_results
lines=lines, out_format=output_format)
File "/usr/local/lib/python2.7/site-packages/bandit/formatters/text.py", line 95, in report
rank)]
KeyError: 'SEVERITY.UNDEFINED'

Given it's by definition a nonsense Python file, we still need to handle the situation gracefully.

KeyError when using '-a vuln'

When using the "-a vuln" option for the bandit command line, I get a KeyError.

promd-1s-dhcp317:bandit browne$ bandit -r ../glance/glance/ -a vuln
315 [0.. 50.. 100.. 150.. 200.. 250.. 300.. ]
Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/Library/Python/2.7/site-packages/bandit/bandit.py", line 88, in main
args.output_format)
File "/Library/Python/2.7/site-packages/bandit/core/manager.py", line 112, in output_results
output_format=output_format
File "/Library/Python/2.7/site-packages/bandit/core/result_store.py", line 382, in report
level=level) # noqa
File "/Library/Python/2.7/site-packages/bandit/core/result_store.py", line 324, in report_tty
issue['lineno'],
KeyError: 'lineno'

After excluding plugin from the bandit.yaml it still was used during the scaning

Steps to reproduce:

  1. Create virtual environment #virtualenv venv
  2. Activate it #. venv/bin/activate
  3. Change bandit.yaml section "exclude" http://paste.openstack.org/show/489562/
  4. Start bandit on any code:
    #bandit -c my-bandit.yaml -r /web_test/ >> qwe

Actual result:

The result contains report from test "assert_used":
Issue: [assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
Severity: Low Confidence: High
Location: /home/ykotko/FRESH-FUEL_MAIN/fuel-qa/fuelweb_test/models/fuel_web_client.py:1878
1877 else:
1878 assert 'No cluster_deletion task found!'
1879

Uncaught exception when running against standalone file

When running Bandit on setup.py (from its own directory) there is an uncaught exception:

(band)MacBook-Pro:bandit travismcpeak$ bandit -n 5 setup.py
Traceback (most recent call last):
File "/Users/travismcpeak/Documents/projects/bandit/band/bin/bandit", line 10, in
sys.exit(main())
File "/Users/travismcpeak/Documents/projects/bandit/band/lib/python2.7/site-packages/bandit/bandit.py", line 74, in main
b_mgr.run_scope(args.files)
File "/Users/travismcpeak/Documents/projects/bandit/band/lib/python2.7/site-packages/bandit/core/manager.py", line 134, in run_scope
self.b_rs, self.b_ts
File "/Users/travismcpeak/Documents/projects/bandit/band/lib/python2.7/site-packages/bandit/core/manager.py", line 170, in _execute_ast_visitor
fname, self.logger, self.b_conf, b_ma, b_rs, b_ts, self.debug
File "/Users/travismcpeak/Documents/projects/bandit/band/lib/python2.7/site-packages/bandit/core/node_visitor.py", line 60, in init
self.namespace = b_utils.get_module_qualname_from_path(fname)
File "/Users/travismcpeak/Documents/projects/bandit/band/lib/python2.7/site-packages/bandit/core/utils.py", line 134, in get_module_qualname_from_path
' Missing path or file name' % (path))
bandit.core.utils.InvalidModulePath: Invalid python file path: "setup.py" Missing path or file name

We should catch the exception and generate some sort of meaningful warning/log output based on it.

/tmp plugin struggles with multi-line strings

The hard-coded /tmp plugin doesn't handle multi-line strings very well. Maybe some code could be borrowed from the SQL injection plugin.

In this example, only lines 1 and 3 are in the report. Line 2, with "/tmp" itself, is missing:
x = """
/tmp
"""

In this example, only line 4 (the closing """) is emitted in the report:
def f():
"""
/tmp
"""

Bandit should gracefully handle file errors

Bandit dumps tracebacks when it fails to access files. It would be preferrable if Bandit gracefully handled the exceptions and displayed a user appropriate error. Also, it should be checking for the existence of the output file prior to running the scan.

promd-1s-dhcp317:bandit browne$ bandit -r ../openstack/ -o /Library/
86 [0.. 50.. ]
Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/Library/Python/2.7/site-packages/bandit/bandit.py", line 88, in main
args.output_format)
File "/Library/Python/2.7/site-packages/bandit/core/manager.py", line 112, in output_results
output_format=output_format
File "/Library/Python/2.7/site-packages/bandit/core/result_store.py", line 393, in report
with open(output_filename, 'w') as fout:
IOError: [Errno 21] Is a directory: '/Library/'

promd-1s-dhcp317:bandit browne$ bandit -r ../openstack/ -o /Library/sfd
86 [0.. 50.. ]
Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/Library/Python/2.7/site-packages/bandit/bandit.py", line 88, in main
args.output_format)
File "/Library/Python/2.7/site-packages/bandit/core/manager.py", line 112, in output_results
output_format=output_format
File "/Library/Python/2.7/site-packages/bandit/core/result_store.py", line 393, in report
with open(output_filename, 'w') as fout:
IOError: [Errno 13] Permission denied: '/Library/sfd'

After excluding plugin from the bandit.yaml it still was used during the scaning

Steps to reproduce:

  1. Create virtual environment #virtualenv venv
  2. Activate it #. venv/bin/activate
  3. Change bandit.yaml section "exclude" http://paste.openstack.org/show/489562/
  4. Start bandit on any code:
    #bandit -c my-bandit.yaml -r /web_test/ >> qwe

Actual result:

The result contains report from test "assert_used":
Issue: [assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
Severity: Low Confidence: High
Location: /home/ykotko/FRESH-FUEL_MAIN/fuel-qa/fuelweb_test/models/fuel_web_client.py:1878
1877 else:
1878 assert 'No cluster_deletion task found!'
1879

JSON report ignores #nosec and severity

Bandit's JSON report doesn't exclude lines marked #nosec. The JSON report also doesn't respect the -l CLI flag, which only shows higher-severity issues in the text report. The command bandit -f json -lll examples/skip.py demonstrates both issues.

As an aside, perhaps #nosec lines shouldn't be scored at all. Right now it's up to the individual reports to filter out these lines. That's the reason tests/test_functional:FunctionalTests.test_skip is skipped right now: #nosec lines receive a score.

Bandit Baseline with severity filtering is broken

If the baseline feature is used along with severity filtering the results end up broken.

Basically, the current baseline routine is to check if there are different results in the currently checked file than what is present in the baseline. If so, all the issues from the current file are inputted and then filtered. To make this clear let's say we have original file a.py:

import subprocess
do_something_benign()
os.system('/tmp/something_bad')

We'll get a low severity finding for subprocess usage, but if we examine this file with a -ll filter, this will be suppressed from the baseline output. We also get a higher severity error which for /tmp.

Now we run a baseline comparison against it, the first action that is performed is checking the results against the previous level. Since the previous level had the LOW severity finding filtered out, it only has the MEDIUM. Since no filtering has been done yet, the current version of the file includes the low severity issue. Basically the baseline has the low severity issue filtered out and the current version doesn't. So they don't match and all of the issues from the file get added to the results.

At this point filtering is done so the LOW severity issue is removed, but the point is even though nothing changed in this file Bandit thinks it did.

The correct behavior is to filter severity first.

Tons of errors when running with config

When running against Keystone with the Keystone profile file (-c bandit.yaml -p gate) we get a ton of errors like:

[tester] ERROR Bandit internal error running: blacklist on file /Users/travismcpeak/Documents/projects/OpenStack_projects/keystone/keystone/common/clean.py at line 67: 'qualnames'Traceback (most recent call last):
File "/Users/travismcpeak/Documents/projects/bandit/bandit/core/tester.py", line 62, in run_tests
result = test(context, test._config)
File "/Users/travismcpeak/Documents/projects/bandit/bandit/core/blacklisting.py", line 48, in blacklist
for qn in check['qualnames']:
KeyError: 'qualnames'

Using --number with lines greater than 3 does not change context

Using --number with lines less than 3 will correctly trim output. For example:

bandit -r --number 1 glances/glances/

Issue: Try, Except, Pass detected.
Severity: Low Confidence: High
Location: glances/glances/plugins/glances_sensors.py:26
26 except ImportError:

Issue: Try, Except, Pass detected.
Severity: Low Confidence: High
Location: glances/glances/plugins/glances_uptime.py:76
76 except Exception:

However, using --number greater than 3 does not adjust the output. It still uses only 3 lines maximum.

bandit -r --number 10 glances/glances/

Issue: Try, Except, Pass detected.
Severity: Low Confidence: High
Location: glances/glances/plugins/glances_uptime.py:76
75 self.stats = str(timedelta(seconds=int(uptime) / 100))
76 except Exception:
77 pass

'NoneType' object has no attribute '__getitem__'

Running bandit analysis against the cinder code base I am getting many of the following output:

[tester] ERROR Bandit internal error running: try_except_pass on file cinder/api/contrib/admin_actions.py at line 97: 'NoneType' object has no attribute 'getitem'Traceback (most recent call last):
File "/home/smcginnis/Documents/dev/repos/OpenStack/cinder/.tox/bandit/local/lib/python2.7/site-packages/bandit/core/tester.py", line 63, in run_tests
result = test(context, test_config)
File "/home/smcginnis/Documents/dev/repos/OpenStack/cinder/.tox/bandit/local/lib/python2.7/site-packages/bandit/plugins/try_except_pass.py", line 28, in try_except_pass
if (not config['check_typed_exception'] and
TypeError: 'NoneType' object has no attribute 'getitem'

It appears config is not being passed in by takes_config.

Other plugins using takes_config do not show this error, just try_except_pass. The other plugins also appear to be importing and declaring the decorator slightly different.

I found switching the import to match some of the other ones or keeping the import as is but adding parenthesis to the decorator makes the problem go away. Not sure how these really make a difference.

Using Python 2.7.6 on Ubuntu 14.01.

Bandit throws traceback when running against examples/nonsense.py

When running against the nonsense example, we get a traceback:

MacBook-Pro:bandit travismcpeak$ bandit examples/nonsense.py
[bandit] INFO using config: /usr/local/etc/bandit/bandit.yaml
[bandit] INFO running on Python 2.7.10
Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/usr/local/lib/python2.7/site-packages/bandit/bandit.py", line 267, in main
args.output_format)
File "/usr/local/lib/python2.7/site-packages/bandit/core/manager.py", line 174, in output_results
lines=lines, out_format=output_format)
File "/usr/local/lib/python2.7/site-packages/bandit/formatters/text.py", line 95, in report
rank)]
KeyError: 'SEVERITY.UNDEFINED'

Given it's by definition a nonsense Python file, we still need to handle the situation gracefully.

Incorrect line number in results

PoC code:

class InnoBackupEx(base.BackupRunner):
"""Implementation of Backup Strategy for InnoBackupEx."""
strategy_name = 'innobackupex'

@property
def cmd(self):
    cmd = ('sudo innobackupex'
           ' --stream=xbstream'
           ' %(extra_opts)s'
           ' /var/lib/mysql 2>/tmp/innobackupex.log'
           )
    return cmd + self.zip_cmd + self.encrypt_cmd

Run Bandit against this code, it reports:

Issue: Probable insecure usage of temp file/directory.
Severity: Medium Confidence: Medium
Location: examples/line_no_test.py:7
6 def cmd(self):
7 cmd = ('sudo innobackupex'
8 ' --stream=xbstream'

The actual issue is on line 10.

Recursion level reached when visiting nodes

File /usr/lib/python2.7/dist-packages/idna/idnadata.py (available in most system installation) is a good testcase for recursion limit. Current bandit master breaks on the file. It should either succeed or recover gracefully with a good error message.

context.check_call_arg_value flags shell=True and shell='True'

Running Bandit against the code:
subprocess.Popen('/bin/gcc --version', shell=True)
subprocess.Popen('/bin/gcc --version', shell='True')

.. results in two issues being flagged.

The check in plugins/injection_shell.py is essentially made up of the line:
if context.check_call_arg_value('shell', 'True'):
..

This implies that it is checking for a string rather than a boolean. I believe this should only flag an issue where the True bool is being used, rather than the string 'True'?

$ bandit examples/broken.py -n 1
[bandit] INFO using config: /Users/finnigaj/repo/bandit/venv27/bin/../etc/bandit/bandit.yaml
[bandit] INFO running on Python 2.7.10
Run started:
2015-10-12 20:46:14.772219

Files skipped (0):

Test results:

Issue: subprocess call with shell=True identified, security issue.
Severity: High Confidence: High
Location: examples/bah.py:1
1 subprocess.Popen('/bin/gcc --version', shell=True)

Issue: subprocess call with shell=True identified, security issue.
Severity: High Confidence: High
Location: examples/bah.py:2
2 subprocess.Popen('/bin/gcc --version', shell='True')

Running bandit after default installation lists no plugins

When installed with no other changes, bandit will not detect any plugins. Tests end successful, even though no checks are really run.
It's not obvious unless bandit is run with --help which does provide an empty list of loaded plugins: "The following plugin suites were discovered and loaded: []"

Main issue seems to be that plugins not listed as entry points will not be detected by stevedore.

System wide pip install fails on some platforms

A system wide $ sudo pip install bandit fails to report any findings for some projects. This is a problem for some CICD work I'm doing which means I generally have to create a wrapper script like:

#!/bin/bash
source /some_virtenv/bin/activate
bandit $@

Which is less than ideal.

Steps to reproduce consistently

  1. Create a VagrantFile with the following content:

Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.provider "virtualbox" do |v|
v.customize ["modifyvm", :id, "--memory", "2048"]
end
end

Start vagrant vm (assumes virtual box provider)

  1. vagrant up
  2. vagrant ssh

Inside vagrant vm

  1. sudo apt-get update
  2. sudo apt-get upgrade
  3. sudo apt-get install python-pip git
  4. sudo pip install -U pip
  5. sudo pip install bandit
  6. git clone https://git.openstack.org/openstack/trove
  7. cd trove
  8. bandit -r .

Actual output:

vagrant@vagrant-ubuntu-trusty-64:~/trove$ bandit -r .
[bandit] INFO using config: /usr/local/lib/python2.7/dist-packages/bandit/config/bandit.yaml
[bandit] INFO running on Python 2.7.6
476 [0.. 50.. 100.. 150.. 200.. 250.. 300.. 350.. 400.. 450.. ]
Run started:
2015-07-17 14:38:33.388857

Files skipped (0):

Test results:
No issues identified.

Expected output:

Lots of issues

Bandit has multiple bugs when running against a file with a -

Running Bandit, erroneously, in the following way produces strange output:

MacBook-Pro:bandit travismcpeak$ bandit examples/multiline-str.py -3
Run started:
2015-03-20 18:23:40.705354

Files in scope (2):
-3 (score: 10)

Files excluded (0):

Files skipped (1):
-3 (No such file or directory)

Test results:

This is wrong because:

  1. two files are listed in scope, but only one is actually listed (the bogus one)
  2. the bogus one is listed with a score of 10

proposed change to test-requirements breaks py34

Patch https://review.openstack.org/#/c/278720 attempts to change test-requirements import of mock to be conditional for only 3.2 and lower. But the mock namespace in py34 is "unittest.mock" not just "mock" So this patch breaks on failing imports:

2016-02-10 23:35:34.138 | Failed to import test module: tests.unit.formatters.test_text
2016-02-10 23:35:34.138 | Traceback (most recent call last):
2016-02-10 23:35:34.138 | File "/home/jenkins/workspace/gate-bandit-python34/.tox/py34/lib/python3.4/site-packages/unittest2/loader.py", line 456, in _find_test_path
2016-02-10 23:35:34.138 | module = self._get_module_from_name(name)
2016-02-10 23:35:34.138 | File "/home/jenkins/workspace/gate-bandit-python34/.tox/py34/lib/python3.4/site-packages/unittest2/loader.py", line 395, in _get_module_from_name
2016-02-10 23:35:34.138 | import(name)
2016-02-10 23:35:34.139 | File "/home/jenkins/workspace/gate-bandit-python34/tests/unit/formatters/test_text.py", line 20, in
2016-02-10 23:35:34.139 | import mock
2016-02-10 23:35:34.139 | ImportError: No module named 'mock'

Bandit should gracefully handle file errors

Bandit dumps tracebacks when it fails to access files. It would be preferrable if Bandit gracefully handled the exceptions and displayed a user appropriate error. Also, it should be checking for the existence of the output file prior to running the scan.

promd-1s-dhcp317:bandit browne$ bandit -r ../openstack/ -o /Library/
86 [0.. 50.. ]
Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/Library/Python/2.7/site-packages/bandit/bandit.py", line 88, in main
args.output_format)
File "/Library/Python/2.7/site-packages/bandit/core/manager.py", line 112, in output_results
output_format=output_format
File "/Library/Python/2.7/site-packages/bandit/core/result_store.py", line 393, in report
with open(output_filename, 'w') as fout:
IOError: [Errno 21] Is a directory: '/Library/'

promd-1s-dhcp317:bandit browne$ bandit -r ../openstack/ -o /Library/sfd
86 [0.. 50.. ]
Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/Library/Python/2.7/site-packages/bandit/bandit.py", line 88, in main
args.output_format)
File "/Library/Python/2.7/site-packages/bandit/core/manager.py", line 112, in output_results
output_format=output_format
File "/Library/Python/2.7/site-packages/bandit/core/result_store.py", line 393, in report
with open(output_filename, 'w') as fout:
IOError: [Errno 13] Permission denied: '/Library/sfd'

Uncaught exception when running against standalone file

When running Bandit on setup.py (from its own directory) there is an uncaught exception:

(band)MacBook-Pro:bandit travismcpeak$ bandit -n 5 setup.py
Traceback (most recent call last):
File "/Users/travismcpeak/Documents/projects/bandit/band/bin/bandit", line 10, in
sys.exit(main())
File "/Users/travismcpeak/Documents/projects/bandit/band/lib/python2.7/site-packages/bandit/bandit.py", line 74, in main
b_mgr.run_scope(args.files)
File "/Users/travismcpeak/Documents/projects/bandit/band/lib/python2.7/site-packages/bandit/core/manager.py", line 134, in run_scope
self.b_rs, self.b_ts
File "/Users/travismcpeak/Documents/projects/bandit/band/lib/python2.7/site-packages/bandit/core/manager.py", line 170, in _execute_ast_visitor
fname, self.logger, self.b_conf, b_ma, b_rs, b_ts, self.debug
File "/Users/travismcpeak/Documents/projects/bandit/band/lib/python2.7/site-packages/bandit/core/node_visitor.py", line 60, in init
self.namespace = b_utils.get_module_qualname_from_path(fname)
File "/Users/travismcpeak/Documents/projects/bandit/band/lib/python2.7/site-packages/bandit/core/utils.py", line 134, in get_module_qualname_from_path
' Missing path or file name' % (path))
bandit.core.utils.InvalidModulePath: Invalid python file path: "setup.py" Missing path or file name

We should catch the exception and generate some sort of meaningful warning/log output based on it.

hardcoded_sql_expressions dumping traceback errors

The latest bandit (from source) is showing traceback errors from the hardcoded_sql_expressions plugin.

To recreate:
git clone https://github.com/openstack/bandit.git
git clone https://github.com/openstack/nova.git
cd bandit
tox -e py27
.tox/py27/bin/bandit -r ../nova/nova -n 5

jenkins@wdc-ecostack-dhcp-4-255:~/bandit$ .tox/py27/bin/bandit -r ../nova/nova -n 5
[bandit] INFO using config: /home/jenkins/bandit/bandit/config/bandit.yaml
[bandit] INFO running on Python 2.7.6
1418 [0.. /home/jenkins/bandit/bandit/plugins/general_hardcoded_password.py:41: UserWarning: Using relative path for word_list: ./wordlist/default-passwords
% word_list_path)
50.. 100.. 150.. 200.. 250.. 300.. 350.. [tester] ERROR Bandit internal error running: hardcoded_sql_expressions on file ../nova/nova/db/sqlalchemy/api.py at line 2170: 'Call' object has no attribute 'id'Traceback (most recent call last):
File "/home/jenkins/bandit/bandit/core/tester.py", line 65, in run_tests
result = test(context)
File "/home/jenkins/bandit/bandit/plugins/injection_sql.py", line 46, in hardcoded_sql_expressions
val = _evaluate_ast(context.node)
File "/home/jenkins/bandit/bandit/plugins/injection_sql.py", line 39, in _evaluate_ast
name = utils.get_called_name(out[0].parent)
File "/home/jenkins/bandit/bandit/core/utils.py", line 343, in get_called_name
return (func.attr if isinstance(func, ast.Attribute) else func.id)
AttributeError: 'Call' object has no attribute 'id'

[tester] ERROR Bandit internal error running: hardcoded_sql_expressions on file ../nova/nova/db/sqlalchemy/api.py at line 2170: 'Call' object has no attribute 'id'Traceback (most recent call last):
File "/home/jenkins/bandit/bandit/core/tester.py", line 65, in run_tests
result = test(context)
File "/home/jenkins/bandit/bandit/plugins/injection_sql.py", line 46, in hardcoded_sql_expressions
val = _evaluate_ast(context.node)
File "/home/jenkins/bandit/bandit/plugins/injection_sql.py", line 39, in _evaluate_ast
name = utils.get_called_name(out[0].parent)
File "/home/jenkins/bandit/bandit/core/utils.py", line 343, in get_called_name
return (func.attr if isinstance(func, ast.Attribute) else func.id)
AttributeError: 'Call' object has no attribute 'id'

Generating line number ranges takes ~40% of the runtime

Currently, linerange_fix takes ~40% of bandit runtime, because it walks the ast down on almost every node. There are places where a few percent could be stripped, but the whole linerange / linerange_fix should be redesigned in the future.

Bandit Baseline with severity filtering is broken

If the baseline feature is used along with severity filtering the results end up broken.

Basically, the current baseline routine is to check if there are different results in the currently checked file than what is present in the baseline. If so, all the issues from the current file are inputted and then filtered. To make this clear let's say we have original file a.py:

import subprocess
do_something_benign()
os.system('/tmp/something_bad')

We'll get a low severity finding for subprocess usage, but if we examine this file with a -ll filter, this will be suppressed from the baseline output. We also get a higher severity error which for /tmp.

Now we run a baseline comparison against it, the first action that is performed is checking the results against the previous level. Since the previous level had the LOW severity finding filtered out, it only has the MEDIUM. Since no filtering has been done yet, the current version of the file includes the low severity issue. Basically the baseline has the low severity issue filtered out and the current version doesn't. So they don't match and all of the issues from the file get added to the results.

At this point filtering is done so the LOW severity issue is removed, but the point is even though nothing changed in this file Bandit thinks it did.

The correct behavior is to filter severity first.

proposed change to test-requirements breaks py34

Patch https://review.openstack.org/#/c/278720 attempts to change test-requirements import of mock to be conditional for only 3.2 and lower. But the mock namespace in py34 is "unittest.mock" not just "mock" So this patch breaks on failing imports:

2016-02-10 23:35:34.138 | Failed to import test module: tests.unit.formatters.test_text
2016-02-10 23:35:34.138 | Traceback (most recent call last):
2016-02-10 23:35:34.138 | File "/home/jenkins/workspace/gate-bandit-python34/.tox/py34/lib/python3.4/site-packages/unittest2/loader.py", line 456, in _find_test_path
2016-02-10 23:35:34.138 | module = self._get_module_from_name(name)
2016-02-10 23:35:34.138 | File "/home/jenkins/workspace/gate-bandit-python34/.tox/py34/lib/python3.4/site-packages/unittest2/loader.py", line 395, in _get_module_from_name
2016-02-10 23:35:34.138 | import(name)
2016-02-10 23:35:34.139 | File "/home/jenkins/workspace/gate-bandit-python34/tests/unit/formatters/test_text.py", line 20, in
2016-02-10 23:35:34.139 | import mock
2016-02-10 23:35:34.139 | ImportError: No module named 'mock'

JSON report ignores #nosec and severity

Bandit's JSON report doesn't exclude lines marked #nosec. The JSON report also doesn't respect the -l CLI flag, which only shows higher-severity issues in the text report. The command bandit -f json -lll examples/skip.py demonstrates both issues.

As an aside, perhaps #nosec lines shouldn't be scored at all. Right now it's up to the individual reports to filter out these lines. That's the reason tests/test_functional:FunctionalTests.test_skip is skipped right now: #nosec lines receive a score.

Running bandit after default installation lists no plugins

When installed with no other changes, bandit will not detect any plugins. Tests end successful, even though no checks are really run.
It's not obvious unless bandit is run with --help which does provide an empty list of loaded plugins: "The following plugin suites were discovered and loaded: []"

Main issue seems to be that plugins not listed as entry points will not be detected by stevedore.

Current command injection behavior isn't correct

Consider the following test file:

import subprocess
my_val = 'do_something; ' + evil_value
subprocess.Popen(my_val, shell=True)

This is obviously a high risk command injection issue, but Bandit currently only reports a low. Since all we can tell is that it's a dynamically constructed string we have to assume HIGH severity IMO.

/tmp plugin struggles with multi-line strings

The hard-coded /tmp plugin doesn't handle multi-line strings very well. Maybe some code could be borrowed from the SQL injection plugin.

In this example, only lines 1 and 3 are in the report. Line 2, with "/tmp" itself, is missing:
x = """
/tmp
"""

In this example, only line 4 (the closing """) is emitted in the report:
def f():
"""
/tmp
"""

JSON report per file score shows total score instead

Score section in JSON output (incorrectly) shows total score instead of per file score:

"stats": [
{
"filename": "./test_file2.py",
"issue totals": {
"HIGH": 0,
"LOW": 3,
"MEDIUM": 0,
"UNDEFINED": 0
},
"score": 59
},
{
"filename": "./test_file1.py",
"issue totals": {
"HIGH": 0,
"LOW": 0,
"MEDIUM": 2,
"UNDEFINED": 0
},
"score": 59
}

The above is from the score section at the end of a JSON report. Note that the score is '59' for both, even though the two files should obviously have different scores.

gate-bandit-integration-* not failing when they should

Bandit has an integration tox job which checks against other projects whether a bandit patch potentially breaks them. I noticed its not working as of late.

When errors occur, they are ignored. Either the exit code is not preserved or something else is happening. The job always shows success.

For example (gate-bandit-integration-keystone):

2016-02-17 19:15:01.574 | + pushd ../keystone
2016-02-17 19:15:01.574 | /home/jenkins/workspace/gate-bandit-integration-keystone/openstack/keystone /home/jenkins/workspace/gate-bandit-integration-keystone/openstack/bandit
2016-02-17 19:15:01.574 | + set +e
2016-02-17 19:15:01.574 | + tox -e bandit --notest
2016-02-17 19:15:01.663 | ERROR: unknown environment 'bandit'
2016-02-17 19:15:01.670 | + .tox/bandit/bin/pip install --force-reinstall -U /home/jenkins/workspace/gate-bandit-integration-keystone/openstack/bandit
2016-02-17 19:15:01.671 | scripts/integration-test.sh: line 48: .tox/bandit/bin/pip: No such file or directory
2016-02-17 19:15:01.671 | + tox -e bandit
2016-02-17 19:15:01.795 | ERROR: unknown environment 'bandit'
2016-02-17 19:15:01.802 | + popd
2016-02-17 19:15:01.802 | /home/jenkins/workspace/gate-bandit-integration-keystone/openstack/bandit
2016-02-17 19:15:01.802 | + [[ 0 -eq 1 ]]
2016-02-17 19:15:01.803 | ___________________________________ summary ____________________________________
2016-02-17 19:15:01.803 | integration: commands succeeded
2016-02-17 19:15:01.803 | congratulations :)

gate-bandit-integration-oslo.vmware:

2016-02-17 19:15:20.354 | �[93m>> Issue: [B309:blacklist] Use of HTTPSConnection does not provide security, see https://wiki.openstack.org/wiki/OSSN/OSSN-0033
2016-02-17 19:15:20.354 | Severity: Medium Confidence: High
2016-02-17 19:15:20.354 | Location: oslo_vmware/objects/datastore.py:313�[0m
2016-02-17 19:15:20.354 | 311 conn = httplib.HTTPConnection(self._server)
2016-02-17 19:15:20.354 | 312 elif self._scheme == 'https':
2016-02-17 19:15:20.354 | 313 conn = httplib.HTTPSConnection(self._server)
2016-02-17 19:15:20.354 | 314 else:
2016-02-17 19:15:20.354 | 315 excep_msg = _("Invalid scheme: %s.") % self._scheme
2016-02-17 19:15:20.354 |
2016-02-17 19:15:20.355 | --------------------------------------------------
2016-02-17 19:15:20.355 | �[94m>> Issue: [B112:os_path_join_traversal] Check variables used with os.path.join are trusted or sanitised.
2016-02-17 19:15:20.355 | Severity: Low Confidence: Low
2016-02-17 19:15:20.355 | Location: oslo_vmware/pbm.py:196�[0m
2016-02-17 19:15:20.355 | 194 major_minor = '%s.%s' % (major_minor, ver[1])
2016-02-17 19:15:20.355 | 195 curr_dir = os.path.abspath(os.path.dirname(file))
2016-02-17 19:15:20.355 | 196 pbm_service_wsdl = os.path.join(curr_dir, 'wsdl', major_minor,
2016-02-17 19:15:20.355 | 197 'pbmService.wsdl')
2016-02-17 19:15:20.355 | 198 if not os.path.exists(pbm_service_wsdl):
2016-02-17 19:15:20.355 | 199 LOG.warning(_LW("PBM WSDL file %s not found."), pbm_service_wsdl)
2016-02-17 19:15:20.356 |
2016-02-17 19:15:20.356 | --------------------------------------------------
2016-02-17 19:15:20.374 | ERROR: InvocationError: '/home/jenkins/workspace/gate-bandit-integration-oslo.vmware/openstack/oslo.vmware/.tox/bandit/bin/bandit -r oslo_vmware -n 5'
2016-02-17 19:15:20.374 | ___________________________________ summary ____________________________________
2016-02-17 19:15:20.374 | ERROR: bandit: commands failed
2016-02-17 19:15:20.382 | + popd
2016-02-17 19:15:20.382 | /home/jenkins/workspace/gate-bandit-integration-oslo.vmware/openstack/bandit
2016-02-17 19:15:20.382 | + [[ 0 -eq 1 ]]
2016-02-17 19:15:20.382 | ___________________________________ summary ____________________________________
2016-02-17 19:15:20.382 | integration: commands succeeded
2016-02-17 19:15:20.382 | congratulations :)

Bandit throws a traceback with bad input

When running Bandit with a typo I got a traceback:

MacBook-Pro:~ travismcpeak$ bandit 0
[bandit] INFO using config: /usr/local/etc/bandit/bandit.yaml
[bandit] INFO running on Python 2.7.10
Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/usr/local/lib/python2.7/site-packages/bandit/bandit.py", line 267, in main
args.output_format)
File "/usr/local/lib/python2.7/site-packages/bandit/core/manager.py", line 174, in output_results
lines=lines, out_format=output_format)
File "/usr/local/lib/python2.7/site-packages/bandit/formatters/text.py", line 84, in report
label, manager.metrics.data['_totals'][metric]
KeyError: 'loc'

Whatever is going on here we should be more graceful about it.

Bandit has multiple bugs when running against a file with a -

Running Bandit, erroneously, in the following way produces strange output:

MacBook-Pro:bandit travismcpeak$ bandit examples/multiline-str.py -3
Run started:
2015-03-20 18:23:40.705354

Files in scope (2):
-3 (score: 10)

Files excluded (0):

Files skipped (1):
-3 (No such file or directory)

Test results:

This is wrong because:

  1. two files are listed in scope, but only one is actually listed (the bogus one)
  2. the bogus one is listed with a score of 10

Inability to find bandit.yaml when running in virtualenv

When running bandit without the '-c' parameter, it has the inability to find bandit.yaml within a virtualenv.

[bandit] ERROR no config found - tried: ./bandit.yaml, /home/ericwb/.config/bandit/bandit.yaml, /etc/bandit/bandit.yaml, /usr/local/etc/bandit/bandit.yaml

Bandit errors out when summing issues

A bug was introduced in a refactor that causes bandit to fail summing results after processing.

Issue: subprocess call - check for execution of untrusted input.
Severity: Low Confidence: High
Location: /Users/travismcpeak/Documents/projects/OpenStack_projects/keystone/tools/install_venv_common.py:64
63
64 proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout)
65 output = proc.communicate()[0]

Traceback (most recent call last):
File "/usr/local/bin/bandit", line 10, in
sys.exit(main())
File "/usr/local/lib/python2.7/site-packages/bandit/bandit.py", line 243, in main
conf_filter=args.confidence - 1) > 0:
File "/usr/local/lib/python2.7/site-packages/bandit/core/manager.py", line 95, in results_count
return sum(i.filter(sev_filter, conf_filter) for i in self.results)
File "/usr/local/lib/python2.7/site-packages/bandit/core/manager.py", line 95, in
return sum(i.filter(sev_filter, conf_filter) for i in self.results)
File "/usr/local/lib/python2.7/site-packages/bandit/core/issue.py", line 50, in filter
return (rank.index(self.severity) >= rank.index(severity) and
ValueError: 0 is not in list

Reporting in JSON format fails on Python3

Bandit on Python3 fails to produce reports in JSON format.

The exception message that bandit displays is like:
TypeError: range(175, 176) is not JSON serializable

There seem to be (Python-2 - Python-3 portability related) bug in
File: bandit/core/utils. py, method: linerange, statement: return range(min(lines), max(lines) + 1))File:bandit/core/utils. py, method: linerange_fix, statement: return range(start, node.sibling.lineno)`

In Python-2, range is a method that returns a list of values. (https://docs.python.org/2/library/functions.html#range)
In Python-3, range is a class (https://docs.python.org/3.4/library/stdtypes.html#range).

Fix: To make it compatible: the range object must be passed to list constructor.

File: bandit/core/utils. py, method: linerange, statement: return list(range(min(lines), max(lines) + 1)))File:bandit/core/utils. py, method: linerange_fix, statement: return list(range(start, node.sibling.lineno))`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.