2020-01-03 15:06:33 +00:00
#!/usr/bin/env python
2019-11-03 14:26:43 +00:00
# -*- coding: utf-8 -*-
#
# Finding potential software vulnerabilities from git commit messages
#
# Software is free software released under the "GNU Affero General Public License v3.0"
#
# This software is part of cve-search.org
#
2020-01-03 16:51:55 +00:00
# Copyright (c) 2019-2020 Alexandre Dulaunoy - a@foo.be
2019-11-03 14:26:43 +00:00
import git
import json
import sys
import argparse
2019-12-17 07:45:28 +00:00
import typing
2019-11-03 14:26:43 +00:00
2020-01-03 15:06:33 +00:00
from git_vuln_finder import (
get_patterns ,
find_vuln ,
2020-01-03 16:51:55 +00:00
summary
2020-01-03 15:06:33 +00:00
)
2019-11-03 14:26:43 +00:00
2020-01-03 15:06:33 +00:00
def main ( ) :
2020-01-03 16:51:55 +00:00
""" Point of entry for the script.
"""
# Parsing arguments
parser = argparse . ArgumentParser ( description = " Finding potential software vulnerabilities from git commit messages. " , epilog = " More info: https://github.com/cve-search/git-vuln-finder " )
parser . add_argument ( " -v " , help = " increase output verbosity " , action = " store_true " )
parser . add_argument ( " -r " , type = str , help = " git repository to analyse " )
parser . add_argument ( " -o " , type = str , help = " Output format: [json] " , default = " json " )
parser . add_argument ( " -s " , type = str , help = " State of the commit found " , default = " under-review " )
parser . add_argument ( " -p " , type = str , help = " Matching pattern to use: [vulnpatterns, cryptopatterns, cpatterns] - the pattern ' all ' is used to match all the patterns at once. " , default = " vulnpatterns " )
parser . add_argument ( " -c " , help = " output only a list of the CVE pattern found in commit messages (disable by default) " , action = " store_true " )
parser . add_argument ( " -t " , help = " Include tags matching a specific commit " , action = " store_true " )
args = parser . parse_args ( )
patterns = get_patterns ( )
vulnpatterns = patterns [ " en " ] [ " medium " ] [ " vuln " ]
cryptopatterns = patterns [ " en " ] [ " medium " ] [ " crypto " ]
cpatterns = patterns [ " en " ] [ " medium " ] [ " c " ]
if args . p == " vulnpatterns " :
defaultpattern = vulnpatterns
elif args . p == " cryptopatterns " :
defaultpattern = cryptopatterns
elif args . p == " cpatterns " :
defaultpattern = cpatterns
elif args . p == " all " :
defaultpattern = [ vulnpatterns , cryptopatterns , cpatterns ]
else :
parser . print_usage ( )
parser . exit ( )
if not args . r :
parser . print_usage ( )
parser . exit ( )
else :
repo = git . Repo ( args . r )
# Initialization of the variables for the results
found = 0
all_potential_vulnerabilities = { }
cve_found = set ( )
repo_heads = repo . heads
repo_heads_names = [ h . name for h in repo_heads ]
print ( repo_heads_names , file = sys . stderr )
origin = repo . remotes . origin . url
if args . t :
tagmap = { }
for t in repo . tags :
tagmap . setdefault ( repo . commit ( t ) . hexsha , [ ] ) . append ( str ( t ) )
for branch in repo_heads_names :
commits = list ( repo . iter_commits ( branch ) )
defaultpattern
for commit in commits :
if isinstance ( defaultpattern , typing . Pattern ) :
ret = find_vuln ( commit , pattern = defaultpattern , versbose = args . v )
2019-12-17 07:45:28 +00:00
if ret :
rcommit = ret [ ' commit ' ]
2020-01-03 15:06:33 +00:00
_ , potential_vulnerabilities = summary ( rcommit ,
branch ,
2020-01-03 16:51:55 +00:00
defaultpattern ,
2020-01-03 15:06:33 +00:00
origin = origin ,
vuln_match = ret [ ' match ' ] ,
tags_matching = args . t ,
commit_state = args . s )
all_potential_vulnerabilities . update ( potential_vulnerabilities )
2019-12-17 07:45:28 +00:00
found + = 1
2020-01-03 16:51:55 +00:00
elif isinstance ( defaultpattern , list ) :
for p in defaultpattern :
ret = find_vuln ( commit , pattern = p , versbose = args . v )
if ret :
rcommit = ret [ ' commit ' ]
_ , potential_vulnerabilities = summary ( rcommit ,
branch ,
p ,
origin = origin ,
vuln_match = ret [ ' match ' ] ,
tags_matching = args . t ,
commit_state = args . s )
all_potential_vulnerabilities . update ( potential_vulnerabilities )
found + = 1
if not args . c :
print ( json . dumps ( all_potential_vulnerabilities ) )
elif args . c :
print ( json . dumps ( list ( cve_found ) ) )
print ( " {} CVE referenced found in commit(s) " . format ( len ( list ( cve_found ) ) ) , file = sys . stderr )
print ( " Total potential vulnerability found in {} commit(s) " . format ( found ) , file = sys . stderr )