{"id":37956808,"url":"https://github.com/mrwong99/gitscanner","last_synced_at":"2026-01-16T18:01:14.368Z","repository":{"id":37102206,"uuid":"433929143","full_name":"MrWong99/gitscanner","owner":"MrWong99","description":"Gitscanner  is used to perform a variety of security checks against Git repositories and is expandable. Feel free to add your own checks.","archived":false,"fork":false,"pushed_at":"2023-03-07T07:00:24.000Z","size":2914,"stargazers_count":2,"open_issues_count":45,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-06-19T19:39:47.415Z","etag":null,"topics":["cli","clone","git","golang","scan","security","ui"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MrWong99.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-01T17:50:28.000Z","updated_at":"2022-01-14T09:15:34.000Z","dependencies_parsed_at":"2024-06-19T19:00:06.185Z","dependency_job_id":"d64c84a5-7a7c-40a1-8def-feadcb753e8d","html_url":"https://github.com/MrWong99/gitscanner","commit_stats":{"total_commits":82,"total_committers":6,"mean_commits":"13.666666666666666","dds":0.5609756097560976,"last_synced_commit":"4e6fbd706291809cc1251e649aa2a190c69f6183"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/MrWong99/gitscanner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrWong99%2Fgitscanner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrWong99%2Fgitscanner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrWong99%2Fgitscanner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrWong99%2Fgitscanner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MrWong99","download_url":"https://codeload.github.com/MrWong99/gitscanner/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MrWong99%2Fgitscanner/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28480513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","clone","git","golang","scan","security","ui"],"created_at":"2026-01-16T18:00:36.665Z","updated_at":"2026-01-16T18:01:14.346Z","avatar_url":"https://github.com/MrWong99.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Git Repository security checker\n\nThis is a fast Go implementation to check Git repositories (local or remote) for some common security issues.\nIt relies heavily on [go-git](https://github.com/go-git/go-git).\n\n## Usage\n\nTo simply start the scanner run this command and provide a configuration file in YAML or JSON format:\n\n`./gitscanner -config \u003cpath to config file\u003e`\n\nTake a look at the [full configuration file](/GrootConfig.yml) for further configuration options.\n\n![UI Example](/ui_example.png)\n\nHere is the full list of available parameters:\n\n```\n$ ./gitscanner --help\nUsage of ./gitscanner:\n  -config string\n        The absolute or relative path of the application configuration file. (default \"GrootConfig.yml\")\n  -decrypt string\n        When set this tool will simply decrypt the given input and exit afterwards. Can be used to decrypt any value for the config file given the correct key.\n  -encrypt string\n        When set this tool will simply encrypt the given input and exit afterwards. Can be used to encrypt any value for the config file.\n  -encryptionKey string\n        Key to use for en-/decrypting sensitive data. Can also be provided via environment variable 'ENCRYPTION_KEY' or by typing into console after start.\n```\n\n## Performed checks\n\n* **[SearchBinaries](/checks/binaryfile/binaryfile.go):** Searches for any binary files on each branch (local or remote) that matches the `branchPattern`.\n* **[SearchIllegalUnicodeCharacters](/checks/unicode/unicode.go):** Searches for specific unicode characters in each file on each branch (local or remote) that matches the `branchPattern`. See [trojan-source.pdf](https://trojansource.codes/trojan-source.pdf).\n* **[CheckCommitMetaInformation](/checks/commitmeta/commitmeta.go):** Checks every commits author and committer name and email for expected match against `emailPattern` and `namePattern`.\n* **[SearchBigFiles](/checks/filesize/filesize.go):** Searches for files on each branch (local or remote) that matches the `branchPattern` and is bigger than `filesizeThresholdByte`.\n  \n## Build locally\n\n1. Install Go.\n2. `go build .`\n\n## Add new tests\n\nAdding tests is very simple:\n\n1. Write a type implementing the [Checker interface](checks/checks.go#L39)\n```go\npackage myawesometest\n\nimport (\n    mygit \"github.com/MrWong99/gitscanner/git\"\n    \"github.com/MrWong99/gitscanner/utils\"\n)\n\ntype MyTest struct{\n}\n\nfunc (*MyTest) Check(wrapRepo *mygit.ClonedRepo, output chan\u003c- *utils.SingleCheck) error {\n    defer close(output)\n    // perform checks here and write any found issues into the output channel\n}\n```\n2. Add the function to the list of possible checks in [main.go](main.go#L45-47)\n\n## REST API\n\nWhen started in server mode *gitscanner* will provide the following endpoints:\n\n### POST /api/v1/checkRepos - Perform checks for given paths\n\n**Status Codes:**\n\n* `200`: checks were performed. Singular could still have failed though.\n* `400`: the request body was malformed.\n\n**Request Body:**\n\n* `path`: a comma separated list of urls to clone. They can be in these formats:\n  * `http(s)://\u003cremote URL\u003e`\n  * `git@\u003cremote URL\u003e`\n  * `file://\u003cpath\u003e` -\u003e will only search on the local filesystem of the server\n* `checks`: a list of check identifiers to determine with checks are to be performed. See [GET checks](#get-apiv1checks---retrieve-the-list-of-possible-checks).\n\n*Example:*\n\n```json\n{\n  \"path\": \"git@github.com:go-git/go-git.git,https://gitlab.com/gitlab-org/gitlab.git\",\n  \"checkNames\": [\n    \"SearchBinaries\",\n    \"CheckCommitMetaInformation\",\n    \"SearchIllegalUnicodeCharacters\",\n    \"SearchBigFiles\"\n  ]\n}\n```\n\n**Response Body:**\n\n* Array of objects with:\n  * `date`: ISO encoded timestamp of when the check was started\n  * `repository`: the repository that was checked\n  * `error`: if any error occured while opening the repo it will be contained here, else empty string\n  * `checks`: list of checks that contained suspicious results. Each check consists of:\n    * `origin`: where this issue was found. This can be multiple things, e.g. a path to a file or a commit hash.\n    * `branch`: the branch (if any) on which the issue was found.\n    * `checkName`: the name of the check that found this issue.\n    * `acknowledged`: currently always false, will be used in future updates.\n    * `additionalInfo`: list of non-specified key-value pairs that differ from check to check.\n\n*Example:*\n\n```json\n[\n    {\n        \"date\": \"2021-12-03T00:22:00.6155686+01:00\",\n        \"repository\": \"git@github.com:MrWong99/micasuca.git\",\n        \"error\": \"\",\n        \"checks\": [\n            {\n                \"origin\": \"Commit 65508c0d5f0ea52ce3d93f77f471359f4ec1d1bc\",\n                \"branch\": \"\",\n                \"checkName\": \"CheckCommitMetaInformation\",\n                \"acknowledged\": false,\n                \"additionalInfo\": {\n                    \"authorEmail\": \"shady.dude@inter.net\",\n                    \"authorName\": \"Jeff\",\n                    \"commitMessage\": \"Table view (in progress...)\\n\",\n                    \"commiterEmail\": \"shady.dude@inter.net\",\n                    \"commiterName\": \"jeffHacker\",\n                    \"commitSize\": \"1.2 TB\",\n                    \"numberOfParents\": 1\n                }\n            },\n            {\n                \"origin\": \"gradle/wrapper/gradle-wrapper.jar\",\n                \"branch\": \"refs/remotes/origin/master\",\n                \"checkName\": \"SearchBigFiles\",\n                \"acknowledged\": false,\n                \"additionalInfo\": {\n                    \"filemode\": \"0100644\",\n                    \"filesize\": \"54.3 kB\"\n                }\n            },\n            {\n                \"origin\": \"gradle/wrapper/gradle-wrapper.jar\",\n                \"branch\": \"refs/remotes/origin/master\",\n                \"checkName\": \"SearchBinaries\",\n                \"acknowledged\": false,\n                \"additionalInfo\": {\n                    \"filemode\": \"0100644\",\n                    \"filesize\": \"54.3 kB\"\n                }\n            },\n            {\n                \"origin\": \"gradlew\",\n                \"branch\": \"refs/remotes/origin/master\",\n                \"checkName\": \"SearchIllegalUnicodeCharacters\",\n                \"acknowledged\": false,\n                \"additionalInfo\": {\n                    \"character\":\"'\\\\u202a'\",\n                    \"filemode\": \"0100644\",\n                    \"filesize\": \"5.3 kB\"\n                }\n            }\n        ]\n    },\n    {\n        \"date\": \"2021-12-03T00:22:01.0774318+01:00\",\n        \"repository\": \"https://github.com/Mnaaz/JavaChat\",\n        \"error\": \"\",\n        \"checks\": []\n    }\n]\n```\n\n### GET /api/v1/checkDefinitions - Retrieve the list of possible checks\n\n**Status Codes:**\n\n* `200`: Checks retrieved.\n\n**Response Body:**\n\n* List of strings for all registered checks\n\n*Example:*\n\n```json\n[\n    \"SearchBinaries\",\n    \"SearchIllegalUnicodeCharacters\",\n    \"CheckCommitMetaInformation\",\n    \"SearchBigFiles\"\n]\n```\n\n### GET /api/v1/config/{checkName} - Retrieve the current configuration for a check\n\n**Path Params:**\n\n* `checkName`: the name of the check whos configuration should be returned.\n\n**Status Codes:**\n\n* `200`: configuration was returned.\n* `400`: configuration not found or unable to read.\n\n**Response Body:**\n\n* `name`: the name of the check.\n* `enabled`: if set to false this check can't be executed.\n* `config`: a configuration object specific for each check. Here is a list of possible values:\n  * `branchPattern`: pattern to match branches against. The *SearchBinaries* and *SearchIllegalUnicodeCharacters* checks use this.\n  * `namePattern`: pattern to match the commiter and author names against. The *CheckCommitMetaInformation* check uses this.\n  * `emailPattern`: pattern to match the commiter and author emails against. The *CheckCommitMetaInformation* check uses this.\n  * `filesizeThresholdByte`: Amout of bytes that a file should have maximum to trigger this check. The *SearchBigFiles* check uses this.\n  * `commitSizeThresholdByte`: Amout of bytes that a file should have maximum to trigger this check. The *CheckCommitMetaInformation* check uses this.\n\n*Example:*\n\n```json\n{\n    \"name\": \"SearchBigFiles\",\n    \"enabled\": false,\n    \"config\": {\n        \"branchPattern\": \".*origin/master\",\n        \"filesizeThresholdByte\": 89234\n    }\n}\n```\n\n### PUT /api/v1/config - Set the configuration for a check\n\n**Status Codes:**\n\n* `200`: config was updated.\n* `400`: the request body was malformed.\n\n**Request Body:**\n\n* `name`: the name of the check.\n* `enabled`: if set to false this check can't be executed.\n* `config`: a configuration object specific for each check. Here is a list of possible values:\n  * `branchPattern`: pattern to match branches against. The *SearchBinaries* and *SearchIllegalUnicodeCharacters* checks use this.\n  * `namePattern`: pattern to match the commiter and author names against. The *CheckCommitMetaInformation* check uses this.\n  * `emailPattern`: pattern to match the commiter and author emails against. The *CheckCommitMetaInformation* check uses this.\n  * `filesizeThresholdByte`: Amout of bytes that a file should have maximum to trigger this check. The *SearchBigFiles* check uses this.\n  * `commitSizeThresholdByte`: Amout of bytes that a file should have maximum to trigger this check. The *CheckCommitMetaInformation* check uses this.\n\n*Example:*\n\n```json\n{\n    \"name\": \"CheckCommitMetaInformation\",\n    \"enabled\": true,\n    \"config\": {\n        \"namePattern\": \"MrWong99\",\n        \"emailPattern\": \".*@cool.com|.*@nice.eu\"\n    }\n}\n```\n\n### PUT /api/v1/config/sshkey - Set the ssh private key to use when using ssh during clone\n\n**Status Codes:**\n\n* `200`: config was updated.\n* `400`: the request body was malformed.\n\n**Request Body:**\n\n* `key`: the ssh private key. Can be additionally encrypted with\n* `password`: the password that this key was encrypted with if any\n\n*Example:*\n\n```json\n{\n    \"key\": \"-----BEGIN RSA PRIVATE KEY-----\\nyOut41nK1mdUMB?\\n-----END RSA PRIVATE KEY-----\",\n    \"password\": \"\"\n}\n```\n\n### PUT /api/v1/config/basicauth - Set the username and password when usic basic authentication during clone\n\n**Status Codes:**\n\n* `200`: config was updated.\n* `400`: the request body was malformed.\n\n**Request Body:**\n\n* `username`: the username to use.\n* `password`: the password to use.\n\n*Example:*\n\n```json\n{\n    \"username\": \"SecureMan\",\n    \"password\": \"1n5EcuR3\"\n}\n```\n\n### GET /api/v1/checks?from={from}\u0026to={to}\u0026checkNames={checkNames} - Retrieve previously performed checks that are stored in DB\n\n**Status Codes:**\n\n* `200`: checks retrieved successfully\n* `500`: checks could not be read from DB\n\n**Query Parameters:**\n\n* `from`: milliseconds since 1970-01-01 as start date from which checks should be included.\n* `to`: milliseconds since 1970-01-01 as end date until which checks should be included.\n* `checkNames`: comma-separated list of check names to include in the results.\n\n**Response Body:**\n\nSame as in [/api/v1/checkRepos](#post-apiv1checkrepos---perform-checks-for-given-paths).\n\n### PUT api/v1/acknowledged/{checkID} - Set the acknowledged flag of given check\n\n**Path Params:**\n\n* `checkID`: the id of the check that should be set to acknowledged.\n\n**Request Body:**\n\n* `acknowledged`: boolean indecating wether this check was acknowledged or not.\n\n*Example:*\n\n```json\n{\n    \"acknowledged\": true\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrwong99%2Fgitscanner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmrwong99%2Fgitscanner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrwong99%2Fgitscanner/lists"}