├── .gitignore ├── LICENSE.md ├── README.md ├── filesystem.go ├── git.go ├── main.go └── patterns ├── Azure.json ├── C#.json ├── Credentials.json ├── Database.json ├── Misc.json ├── blueflower.json ├── gitrob.json └── new.json /.gitignore: -------------------------------------------------------------------------------- 1 | .build/ 2 | test/build 3 | .idea/ 4 | PwnDelorean 5 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Paul Ganea 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PwnDelorean 2 | 3 | PwnDelorean is a credential seeker. It allows users to search local and remote git repositories history for 4 | any developer secrets that were left over and in addition searches filesystems for the same secrets. 5 | 6 | ### Prerequisities 7 | Requires Go runtime, currently using go version 1.8.3 8 | 9 | ## Getting Started 10 | 11 | ```bash 12 | brew install libgit2 13 | go get 14 | go build . 15 | ./PwnDelorean -url https://github.com/k4ch0w/PwnDelorean.git 16 | ``` 17 | 18 | ### Scan filesystem 19 | ```bash 20 | ./PwnDelorean -directory ~/Workspace 21 | ``` 22 | 23 | ### Scan Organization 24 | ```bash 25 | ./PwnDelorean -organization GitHub 26 | ``` 27 | 28 | ### Scan repo with Creds 29 | #### Plaintext 30 | ```bash 31 | export GIT_USER=k4ch0w 32 | export GIT_PASS=********* 33 | ./PwnDelorean -url https://github.com/k4ch0w/PwnDeloreanRepo.git -creds=plaintext 34 | ``` 35 | #### SSH 36 | ```bash 37 | export GIT_USER=k4ch0w 38 | export GIT_PRIV_KEY=~/.ssh/id_rsa 39 | export GIT_PUB_KEY=~/.ssh/id_rsa.pub 40 | #If needed 41 | export GIT_PASSPHRASE=****** 42 | ./PwnDelorean -url https://github.com/k4ch0w/PwnDeloreanRepo.git -creds=ssh 43 | ``` 44 | ### Additional Flags 45 | * csv - The filename to output results in CSV format to I.E ~/results.csv 46 | * fileNamesOnly - Only look for interesting filenames instead of parsing each file 47 | * ignoreForkedRepos - When scanning an organization ignore repos they forked 48 | * ignoreHighFalsePositives - Ignore searching for patterns that generally cause false positives, be careful with this flag it will miss things like AWS keys and Azure keys 49 | 50 | 51 | ## Authors 52 | 53 | * **Paul Ganea** - *Initial work* 54 | 55 | 56 | ## License 57 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details 58 | 59 | -------------------------------------------------------------------------------- /filesystem.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | "os" 7 | "strings" 8 | "io/ioutil" 9 | "bytes" 10 | "github.com/fatih/color" 11 | "strconv" 12 | "github.com/pkg/errors" 13 | ) 14 | 15 | type FileStruct struct { 16 | Filename string 17 | Path string 18 | } 19 | 20 | const MAX_FILE_SIZE_TO_SCAN = 200000 21 | var ignoreExts = []string{".dll", ".nupkg", ".mp4", ".mkv", ".avi", ".flv", ".wmv", ".mov", ".pdf" } 22 | 23 | func appendFilesystemMatch(pattern Pattern, filestruct FileStruct, lineMatched string, 24 | lineNum int, table map[string]*Match) { 25 | name := filestruct.Filename 26 | _, exists := table[name] 27 | if !exists { 28 | table[name] = &Match{filestruct.Filename, filestruct.Path, 29 | nil, pattern.Description, 30 | pattern.Value, lineMatched, lineNum} 31 | fmt.Println(color.BlueString("Found match %s %s: ", pattern.Description, pattern.Value)) 32 | if lineNum == NO_LINE_NUMBER_APPLICABLE{ 33 | color.Green("%s", filestruct.Path) 34 | } else{ 35 | color.Green("%s:%d ", filestruct.Path, lineNum) 36 | } 37 | } 38 | } 39 | func getAllFilesInDirectory(dir string) ([]FileStruct, error) { 40 | fileList := []FileStruct{} 41 | err := filepath.Walk(dir, func(path string, f os.FileInfo, err error) error { 42 | fileList = append(fileList, FileStruct{f.Name(), path}) 43 | return nil 44 | }) 45 | if err != nil { 46 | return nil, err 47 | } 48 | return fileList, nil 49 | } 50 | 51 | func searchThroughFile(path string) (bool, Pattern, string, int, error) { 52 | fi, err := os.Stat(path) 53 | if err != nil { 54 | return false, Pattern{}, "", -1, err 55 | } 56 | ext := filepath.Ext(path) 57 | for _, ignore := range ignoreExts { 58 | if ext == ignore { 59 | return false, Pattern{}, IS_FILENAME_MATCH, 60 | NO_LINE_NUMBER_APPLICABLE, errors.New("Ignoring file extension " + path) 61 | } 62 | } 63 | if fi.IsDir() || checkIfInsideIgnoredDirectory(path) { 64 | return false, Pattern{}, IS_FILENAME_MATCH, 65 | NO_LINE_NUMBER_APPLICABLE, err 66 | } 67 | if fi.Size() / 1024 >= MAX_FILE_SIZE_TO_SCAN{ 68 | return false, Pattern{}, IS_FILENAME_MATCH, 69 | NO_LINE_NUMBER_APPLICABLE, errors.New(path + " is over max file size to scan") 70 | } 71 | f, err := ioutil.ReadFile(path) 72 | if err != nil { 73 | return false, Pattern{}, IS_FILENAME_MATCH, 74 | NO_LINE_NUMBER_APPLICABLE, err 75 | } 76 | lines := bytes.Split(f, []byte("\n")) 77 | for _, pattern := range fileContentRegexes { 78 | lineNum := 0 79 | for _, line := range lines { 80 | lineNum++ 81 | if pattern.Regex.Match(line) { 82 | return true, pattern, string(line), lineNum, nil 83 | } 84 | } 85 | } 86 | return false, Pattern{}, IS_FILENAME_MATCH, NO_LINE_NUMBER_APPLICABLE, nil 87 | } 88 | func searchFileContents(files []FileStruct, table map[string]*Match) { 89 | for _, f := range files { 90 | match, p, line, lineNum, err := searchThroughFile(f.Path) 91 | if err == nil && match { 92 | appendFilesystemMatch(p, f, line, lineNum, table) 93 | } 94 | } 95 | } 96 | 97 | func outputCSVFilesystem(matches []*Match) { 98 | records := [][]string{{"Filename", "Description", "Filepath", "LineMatched", "LineNumber"}} 99 | for _, match := range matches { 100 | records = append(records, []string{match.Filename, match.Description, 101 | match.Filepath, truncateString(match.LineMatched, 160), 102 | strconv.Itoa(match.LineNumber)}) 103 | } 104 | outputCSV(*outputCSVFlag, records) 105 | } 106 | 107 | func filesystemSecretFilenameRegexSearch(files []FileStruct, table map[string]*Match) { 108 | for _, filestruct := range files { 109 | for _, pattern := range secretFileNameRegexes { 110 | if pattern.Regex.MatchString(filestruct.Filename) { 111 | appendFilesystemMatch(pattern, filestruct, IS_FILENAME_MATCH, NO_LINE_NUMBER_APPLICABLE, table) 112 | break 113 | } 114 | } 115 | } 116 | } 117 | 118 | func filesystemSecretFilenameLiteralSearch(files []FileStruct, table map[string]*Match) { 119 | for _, pattern := range secretFileNameLiterals { 120 | for _, filename := range files { 121 | if strings.Contains(filename.Filename, pattern.Value) { 122 | appendFilesystemMatch(pattern, filename, IS_FILENAME_MATCH, NO_LINE_NUMBER_APPLICABLE, table) 123 | } 124 | } 125 | } 126 | } 127 | 128 | func startFileSystemScan() { 129 | files, err := getAllFilesInDirectory(*dirToScanFlag) 130 | if err != nil { 131 | color.Red(err.Error()) 132 | os.Exit(-1) 133 | } 134 | var uniqFileSet = make(map[string]*Match) 135 | filesystemSecretFilenameLiteralSearch(files, uniqFileSet) 136 | filesystemSecretFilenameRegexSearch(files, uniqFileSet) 137 | if !*fileNamesOnlyFlag { 138 | searchFileContents(files, uniqFileSet) 139 | } 140 | if len(*outputCSVFlag) != 0 { 141 | var results []*Match 142 | for _, values := range uniqFileSet { 143 | results = append(results, values) 144 | } 145 | outputCSVFilesystem(results) 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /git.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "gopkg.in/libgit2/git2go.v26" 5 | "io/ioutil" 6 | "os" 7 | "errors" 8 | "encoding/json" 9 | "net/http" 10 | "fmt" 11 | "strings" 12 | "bytes" 13 | "github.com/fatih/color" 14 | "strconv" 15 | ) 16 | 17 | type GitFile struct { 18 | Name string 19 | Filepath string 20 | CommitId string 21 | RepoUrl string 22 | } 23 | 24 | const GITHUB_API_VERSION = "application/vnd.github.v3+json" 25 | const INVALID_PLAINTEXT_CREDS = -10 26 | const INVALID_SSH_CREDS= -11 27 | 28 | 29 | func gitHubPerformRequest(urlString string) ([]string, error) { 30 | var urls = []string{} 31 | client := &http.Client{} 32 | req, err := http.NewRequest("GET", urlString, nil) 33 | if err != nil { 34 | return urls, err 35 | } 36 | req.Header.Set("Accept", GITHUB_API_VERSION) 37 | //TODO: Add auth here 38 | //req.SetBasicAuth(Github.Username, Github.AccessToken) 39 | resp, err := client.Do(req) 40 | if err != nil { 41 | return urls, err 42 | } 43 | defer resp.Body.Close() 44 | body, _ := ioutil.ReadAll(resp.Body) 45 | switch resp.StatusCode { 46 | case 200: 47 | var data []interface{} 48 | err := json.Unmarshal(body, &data) 49 | if err != nil { 50 | return urls, err 51 | } 52 | for _, repo := range data{ 53 | url := repo.(map[string]interface{})["html_url"] 54 | urls = append(urls, url.(string)) 55 | } 56 | return urls, nil 57 | case 400: 58 | return urls, errors.New("Bad request sent to Github") 59 | case 422: 60 | return urls, errors.New("Invalid fields sent to Github") 61 | case 403: 62 | return urls, errors.New("Github API Rate Limiting detected") 63 | case 404: 64 | return urls, errors.New("Organization doesn't exist") 65 | default: 66 | return urls, errors.New(string(body)) 67 | } 68 | return urls, nil 69 | } 70 | 71 | func getAllOrganizationsRepoUrls(orgName string) ([]string, error){ 72 | urlString := fmt.Sprintf("https://api.github.com/orgs/%s/repos", 73 | orgName) 74 | if *ignoreForkRepos{ 75 | urlString+="?type=sources" //Read Github API Documentation for details 76 | } 77 | urls, err := gitHubPerformRequest(urlString) 78 | if err!= nil { 79 | return nil, err 80 | } 81 | return urls, err 82 | } 83 | 84 | 85 | func credentialsCallback(url string, username string, allowedTypes git.CredType) (git.ErrorCode, *git.Cred) { 86 | git_user := os.Getenv("GIT_USER") 87 | git_pass := os.Getenv("GIT_PASS") 88 | git_priv := os.Getenv("GIT_PRIV_KEY") 89 | git_pub := os.Getenv("GIT_PUB_KEY") 90 | git_passphrase := os.Getenv("GIT_PASSPHRASE") 91 | switch *useGitCredentials{ 92 | case "ssh": 93 | if len(git_user) == 0 || len(git_pub) ==0 || len(git_priv) == 0{ 94 | return git.ErrorCode(INVALID_SSH_CREDS), nil 95 | } 96 | ret, cred := git.NewCredSshKey(git_user, 97 | git_pub, 98 | git_priv, 99 | git_passphrase) 100 | return git.ErrorCode(ret), &cred 101 | case "plaintext": 102 | if len(git_user) == 0 || len(git_pass) == 0{ 103 | return git.ErrorCode(INVALID_PLAINTEXT_CREDS), nil 104 | } 105 | ret, cred := git.NewCredUserpassPlaintext(git_user, git_pass) 106 | return git.ErrorCode(ret), &cred 107 | default: 108 | return git.ErrorCode(-1), nil 109 | } 110 | } 111 | 112 | func certificateCheckCallback(cert *git.Certificate, valid bool, hostname string) git.ErrorCode { 113 | //TODO: Fix lol 114 | return 0 115 | } 116 | 117 | func searchBlobContents(contents []byte) (bool, Pattern, string, int){ 118 | lines := bytes.Split(contents, []byte("\n")) 119 | for _, pattern := range fileContentRegexes { 120 | lineNumb := 0 121 | for _, line := range lines { 122 | lineNumb++ 123 | if pattern.Regex.Match(line) { 124 | return true, pattern, string(line), lineNumb 125 | } 126 | } 127 | } 128 | return false, Pattern{}, "", -1 129 | /* 130 | This is matching on things it shouldn't 131 | for _, pattern := range fileContentLiterals{ 132 | if bytes.Contains([]byte(pattern.Value), contents){ 133 | fmt.Println(pattern.Value) 134 | fmt.Println(string(contents)) 135 | return true, pattern 136 | } 137 | } 138 | */ 139 | } 140 | 141 | func gitRepoSearch(repoUrl string) ([]*Match, error){ 142 | var results = []*Match{} 143 | files, matches, err := getRepoFilenames(repoUrl) 144 | if err != nil { 145 | return results, err 146 | } 147 | results = append(results, gitSecretFilenameLiteralSearch(files)...) 148 | results = append(results, gitSecretFilenameRegexSearch(files)...) 149 | results = append(results, matches...) 150 | return results, nil 151 | } 152 | 153 | func getOrgRepo(url string, matchChan chan[]*Match){ 154 | matches, err := gitRepoSearch(url) 155 | if err != nil{ 156 | color.Red(err.Error()) 157 | } 158 | matchChan <- matches 159 | } 160 | 161 | func searchAllBranches(repo *git.Repository, walk *git.RevWalk) error{ 162 | itr, err := repo.NewBranchIterator(git.BranchRemote) 163 | defer itr.Free() 164 | if err != nil{ 165 | return err 166 | } 167 | var f = func(b *git.Branch, t git.BranchType) error { 168 | walk.Push(b.Target()) 169 | return nil 170 | } 171 | itr.ForEach(f) 172 | return nil 173 | } 174 | 175 | func getRepoFilenames(repoUrl string) ([]GitFile, []*Match, error){ 176 | var table = make(map[string]*Match) 177 | var filenames []GitFile 178 | var matches []*Match 179 | dir, err := ioutil.TempDir("", "PwnDelorean") 180 | if err != nil { 181 | return filenames, matches, err 182 | } 183 | defer os.RemoveAll(dir) 184 | cloneOptions := &git.CloneOptions{} 185 | if len(*useGitCredentials) !=0 { 186 | cloneOptions.FetchOptions = &git.FetchOptions{ 187 | RemoteCallbacks: git.RemoteCallbacks{ 188 | CredentialsCallback: credentialsCallback, 189 | CertificateCheckCallback: certificateCheckCallback, 190 | }, 191 | } 192 | } 193 | repo, err := git.Clone(repoUrl, dir, cloneOptions) 194 | if err != nil { 195 | if err.(*git.GitError).Code == INVALID_PLAINTEXT_CREDS{ 196 | return filenames, matches, 197 | errors.New("Please check your GIT_USER and GIT_PASS Environment variables") 198 | } else if len(*useGitCredentials) ==0 { 199 | return filenames, matches, errors.New( 200 | "-creds flag not in use, the repo may be private or doesn't exist") 201 | } else { 202 | return filenames, matches, errors.New("Git repo appears to not exist") 203 | } 204 | } 205 | defer repo.Free() 206 | head, err := repo.Head() 207 | if err != nil{ 208 | return filenames, matches, err 209 | } 210 | defer head.Free() 211 | walk, err := repo.Walk() 212 | if err != nil{ 213 | return filenames, matches, err 214 | } 215 | defer walk.Free() 216 | walk.Sorting(git.SortTopological) 217 | walk.Push(head.Target()) 218 | searchAllBranches(repo, walk) 219 | gi := head.Target() 220 | for { 221 | err := walk.Next(gi) 222 | if err != nil { 223 | break 224 | } 225 | commit, err := repo.LookupCommit(gi) 226 | tree, err := commit.Tree() 227 | err = tree.Walk(func(td string, te *git.TreeEntry) int { 228 | if te.Type == git.ObjectBlob && te.Filemode == git.FilemodeBlob{ 229 | gitFile := GitFile{te.Name, 230 | td, commit.Id().String(), repoUrl} 231 | if !*fileNamesOnlyFlag && checkIfInsideIgnoredDirectory(td){ 232 | blob, err := repo.LookupBlob(te.Id) 233 | if err == nil { 234 | match, pattern, line, lineNum := searchBlobContents(blob.Contents()) 235 | if match { 236 | appendGitMatch(pattern, gitFile, line, lineNum, table) 237 | } 238 | } 239 | } 240 | filenames = append(filenames, gitFile) 241 | } 242 | return 0 243 | }) 244 | } 245 | var results []*Match 246 | for _, values := range table { 247 | results = append(results, values) 248 | } 249 | return filenames, results, nil 250 | } 251 | 252 | 253 | func appendGitMatch(pattern Pattern, filename GitFile, 254 | lineMatched string, lineNumb int, table map[string]*Match) { 255 | //You can't assume a file hasn't moved directories in history 256 | // which is why you use the filepath + filename for uniqueness 257 | path := filename.Filepath 258 | if len(path) == 0 { 259 | path = "/" + filename.Name 260 | } else { 261 | path += filename.Name 262 | } 263 | _, exists := table[path] 264 | if exists { 265 | table[path].CommitIds = append(table[path].CommitIds, filename.CommitId) 266 | } else { 267 | table[path] = &Match{filename.Name, path, 268 | []string{filename.CommitId}, pattern.Description, 269 | pattern.Value, lineMatched, lineNumb} 270 | 271 | fmt.Print(color.BlueString("Found match %s %s ", pattern.Description, pattern.Value)) 272 | if lineNumb == NO_LINE_NUMBER_APPLICABLE{ 273 | color.Green("%s %s", path, filename.RepoUrl) 274 | } else{ 275 | color.Green("%s:%d %s", path, lineNumb, filename.RepoUrl) 276 | } 277 | } 278 | } 279 | 280 | func gitSecretFilenameLiteralSearch(files []GitFile) []*Match { 281 | var table = make(map[string]*Match) 282 | for _, pattern := range secretFileNameLiterals { 283 | for _, filename := range files { 284 | if strings.Contains(filename.Name, pattern.Value) { 285 | appendGitMatch(pattern, filename, IS_FILENAME_MATCH, NO_LINE_NUMBER_APPLICABLE, table) 286 | } 287 | } 288 | } 289 | var results []*Match 290 | for _, values := range table { 291 | results = append(results, values) 292 | } 293 | return results 294 | } 295 | 296 | func gitSecretFilenameRegexSearch(files []GitFile) []*Match { 297 | var table = make(map[string]*Match) 298 | for _, filename := range files { 299 | for _, pattern := range secretFileNameRegexes { 300 | if pattern.Regex.MatchString(filename.Name) { 301 | appendGitMatch(pattern, filename, IS_FILENAME_MATCH, NO_LINE_NUMBER_APPLICABLE, table) 302 | break 303 | } 304 | } 305 | } 306 | var results []*Match 307 | for _, values := range table { 308 | results = append(results, values) 309 | } 310 | return results 311 | } 312 | 313 | func outputCSVGitRepo(matches []*Match){ 314 | records := [][]string{{"Filename", "Description", "Filepath", "CommitID", "Value", "Line Number"}} 315 | for _, match := range matches { 316 | records = append(records, []string{match.Filename, match.Description, match.Filepath, 317 | strings.Join(match.CommitIds, "|"), 318 | match.Value, strconv.Itoa(match.LineNumber)}) 319 | } 320 | outputCSV(*outputCSVFlag, records) 321 | } 322 | 323 | func startGitRepoScan(){ 324 | results, err := gitRepoSearch(*repoToScanFlag) 325 | if err != nil{ 326 | color.Red(err.Error()) 327 | } 328 | if len(*outputCSVFlag) != 0 { 329 | outputCSVGitRepo(results) 330 | } 331 | } 332 | 333 | func startGitOrganizationScan(){ 334 | var results = []*Match{} 335 | urls, err := getAllOrganizationsRepoUrls(*organizationFlag) 336 | if err!= nil { 337 | color.Red(err.Error()) 338 | os.Exit(-1) 339 | } 340 | matchChan := make(chan []*Match, len(urls)) 341 | for _, url := range urls{ 342 | go getOrgRepo(url, matchChan) 343 | } 344 | for i:= 0; i < len(urls); i++{ 345 | select { 346 | case matches := <-matchChan: 347 | results = append(results, matches...) 348 | } 349 | } 350 | if len(*outputCSVFlag) != 0 { 351 | outputCSVGitRepo(results) 352 | } 353 | } 354 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "path/filepath" 5 | "os" 6 | "io/ioutil" 7 | "encoding/json" 8 | "flag" 9 | "regexp" 10 | "encoding/csv" 11 | "github.com/fatih/color" 12 | "strings" 13 | ) 14 | 15 | type Pattern struct { 16 | Description string `json:description` 17 | SecretType string `json:type` 18 | Value string `json:value` 19 | HighFalsePositive bool `json:highFalsePositive` 20 | Regex *regexp.Regexp 21 | } 22 | 23 | type Match struct { 24 | Filename string 25 | Filepath string 26 | CommitIds []string 27 | Description string 28 | Value string 29 | LineMatched string 30 | LineNumber int 31 | } 32 | 33 | var dirToScanFlag = flag.String("directory", "", "Filesystem location to scan") 34 | var repoToScanFlag = flag.String("url", "", "Git Repo URL to scan") 35 | var outputCSVFlag = flag.String("csv", "", "Output CSV file with results to filelocation") 36 | var fileNamesOnlyFlag = flag.Bool("fileNamesOnly", false, 37 | "Disable searching through file contents for speed increase") 38 | var organizationFlag = flag.String("organization", "", "Search all of an Organizations repos") 39 | var ignoreForkRepos = flag.Bool("ignoreForkedRepos", false, 40 | "Ignore any Organization repos that are forked") 41 | var ignoreHighFalsePositives = flag.Bool("ignoreHighFalsePositives", false, 42 | "Ignore patterns that cause a lot of false findings") 43 | var useGitCredentials = flag.String("creds", "", 44 | "set to 'ssh' or 'plaintext'\nplaintext set environment variables: GIT_USER/GIT_PASS\n"+ 45 | "ssh set environment variables: GIT_USER/GIT_PRIV_KEY/GIT_PUB_KEY/GIT_PASSPHRASE") 46 | 47 | var secretFileNameLiterals = []Pattern{} 48 | var secretFileNameRegexes = []Pattern{} 49 | var fileContentLiterals = []Pattern{} 50 | var fileContentRegexes = []Pattern{} 51 | 52 | const NO_LINE_NUMBER_APPLICABLE = -1 53 | const IS_FILENAME_MATCH = "" 54 | 55 | var IGNORE_THESE_DIRECTORIES = []string{".git", "node_modules", ".npm"} 56 | 57 | func checkIfInsideIgnoredDirectory(filename string) bool { 58 | for _, dir := range IGNORE_THESE_DIRECTORIES { 59 | if strings.Contains(filename, dir) { 60 | return true 61 | } 62 | } 63 | return false 64 | } 65 | 66 | func initialize() { 67 | err := filepath.Walk("./patterns", initializePatterns) 68 | if err != nil { 69 | color.Red(err.Error()) 70 | } 71 | } 72 | 73 | func initializePatterns(path string, info os.FileInfo, _ error) error { 74 | if !info.IsDir() { 75 | file, e := ioutil.ReadFile(path) 76 | if e != nil { 77 | color.Red("File error: %v\n", e) 78 | os.Exit(1) 79 | } 80 | var data []Pattern 81 | json.Unmarshal(file, &data) 82 | for _, pattern := range data { 83 | if *ignoreHighFalsePositives && pattern.HighFalsePositive { 84 | color.Yellow("Ignoring " + pattern.Value) 85 | continue 86 | } 87 | switch pattern.SecretType { 88 | case "secretFilenameLiteral": 89 | secretFileNameLiterals = append(secretFileNameLiterals, pattern) 90 | case "secretFilenameRegex": 91 | pattern.Regex = regexp.MustCompile(pattern.Value) 92 | secretFileNameRegexes = append(secretFileNameRegexes, pattern) 93 | case "fileContentLiteral": 94 | fileContentLiterals = append(fileContentLiterals, pattern) 95 | case "fileContentRegex": 96 | pattern.Regex = regexp.MustCompile(pattern.Value) 97 | fileContentRegexes = append(fileContentRegexes, pattern) 98 | default: 99 | color.Red("Unable to read %s", pattern.Description) 100 | } 101 | } 102 | } 103 | return nil 104 | } 105 | 106 | func outputCSV(filename string, records [][]string) { 107 | file, err := os.Create(filename) 108 | if err != nil { 109 | color.Red("Unable to open file, possibly due to permissions dump to STDOUT") 110 | w := csv.NewWriter(os.Stdout) 111 | w.WriteAll(records) 112 | if err := w.Error(); err != nil { 113 | color.Red(err.Error()) 114 | } 115 | } 116 | w := csv.NewWriter(file) 117 | w.WriteAll(records) 118 | defer file.Close() 119 | } 120 | 121 | func truncateString(str string, num int) string { 122 | temp := str 123 | if len(str) > num { 124 | if num > 3 { 125 | num -= 3 126 | } 127 | temp = str[0:num] + "..." 128 | } 129 | return temp 130 | } 131 | 132 | func main() { 133 | flag.Parse() 134 | initialize() 135 | if len(*dirToScanFlag) != 0 { 136 | startFileSystemScan() 137 | } else if len(*repoToScanFlag) != 0 { 138 | startGitRepoScan() 139 | } else if len(*organizationFlag) != 0 { 140 | startGitOrganizationScan() 141 | } else { 142 | flag.Usage() 143 | os.Exit(-1) 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /patterns/Azure.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "Azure storage standard key format", 4 | "secretType": "fileContentRegex", 5 | "value": "\\b[A-Za-z0-9/+-]{86}\\b", 6 | "highFalsePositive": false 7 | }, 8 | { 9 | "description": "Azure service bus standard key format", 10 | "secretType": "fileContentRegex", 11 | "value": "\\b[A-Za-z0-9\/+-]{43}\\b", 12 | "highFalsePositive": true 13 | }, 14 | { 15 | "description": "Azure service configuration file", 16 | "secretType": "secretFilenameLiteral", 17 | "value": ".cscfg", 18 | "highFalsePositive": false 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /patterns/C#.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "Decryption Key", 4 | "secretType":"fileContentLiteral", 5 | "value": "CryptDeriveKey", 6 | "highFalsePositive": false 7 | }, 8 | { 9 | "description": "Encryption Key", 10 | "secretType": "fileContentLiteral", 11 | "value": "CryptGenKey", 12 | "highFalsePositive": false 13 | }, 14 | { 15 | "description": "Encryption Key", 16 | "secretType": "fileContentLiteral", 17 | "value": "HMACSHA1", 18 | "highFalsePositive": false 19 | }, 20 | { 21 | "description": "Machine Key", 22 | "secretType": "fileContentLiteral", 23 | "value": "machinekey", 24 | "highFalsePositive": false 25 | }, 26 | { 27 | "description": "Potential MSBuild publish profile", 28 | "secretType":"secretFilenameRegex", 29 | "value": "\\.pubxml(\\.user)?$", 30 | "highFalsePositive": false 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /patterns/Credentials.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "RDP file", 4 | "secretType": "secretFilenameLiteral", 5 | "value": ".rdp", 6 | "highFalsePositive": false 7 | }, 8 | { 9 | "description": "Private client certificate", 10 | "secretType": "secretFilenameLiteral", 11 | "value": ".pfx", 12 | "highFalsePositive": false 13 | }, 14 | { 15 | "description": "Potential cryptographic private key", 16 | "secretType": "secretFilenameLiteral", 17 | "value": ".pem", 18 | "highFalsePositive": true 19 | }, 20 | { 21 | "description": "Potential cryptographic key bundle", 22 | "secretType": "secretFilenameLiteral", 23 | "value": ".pkcs12", 24 | "highFalsePositive": false 25 | }, 26 | { 27 | "description": "Potential cryptographic key bundle", 28 | "secretType": "secretFilenameLiteral", 29 | "value": ".p12", 30 | "highFalsePositive": false 31 | }, 32 | { 33 | "description": "Potential cryptographic key bundle", 34 | "secretType": "secretFilenameLiteral", 35 | "value": ".asc", 36 | "highFalsePositive": false 37 | }, 38 | { 39 | "description": "Possible certificates information", 40 | "secretType": "secretFilenameLiteral", 41 | "value": "cert", 42 | "highFalsePositive": true 43 | }, 44 | { 45 | "description": "Possible creds", 46 | "secretType": "fileContentLiteral", 47 | "value": "pswd", 48 | "highFalsePositive": true 49 | }, 50 | { 51 | "description": "Possible public key", 52 | "secretType": "secretFilenameLiteral", 53 | "value": ".pub", 54 | "highFalsePositive": true 55 | }, 56 | { 57 | "description": "Potential Jenkins credentials file", 58 | "secretType": "secretFilenameRegex", 59 | "value": "^cred[\\s\\S]*xml", 60 | "highFalsePositive": false 61 | } 62 | 63 | ] 64 | -------------------------------------------------------------------------------- /patterns/Database.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "Database file", 4 | "secretType": "secretFilenameLiteral", 5 | "value":".mdf", 6 | "highFalsePositive": true 7 | }, 8 | { 9 | "description": "Database file", 10 | "secretType": "secretFilenameLiteral", 11 | "value": ".sdf", 12 | "highFalsePositive": true 13 | }, 14 | { 15 | "description": "Database file", 16 | "secretType": "secretFilenameLiteral", 17 | "value": ".sql", 18 | "highFalsePositive": true 19 | }, 20 | { 21 | "description": "Database file", 22 | "secretType": "secretFilenameLiteral", 23 | "value": ".sqlite", 24 | "highFalsePositive": true 25 | }, 26 | { 27 | "description": "MySQL client command history file", 28 | "secretType": "secretFilenameRegex", 29 | "value": "^[\\s\\S]*mysql_history", 30 | "highFalsePositive": true 31 | }, 32 | { 33 | "description": "PostgreSQL client command history file", 34 | "secretType": "secretFilenameRegex", 35 | "value": "^[\\s\\S]*psql_history", 36 | "highFalsePositive": true 37 | }, 38 | { 39 | "description": "Ruby On Rails database configuration file", 40 | "secretType": "secretFilenameRegex", 41 | "value":"^database[\\s\\S]*.yml", 42 | "highFalsePositive": false 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /patterns/Misc.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description" : "AWS access key", 4 | "secretType" : "fileContentRegex", 5 | "value": "\\b[A-Za-z0-9\/+-]{40}\\b", 6 | "highFalsePositive": true 7 | }, 8 | { 9 | "description": "Network traffic capture file", 10 | "secretType": "secretFilenameLiteral", 11 | "value": ".pcap", 12 | "highFalsePositive": false 13 | }, 14 | { 15 | "description": "Pidgin chat client account configuration file", 16 | "secretType": "secretFilenameRegex", 17 | "value": "accounts[\\s\\S]*.xml", 18 | "highFalsePositive": false 19 | }, 20 | { 21 | "description": "Wordpress configuration file", 22 | "secretType": "secretFilenameRegex", 23 | "value": "wp-config[\\s\\S]*.php", 24 | "highFalsePositive": true 25 | }, 26 | { 27 | "description": "Hexchat/XChat IRC client server list configuration file", 28 | "secretType": "secretFilenameRegex", 29 | "value": ".?xchat2[\\s\\S]*.conf", 30 | "highFalsePositive": false 31 | 32 | }, 33 | { 34 | "description": "S3cmd configuration file", 35 | "secretType": "secretFilenameLiteral", 36 | "highFalsePositive": false, 37 | "value": ".s3cfg" 38 | }, 39 | { 40 | "description": "T command-line Twitter client configuration file", 41 | "secretType": "secretFilenameLiteral", 42 | "highFalsePositive": false, 43 | "value": ".trc" 44 | }, 45 | { 46 | "description": "OpenVPN client configuration file", 47 | "secretType": "secretFilenameLiteral", 48 | "highFalsePositive": false, 49 | "value": ".ovpn" 50 | }, 51 | { 52 | "description": "Ruby On Rails secret token configuration file", 53 | "secretType": "secretFilenameLiteral", 54 | "highFalsePositive": false, 55 | "value": "secret_token" 56 | }, 57 | { 58 | "description": "OmniAuth configuration file", 59 | "value": ".omniauth", 60 | "highFalsePositive": false, 61 | "secretType": "secretFilenameLiteral" 62 | }, 63 | { 64 | "description": "Carrierwave configuration file", 65 | "secretType": "secretFilenameLiteral", 66 | "highFalsePositive": false, 67 | "value": "carrierwave" 68 | }, 69 | { 70 | "description": "Django configuration file", 71 | "secretType": "secretFilenameLiteral", 72 | "highFalsePositive": false, 73 | "value": "settings.py" 74 | }, 75 | { 76 | "description": "Client SSH Config", 77 | "secretType": "secretFilenameRegex", 78 | "highFalsePositive": false, 79 | "value": ".?ssh_config[\\s\\S]*" 80 | }, 81 | { 82 | "description": "Server SSH Config", 83 | "secretType": "secretFilenameRegex", 84 | "highFalsePositive": false, 85 | "value": ".?sshd_config[\\s\\S]*" 86 | }, 87 | { 88 | "description": "KeePass password manager database file", 89 | "secretType": "secretFilenameLiteral", 90 | "highFalsePositive": false, 91 | "value": ".kdb" 92 | }, 93 | { 94 | "description": "Contains word: backup", 95 | "secretType": "secretFilenameLiteral", 96 | "highFalsePositive": true, 97 | "value": ".backup" 98 | }, 99 | { 100 | "description": "Contains word: dump", 101 | "secretType": "secretFilenameLiteral", 102 | "highFalsePositive": true, 103 | "value": ".dump" 104 | }, 105 | { 106 | "description": "Jenkins publish over SSH plugin file", 107 | "secretType": "secretFilenameRegex", 108 | "highFalsePositive": false, 109 | "value": "jenkins.plugins.publish_over_ssh[^ ]*.xml" 110 | }, 111 | { 112 | "description": "Potential MediaWiki configuration file", 113 | "secretType": "secretFilenameRegex", 114 | "highFalsePositive": true, 115 | "value": "LocalSettings[^ ]*php" 116 | }, 117 | { 118 | "description": "Rubygems credentials file", 119 | "secretType": "secretFilenameRegex", 120 | "highFalsePositive": false, 121 | "value": "\\A\\.?gem/credentials\\z" 122 | }, 123 | { 124 | "description": "SSH file", 125 | "secretType": "secretFilenameLiteral", 126 | "highFalsePositive": false, 127 | "value": ".ssh" 128 | }, 129 | { 130 | "description": "Github Dev API key", 131 | "secretType": "fileContentRegex", 132 | "highFalsePositive": false, 133 | "value": "jekyll_github_token[^ ]*" 134 | }, 135 | { 136 | "description": "DHCP server configs", 137 | "secretType": "secretFilenameRegex", 138 | "highFalsePositive": false, 139 | "value": "dhcpd[^ ]*.conf" 140 | }, 141 | { 142 | "description": "Heroku Environment Variable", 143 | "secretType": "fileContentLiteral", 144 | "highFalsePositive": false, 145 | "value": "heroku config:set" 146 | }, 147 | { 148 | "description": "Jupyter Configuration file", 149 | "secretType": "secretFilenameRegex", 150 | "highFalsePositive": false, 151 | "value": "jupyter[^ ]*config[^ ]*.json" 152 | } 153 | ] 154 | -------------------------------------------------------------------------------- /patterns/blueflower.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "descrption": "bitlocker", 4 | "secretType": "secretFilenameLiteral", 5 | "value": ".bek", 6 | "highFalsePositive": false 7 | }, 8 | { 9 | "descrption": "bitlocker", 10 | "secretType": "secretFilenameLiteral", 11 | "value": ".tpm", 12 | "highFalsePositive": false 13 | }, 14 | { 15 | "descrption": "bitlocker", 16 | "secretType": "secretFilenameLiteral", 17 | "value": ".fve", 18 | "highFalsePositive": false 19 | }, 20 | { 21 | "descrption": "certs", 22 | "secretType": "secretFilenameLiteral", 23 | "value": ".crt", 24 | "highFalsePositive": false 25 | }, 26 | { 27 | "descrption": "java key store", 28 | "secretType": "secretFilenameLiteral", 29 | "value": ".jks", 30 | "highFalsePositive": false 31 | }, 32 | { 33 | "descrption": "openssl .key, apple .keychain, etc.", 34 | "secretType": "secretFilenameLiteral", 35 | "value": ".key", 36 | "highFalsePositive": false 37 | }, 38 | { 39 | "descrption": "passwordsafe", 40 | "secretType": "secretFilenameLiteral", 41 | "value": ".psafe3", 42 | "highFalsePositive": false 43 | }, 44 | { 45 | "descrption": "PKCS15 tokens", 46 | "secretType": "secretFilenameLiteral", 47 | "value": ".p15", 48 | "highFalsePositive": false 49 | }, 50 | { 51 | "descrption": "mozilla", 52 | "secretType": "secretFilenameLiteral", 53 | "value": "cert8.db", 54 | "highFalsePositive": false 55 | }, 56 | { 57 | "descrption": "sql", 58 | "secretType": "secretFilenameLiteral", 59 | "value": "connect.inc", 60 | "highFalsePositive": false 61 | }, 62 | { 63 | "descrption": "dbman", 64 | "secretType": "secretFilenameLiteral", 65 | "value": "default.pass", 66 | "highFalsePositive": false 67 | }, 68 | { 69 | "descrption": "apache/nginx", 70 | "secretType": "secretFilenameLiteral", 71 | "value": "htaccess", 72 | "highFalsePositive": false 73 | }, 74 | { 75 | "descrption": "openssh", 76 | "secretType": "secretFilenameLiteral", 77 | "value": "id_dsa", 78 | "highFalsePositive": false 79 | }, 80 | { 81 | "descrption": "openssh", 82 | "secretType": "secretFilenameLiteral", 83 | "value": "id_ecdsa", 84 | "highFalsePositive": false 85 | }, 86 | { 87 | "descrption": "openssh", 88 | "secretType": "secretFilenameLiteral", 89 | "value": "id_ed25519", 90 | "highFalsePositive": false 91 | }, 92 | { 93 | "descrption": "openssh", 94 | "secretType": "secretFilenameLiteral", 95 | "value": "id_rsa", 96 | "highFalsePositive": false 97 | }, 98 | { 99 | "descrption": "mozilla", 100 | "secretType": "secretFilenameLiteral", 101 | "value": "key3.db", 102 | "highFalsePositive": false 103 | }, 104 | { 105 | "descrption": "typo3", 106 | "secretType": "secretFilenameLiteral", 107 | "value": "localconf", 108 | "highFalsePositive": false 109 | }, 110 | { 111 | "descrption": "wikimedia", 112 | "secretType": "secretFilenameLiteral", 113 | "value": "localsettings", 114 | "highFalsePositive": false 115 | }, 116 | { 117 | "descrption": "~/.netrc", 118 | "secretType": "secretFilenameLiteral", 119 | "value": "netrc", 120 | "highFalsePositive": false 121 | }, 122 | { 123 | "descrption": "libpurple otr fingerprints", 124 | "secretType": "secretFilenameLiteral", 125 | "value": "otr.fingerprints", 126 | "highFalsePositive": false 127 | }, 128 | { 129 | "descrption": "misc", 130 | "secretType": "secretFilenameLiteral", 131 | "value": "passlist", 132 | "highFalsePositive": false 133 | }, 134 | { 135 | "descrption": "*nix & htpasswd", 136 | "secretType": "secretFilenameLiteral", 137 | "value": "passwd", 138 | "highFalsePositive": false 139 | }, 140 | { 141 | "descrption": "misc", 142 | "secretType": "secretFilenameLiteral", 143 | "value": "passwords", 144 | "highFalsePositive": false 145 | }, 146 | { 147 | "descrption": "pgp", 148 | "secretType": "secretFilenameLiteral", 149 | "value": "pgplog", 150 | "highFalsePositive": false 151 | }, 152 | { 153 | "descrption": "pgp", 154 | "secretType": "secretFilenameLiteral", 155 | "value": "pgppolicy.xml", 156 | "highFalsePositive": false 157 | }, 158 | { 159 | "descrption": "pgp", 160 | "secretType": "secretFilenameLiteral", 161 | "value": "pgpprefs.xml", 162 | "highFalsePositive": false 163 | }, 164 | { 165 | "descrption": "gnupg", 166 | "secretType": "secretFilenameLiteral", 167 | "value": "secring", 168 | "highFalsePositive": false 169 | }, 170 | { 171 | "descrption": "sftp", 172 | "secretType": "secretFilenameLiteral", 173 | "value": "sftp-config", 174 | "highFalsePositive": false 175 | }, 176 | { 177 | "descrption": "*nix", 178 | "secretType": "secretFilenameLiteral", 179 | "value": "shadow", 180 | "highFalsePositive": true 181 | }, 182 | { 183 | "descrption": "freebsd", 184 | "secretType": "secretFilenameLiteral", 185 | "value": "spwd.bd", 186 | "highFalsePositive": false 187 | }, 188 | { 189 | "descrption": ".net", 190 | "secretType": "secretFilenameLiteral", 191 | "value": "users.xml", 192 | "highFalsePositive": false 193 | }, 194 | { 195 | "descrption": "bitcoin", 196 | "secretType": "secretFilenameLiteral", 197 | "value": "wallet.dat", 198 | "highFalsePositive": false 199 | } 200 | ] 201 | -------------------------------------------------------------------------------- /patterns/gitrob.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "value": "\\A.*_rsa\\z", 4 | "description": "Private SSH key", 5 | "secretType": "secretFilenameRegex", 6 | "highFalsePositive": false 7 | }, 8 | { 9 | "value": "\\A.*_dsa\\z", 10 | "description": "Private SSH key", 11 | "secretType": "secretFilenameRegex", 12 | "highFalsePositive": false 13 | }, 14 | { 15 | "value": "\\A.*_ed25519\\z", 16 | "description": "Private SSH key", 17 | "secretType": "secretFilenameRegex", 18 | "highFalsePositive": false 19 | }, 20 | { 21 | "value": "\\A.*_ecdsa\\z", 22 | "description": "Private SSH key", 23 | "secretType": "secretFilenameRegex", 24 | "highFalsePositive": false 25 | }, 26 | { 27 | "value": "\\.?ssh/config\\z", 28 | "description": "SSH configuration file", 29 | "secretType": "secretFilenameRegex", 30 | "highFalsePositive": false 31 | }, 32 | { 33 | "value": ".pem", 34 | "description": "Potential cryptographic private key", 35 | "secretType": "secretFilenameLiteral", 36 | "highFalsePositive": false 37 | }, 38 | { 39 | "value": "\\Akey(pair)?\\z", 40 | "description": "Potential cryptographic private key", 41 | "secretType": "secretFilenameRegex", 42 | "highFalsePositive": false 43 | }, 44 | { 45 | "value": ".pkcs12", 46 | "description": "Potential cryptographic key bundle", 47 | "secretType": "secretFilenameLiteral", 48 | "highFalsePositive": false 49 | }, 50 | { 51 | "value": ".pfx", 52 | "description": "Potential cryptographic key bundle", 53 | "secretType": "secretFilenameLiteral", 54 | "highFalsePositive": false 55 | }, 56 | { 57 | "value": ".p12", 58 | "description": "Potential cryptographic key bundle", 59 | "secretType": "secretFilenameLiteral", 60 | "highFalsePositive": false 61 | }, 62 | { 63 | "value": ".asc", 64 | "description": "Potential cryptographic key bundle", 65 | "secretType": "secretFilenameLiteral", 66 | "highFalsePositive": false 67 | }, 68 | { 69 | "value": ".otr.private_key", 70 | "description": "Pidgin OTR private key", 71 | "secretType": "secretFilenameLiteral", 72 | "highFalsePositive": false 73 | }, 74 | { 75 | "value": "\\A\\.?(bash_|zsh_|z)?history\\z", 76 | "description": "Shell command history file", 77 | "secretType": "secretFilenameRegex", 78 | "highFalsePositive": false 79 | }, 80 | { 81 | "value": "\\A\\.?mysql_history\\z", 82 | "description": "MySQL client command history file", 83 | "secretType": "secretFilenameRegex", 84 | "highFalsePositive": false 85 | }, 86 | { 87 | "value": "\\A\\.?psql_history\\z", 88 | "description": "PostgreSQL client command history file", 89 | "secretType": "secretFilenameRegex", 90 | "highFalsePositive": false 91 | }, 92 | { 93 | "value": "\\A\\.?pgpass\\z", 94 | "description": "PostgreSQL password file", 95 | "secretType": "secretFilenameRegex", 96 | "highFalsePositive": false 97 | }, 98 | { 99 | "value": "\\A\\.?irb_history\\z", 100 | "description": "Ruby IRB console history file", 101 | "secretType": "secretFilenameRegex", 102 | "highFalsePositive": false 103 | }, 104 | { 105 | "value": "\\.?purple\\/accounts\\.xml\\z", 106 | "description": "Pidgin chat client account configuration file", 107 | "secretType": "secretFilenameRegex", 108 | "highFalsePositive": false 109 | }, 110 | { 111 | "value": "\\.?xchat2?\\/servlist_?\\.conf\\z", 112 | "description": "Hexchat/XChat IRC client server list configuration file", 113 | "secretType": "secretFilenameRegex", 114 | "highFalsePositive": false 115 | }, 116 | { 117 | "value": "\\.?irssi\\/config\\z", 118 | "description": "Irssi IRC client configuration file", 119 | "secretType": "secretFilenameRegex", 120 | "highFalsePositive": false 121 | }, 122 | { 123 | "value": "\\.?recon-ng\\/keys\\.db\\z", 124 | "description": "Recon-ng web reconnaissance framework API key database", 125 | "secretType": "secretFilenameRegex", 126 | "highFalsePositive": false 127 | }, 128 | { 129 | "value": "\\A\\.?dbeaver-data-sources.xml\\z", 130 | "description": "DBeaver SQL database manager configuration file", 131 | "secretType": "secretFilenameRegex", 132 | "highFalsePositive": false 133 | }, 134 | { 135 | "value": "\\A\\.?muttrc\\z", 136 | "description": "Mutt e-mail client configuration file", 137 | "secretType": "secretFilenameRegex", 138 | "highFalsePositive": false 139 | }, 140 | { 141 | "value": "\\A\\.?s3cfg\\z", 142 | "description": "S3cmd configuration file", 143 | "secretType": "secretFilenameRegex", 144 | "highFalsePositive": false 145 | }, 146 | { 147 | "value": "\\.?aws/credentials\\z", 148 | "description": "AWS CLI credentials file", 149 | "secretType": "secretFilenameRegex", 150 | "highFalsePositive": false 151 | }, 152 | { 153 | "value": "\\A\\.?trc\\z", 154 | "description": "T command-line Twitter client configuration file", 155 | "secretType": "secretFilenameRegex", 156 | "highFalsePositive": false 157 | }, 158 | { 159 | "value": ".ovpn", 160 | "description": "OpenVPN client configuration file", 161 | "secretType": "secretFilenameLiteral", 162 | "highFalsePositive": false 163 | }, 164 | { 165 | "value": "\\A\\.?gitrobrc\\z", 166 | "description": "Well, this is awkward... Gitrob configuration file", 167 | "secretType": "secretFilenameRegex", 168 | "highFalsePositive": false 169 | }, 170 | { 171 | "value": "\\A\\.?(bash|zsh)rc\\z", 172 | "description": "Shell configuration file", 173 | "secretType": "secretFilenameRegex", 174 | "highFalsePositive": false 175 | }, 176 | { 177 | "value": "\\A\\.?(bash_|zsh_)?profile\\z", 178 | "description": "Shell profile configuration file", 179 | "secretType": "secretFilenameRegex", 180 | "highFalsePositive": false 181 | }, 182 | { 183 | "value": "\\A\\.?(bash_|zsh_)?aliases\\z", 184 | "description": "Shell command alias configuration file", 185 | "secretType": "secretFilenameRegex", 186 | "highFalsePositive": false 187 | }, 188 | { 189 | "value": "database.yml", 190 | "description": "Potential Ruby On Rails database configuration file", 191 | "secretType": "secretFilenameLiteral", 192 | "highFalsePositive": false 193 | }, 194 | { 195 | "value": "\\A(.*)?config(\\.inc)?\\.php\\z", 196 | "description": "PHP configuration file", 197 | "secretType": "secretFilenameRegex", 198 | "highFalsePositive": true 199 | }, 200 | { 201 | "value": ".kdb", 202 | "description": "KeePass password manager database file", 203 | "secretType": "secretFilenameLiteral", 204 | "highFalsePositive": false 205 | }, 206 | { 207 | "value": ".agilekeychain", 208 | "description": "1Password password manager database file", 209 | "secretType": "secretFilenameLiteral", 210 | "highFalsePositive": false 211 | }, 212 | { 213 | "value": ".keychain", 214 | "description": "Apple Keychain database file", 215 | "secretType": "secretFilenameLiteral", 216 | "highFalsePositive": false 217 | }, 218 | { 219 | "value": "\\Akey(store|ring)\\z", 220 | "description": "GNOME Keyring database file", 221 | "secretType": "secretFilenameRegex", 222 | "highFalsePositive": false 223 | }, 224 | { 225 | "value": ".log", 226 | "description": "Log file", 227 | "secretType": "secretFilenameLiteral", 228 | "highFalsePositive": true 229 | }, 230 | { 231 | "value": ".pcap", 232 | "description": "Network traffic capture file", 233 | "secretType": "secretFilenameLiteral", 234 | "highFalsePositive": false 235 | }, 236 | { 237 | "value": "\\Asql(dump)?\\z", 238 | "description": "SQL dump file", 239 | "secretType": "secretFilenameRegex", 240 | "highFalsePositive": false 241 | }, 242 | { 243 | "value": ".gnucash", 244 | "description": "GnuCash database file", 245 | "secretType": "secretFilenameLiteral", 246 | "highFalsePositive": false 247 | }, 248 | { 249 | "value": "credential", 250 | "description": "Contains word: credential", 251 | "secretType": "secretFilenameLiteral", 252 | "highFalsePositive": true 253 | }, 254 | { 255 | "value": "secret", 256 | "description": "Contains word: secret", 257 | "secretType": "secretFilenameLiteral", 258 | "highFalsePositive": false 259 | }, 260 | { 261 | "value": "private[^ ]*key", 262 | "description": "Contains words: private, key", 263 | "secretType": "secretFilenameRegex", 264 | "highFalsePositive": true 265 | }, 266 | { 267 | "value": "jenkins.plugins.publish_over_ssh.BapSshPublisherPlugin.xml", 268 | "description": "Jenkins publish over SSH plugin file", 269 | "secretType": "secretFilenameLiteral", 270 | "highFalsePositive": false 271 | }, 272 | { 273 | "value": "credentials.xml", 274 | "description": "Potential Jenkins credentials file", 275 | "secretType": "secretFilenameLiteral", 276 | "highFalsePositive": false 277 | }, 278 | { 279 | "value": "\\A\\.?htpasswd\\z", 280 | "description": "Apache htpasswd file", 281 | "secretType": "secretFilenameRegex", 282 | "highFalsePositive": false 283 | }, 284 | { 285 | "value": "\\A(\\.|_)?netrc\\z", 286 | "description": "Configuration file for auto-login process", 287 | "secretType": "secretFilenameRegex", 288 | "highFalsePositive": false 289 | }, 290 | { 291 | "value": ".kwallet", 292 | "description": "KDE Wallet Manager database file", 293 | "secretType": "secretFilenameLiteral", 294 | "highFalsePositive": false 295 | }, 296 | { 297 | "value": "LocalSettings.php", 298 | "description": "Potential MediaWiki configuration file", 299 | "secretType": "secretFilenameLiteral", 300 | "highFalsePositive": false 301 | }, 302 | { 303 | "value": "tblk", 304 | "description": "Tunnelblick VPN configuration file", 305 | "secretType": "secretFilenameLiteral", 306 | "highFalsePositive": true 307 | }, 308 | { 309 | "value": "\\.?gem/credentials\\z", 310 | "description": "Rubygems credentials file", 311 | "secretType": "secretFilenameRegex", 312 | "highFalsePositive": false 313 | }, 314 | { 315 | "value": "\\A*\\.pubxml(\\.user)?\\z", 316 | "description": "Potential MSBuild publish profile", 317 | "secretType": "secretFilenameRegex", 318 | "highFalsePositive": false 319 | }, 320 | { 321 | "value": "Favorites.plist", 322 | "description": "Sequel Pro MySQL database manager bookmark file", 323 | "secretType": "secretFilenameLiteral", 324 | "highFalsePositive": false 325 | }, 326 | { 327 | "value": "configuration.user.xpl", 328 | "description": "Little Snitch firewall configuration file", 329 | "secretType": "secretFilenameLiteral", 330 | "highFalsePositive": false 331 | }, 332 | { 333 | "value": ".dayone", 334 | "description": "Day One journal file", 335 | "secretType": "secretFilenameLiteral", 336 | "highFalsePositive": false 337 | }, 338 | { 339 | "value": "journal.txt", 340 | "description": "Potential jrnl journal file", 341 | "secretType": "secretFilenameLiteral", 342 | "highFalsePositive": false 343 | }, 344 | { 345 | "value": "\\A\\.?tugboat\\z", 346 | "description": "Tugboat DigitalOcean management tool configuration", 347 | "secretType": "secretFilenameRegex", 348 | "highFalsePositive": false 349 | }, 350 | { 351 | "value": "\\A\\.?git-credentials\\z", 352 | "description": "git-credential-store helper credentials file", 353 | "secretType": "secretFilenameRegex", 354 | "highFalsePositive": false 355 | }, 356 | { 357 | "value": "\\A\\.?gitconfig\\z", 358 | "description": "Git configuration file", 359 | "secretType": "secretFilenameRegex", 360 | "highFalsePositive": false 361 | }, 362 | { 363 | "value": "knife.rb", 364 | "description": "Chef Knife configuration file", 365 | "secretType": "secretFilenameLiteral", 366 | "highFalsePositive": false 367 | }, 368 | { 369 | "value": "\\.?chef/(.*)\\.pem\\z", 370 | "description": "Chef private key", 371 | "secretType": "secretFilenameRegex", 372 | "highFalsePositive": false 373 | }, 374 | { 375 | "value": "proftpdpasswd", 376 | "description": "cPanel backup ProFTPd credentials file", 377 | "secretType": "secretFilenameLiteral", 378 | "highFalsePositive": false 379 | }, 380 | { 381 | "value": "robomongo.json", 382 | "description": "Robomongo MongoDB manager configuration file", 383 | "secretType": "secretFilenameLiteral", 384 | "highFalsePositive": false 385 | }, 386 | { 387 | "value": "filezilla.xml", 388 | "description": "FileZilla FTP configuration file", 389 | "secretType": "secretFilenameLiteral", 390 | "highFalsePositive": false 391 | }, 392 | { 393 | "value": "recentservers.xml", 394 | "description": "FileZilla FTP recent servers file", 395 | "secretType": "secretFilenameLiteral", 396 | "highFalsePositive": false 397 | }, 398 | { 399 | "value": "ventrilo_srv.ini", 400 | "description": "Ventrilo server configuration file", 401 | "secretType": "secretFilenameLiteral", 402 | "highFalsePositive": false 403 | }, 404 | { 405 | "value": "\\A\\.?dockercfg\\z", 406 | "description": "Docker configuration file", 407 | "secretType": "secretFilenameRegex", 408 | "highFalsePositive": false 409 | }, 410 | { 411 | "value": "\\A\\.?npmrc\\z", 412 | "description": "NPM configuration file", 413 | "secretType": "secretFilenameRegex", 414 | "highFalsePositive": false 415 | }, 416 | { 417 | "value": "terraform.tfvars", 418 | "description": "Terraform variable config file", 419 | "secretType": "secretFilenameLiteral", 420 | "highFalsePositive": false 421 | }, 422 | { 423 | "value": "\\A\\.?env\\z", 424 | "description": "Environment configuration file", 425 | "secretType": "secretFilenameRegex", 426 | "highFalsePositive": false 427 | } 428 | ] 429 | -------------------------------------------------------------------------------- /patterns/new.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "highFalsePositive": "false", 4 | "value": "(\\n[a-z0-9_\\-]+[:;\\|][a-z0-9_\\-]+){10,}", 5 | "description": "Secret", 6 | "secretType": "fileContentRegex" 7 | }, 8 | { 9 | "highFalsePositive": "false", 10 | "value": "(api|secret)key\\s*[\\=]+", 11 | "description": "API secret key", 12 | "secretType": "fileContentRegex" 13 | }, 14 | { 15 | "highFalsePositive": "false", 16 | "value": "BEGIN:VCALENDAR", 17 | "description": "iCalender", 18 | "secretType": "fileContentLiteral" 19 | }, 20 | { 21 | "highFalsePositive": "false", 22 | "value": "\\s*[a-z0-9\\-_]*secret[key]+\\s*[:=]+\\s*[\"']\\S+[\"']", 23 | "description": "secret key", 24 | "secretType": "fileContentRegex" 25 | }, 26 | { 27 | "highFalsePositive": "false", 28 | "value": "^[a-z0-9]+:[a-z0-9]{13}$", 29 | "description": "HtPasswds", 30 | "secretType": "fileContentRegex" 31 | }, 32 | { 33 | "highFalsePositive": "false", 34 | "value": "secret\\s*[\\=]+", 35 | "description": "Secret finder", 36 | "secretType": "fileContentRegex" 37 | } 38 | ] 39 | --------------------------------------------------------------------------------