Skip to content

Commit

Permalink
pep8 compliant
Browse files Browse the repository at this point in the history
  • Loading branch information
kootenpv committed Aug 23, 2015
1 parent f279b2e commit f44d372
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 85 deletions.
175 changes: 91 additions & 84 deletions gittyleaks/gittyleaks.py
Expand Up @@ -7,10 +7,12 @@
import os
import argparse


class GittyLeak():
def __init__(self, kwargs = None):
self.keywords = ['api', 'key', 'username', 'user', 'uname', 'pw', 'password',
'pass', 'email', 'mail', 'credentials', 'credential', 'login',

def __init__(self, kwargs=None):
self.keywords = ['api', 'key', 'username', 'user', 'uname', 'pw', 'password',
'pass', 'email', 'mail', 'credentials', 'credential', 'login',
'token', 'secret']

self.revision_file_regex = '([a-z0-9]{40}):([^:]+):'
Expand All @@ -19,82 +21,84 @@ def __init__(self, kwargs = None):
self.assignment_pattern = assignment.format('|'.join(self.keywords))

self.excluded_value_chars = [
'.', '[', 'none', 'true', 'false', 'null',
'.', '[', 'none', 'true', 'false', 'null',
'default', 'example', 'username', 'email', 'password'
]

self.min_value_length = 4
self.min_value_length = 4

self.excluding = None
self.revision_list = []
self.user = None
self.repo = None
self.link = None
self.find_anything = None
self.case_sensitive = False
self.find_anything = None
self.case_sensitive = False
self.show_revision_names = False
self.no_banner = False
self.delete = None
self.matched_items = []
self.verbose = None
self.verbose = None
self.no_fancy_color = None

if kwargs is not None:
if kwargs is not None:
self.apply_init_args(kwargs)

def apply_init_args(self, kwargs):
for k,v in kwargs.items():
for k, v in kwargs.items():
setattr(self, k, v)

if self.find_anything:
if self.find_anything:
self.excluded_value_chars = []

if self.excluding is not None:
self.excluded_value_chars.extend(self.excluding)
self.excluded_value_chars.extend(self.excluding)

if not self.case_sensitive:
self.excluded_value_chars = [x.lower() for x in self.excluded_value_chars]
if not self.case_sensitive:
self.excluded_value_chars = [x.lower() for x in self.excluded_value_chars]

def clone(self):
def clone(self):
if self.link is not None:
try:
pre = get_immediate_subdirectories()
git('clone', self.link)
git('clone', self.link)
post = get_immediate_subdirectories()
self.repo = (post - pre).pop()
except sh.ErrorReturnCode_128:
pass
pass

elif self.user is not None:
elif self.user is not None:
try:
git('clone', 'https://github.com/{}/{}.git'.format(self.user, self.repo))

except sh.ErrorReturnCode_128:
pass

os.chdir(self.repo)
os.chdir(self.repo)

def get_revision_list(self):
self.revision_list = git('rev-list', '--all').strip().split('\n')
self.revision_list = git('rev-list', '--all').strip().split('\n')

def get_git_matches(self, revision):
try:
return str(git('grep', '-i', '-e', '"({})"'.format(r'\|'.join(self.keywords)),
revision, _tty_out=False))
# return subprocess.check_output('git grep -i -e "(api\\|key\\|username\\|user\\|pw\\|password\\|pass\\|email\\|mail)" -- `git ls-files | grep -v .html` | cat', shell=True).decode('utf8')
try:
return str(git('grep', '-i', '-e', '"({})"'.format(r'\|'.join(self.keywords)),
revision, _tty_out=False))
# return subprocess.check_output('git grep -i -e
# "(api\\|key\\|username\\|user\\|pw\\|password\\|pass\\|email\\|mail)" --
# `git ls-files | grep -v .html` | cat', shell=True).decode('utf8')
except sh.ErrorReturnCode_1:
return ''
except:
return ''
except:
print('encoding error at revision: ', revision)
return ''

def get_word_matches(self):
# git grep simple word matches (python processing follows)
word_matches = set()
for revision in self.revision_list:
for m in self.get_git_matches(revision).split('\n'):
word_matches = set()
for revision in self.revision_list:
for m in self.get_git_matches(revision).split('\n'):
word_matches.add(m)
return word_matches
return word_matches

def validated_value(self, v):
if v.strip():
Expand All @@ -106,70 +110,70 @@ def validated_value(self, v):
if not any([x in v for x in self.excluded_value_chars]):
return True
else:
return True
return False
return True
return False

def get_matches_dict(self):
matches = {}
for match in self.get_word_matches():
for match in self.get_word_matches():
if self.case_sensitive:
m = re.search(self.assignment_pattern, match)
else:
else:
m = re.search(self.assignment_pattern, match, re.IGNORECASE)
if m:
rev, fname = (re.search(self.revision_file_regex, match).groups())

if m:
rev, fname = (re.search(self.revision_file_regex, match).groups())
key, _, value = m.groups()[1:]
if self.validated_value(value):
appearance = ':'.join(match.split(':')[2:]).strip()
identifier = (fname, key, value)
if identifier not in matches:
matches[identifier] = []
matches[identifier] = []
matches[identifier].append((appearance, rev))

return matches

def printer(self):
def printer(self):
if not self.no_banner:
print("""
--------------------------------------------------------------------
gittyleaks' Bot Detective at work ...
--------------------------------------------------------------------
""")
if not self.matched_items:
if not self.matched_items:
print('No matches.')
if self.verbose:
self.print_verbose_matches()
else:
self.print_matches()
else:
self.print_matches()

def print_matches(self):
if self.matched_items:
print('----------------------------------------')

for k,v in self.matched_items.items():
for k, v in self.matched_items.items():
for appear in set([x[0] for x in v]):
# 32 is green, 31 is red
if not self.no_fancy_color:
fname = colorize(k[0], '36')
appear = appear.replace(k[1], colorize(k[1], '33'))
appear = appear.replace(k[2], colorize(k[2], '31'))
fname = colorize(k[0], '36')
appear = appear.replace(k[1], colorize(k[1], '33'))
appear = appear.replace(k[2], colorize(k[2], '31'))
else:
fname = k[0]
fname = k[0]

print('{}: {}'.format(fname, appear))
def print_verbose_matches(self):
for k,v in self.matched_items.items():

def print_verbose_matches(self):
for k, v in self.matched_items.items():
print('file: {}\nwhat: {}\nvalue: {}\nmatch:'.format(*k))
for appear in set([x[0] for x in v]):
print(' {}'.format(appear))
if self.show_revision_names:
print('-----Revisions--------------------------')
for x in v:
if self.show_revision_names:
print('-----Revisions--------------------------')
for x in v:
print(x[1])
else:
print('num_of_revisions: {}'.format(len(set([x[1] for x in v]))))
print('num_of_revisions: {}'.format(len(set([x[1] for x in v]))))
print('----------------------------------------')

def run(self):
Expand All @@ -179,48 +183,51 @@ def run(self):
self.get_revision_list()

self.matched_items = self.get_matches_dict()

if self.delete and (self.user and self.repo) or self.link:
rm('-rf', '../' + self.repo)


def get_immediate_subdirectories():
return set([fname for fname in os.listdir('.') if os.path.isdir(fname)])

def colorize(val, code):

def colorize(val, code):
return '\x1b[{}m{}\x1b[0m'.format(code, val)



def get_args_parser():
p = argparse.ArgumentParser(
description='Discover where your sensitive data has been leaked.')
p.add_argument('-user', '-u',
help='Provide a github username, only if also -repo')
p.add_argument('-repo', '-r',
help='Provide a github repo, only if also -user')
p.add_argument('-link', '-l',
help='Provide a link to clone')
p.add_argument('-delete', '-d', action='store_true',
help = 'If cloned, remove the repo afterwards.')
p.add_argument('--find-anything', '-a', action='store_true',
description='Discover where your sensitive data has been leaked.')
p.add_argument('-user', '-u',
help='Provide a github username, only if also -repo')
p.add_argument('-repo', '-r',
help='Provide a github repo, only if also -user')
p.add_argument('-link', '-l',
help='Provide a link to clone')
p.add_argument('-delete', '-d', action='store_true',
help='If cloned, remove the repo afterwards.')
p.add_argument('--find-anything', '-a', action='store_true',
help='flag: If you want to find anything remotely suspicious.')
p.add_argument('--case-sensitive', '-c', action='store_true',
p.add_argument('--case-sensitive', '-c', action='store_true',
help='flag: If you want to be specific about case matching.')
p.add_argument('--excluding', '-e', nargs = '+',
p.add_argument('--excluding', '-e', nargs='+',
help='List of words that are ignored occurring as value.')
p.add_argument('--verbose', '-v', action='store_true',
help = 'If flag given, print verbose matches.')
p.add_argument('--no-banner', '-b', action='store_true',
p.add_argument('--verbose', '-v', action='store_true',
help='If flag given, print verbose matches.')
p.add_argument('--no-banner', '-b', action='store_true',
help='Omit the banner at the start of a print statement')
p.add_argument('--no-fancy-color', '-f', action='store_true',
p.add_argument('--no-fancy-color', '-f', action='store_true',
help='Omit the banner at the start of a print statement')
return p



def main():
""" This is the function that is run from commandline with `gittyleaks` """
args = get_args_parser().parse_args()
gl = GittyLeak(args.__dict__)
""" This is the function that is run from commandline with `gittyleaks` """
args = get_args_parser().parse_args()
gl = GittyLeak(args.__dict__)
try:
gl.run()
gl.run()
except KeyboardInterrupt:
print('gittyleaks user interupted')
print('gittyleaks user interupted')
gl.printer()
27 changes: 26 additions & 1 deletion setup.py
Expand Up @@ -19,4 +19,29 @@
entry_points = {
'console_scripts': ['gittyleaks = gittyleaks.gittyleaks:main']
},
zip_safe = False)
classifiers = [
'Environment :: Console',
'Intended Audience :: Developers',
'Intended Audience :: Customer Service',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
'Operating System :: Microsoft',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Unix',
'Operating System :: POSIX',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Topic :: Software Development',
'Topic :: Software Development :: Build Tools',
'Topic :: Software Development :: Debuggers',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: System :: Software Distribution',
'Topic :: System :: Systems Administration',
'Topic :: Utilities'
],
zip_safe = False,
platforms='any')

0 comments on commit f44d372

Please sign in to comment.