{"id":13717199,"url":"https://github.com/cugu/gocap","last_synced_at":"2025-05-07T07:30:33.005Z","repository":{"id":37241680,"uuid":"447011983","full_name":"cugu/gocap","owner":"cugu","description":"List your dependencies capabilities and monitor if updates require more  capabilities.","archived":true,"fork":false,"pushed_at":"2023-05-21T12:12:09.000Z","size":51,"stargazers_count":130,"open_issues_count":0,"forks_count":12,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-08-04T00:13:11.461Z","etag":null,"topics":["go","supply-chain-attacks","supply-chain-security"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cugu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-01-11T23:23:53.000Z","updated_at":"2024-01-15T07:02:47.000Z","dependencies_parsed_at":"2024-01-14T21:29:10.454Z","dependency_job_id":null,"html_url":"https://github.com/cugu/gocap","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cugu%2Fgocap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cugu%2Fgocap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cugu%2Fgocap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cugu%2Fgocap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cugu","download_url":"https://codeload.github.com/cugu/gocap/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224573309,"owners_count":17333802,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["go","supply-chain-attacks","supply-chain-security"],"created_at":"2024-08-03T00:01:19.196Z","updated_at":"2024-11-14T05:31:06.285Z","avatar_url":"https://github.com/cugu.png","language":"Go","funding_links":[],"categories":["Dependency intelligence","Go"],"sub_categories":[],"readme":"# A take on supply chain security in Go\n\nList your dependencies capabilities and monitor if dependency updates require more capabilities.\n\n## The Problem\n\nRecently different [attacks](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610) and\n[other](https://www.bleepingcomputer.com/news/security/dev-corrupts-npm-libs-colors-and-faker-breaking-thousands-of-apps/)\n[issues](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228)\nrelated to open-source dependencies highlighted a quite severe problem with dependencies:\n\n\u003e Every imported package gives that package's author basically remote code\n\u003e execution for your software.\n\n## The Idea\n\nA [video on WASI](https://www.youtube.com/watch?v=fh9WXPu0hw8) by\n[linclark](https://twitter.com/linclark) brought me to the idea how cool it would be if we could pass permissions to our\ndependencies.\n\nIn Go this could look something like this:\n\n```\nmodule github.com/cugu/gocap\n\ngo 1.20\n\nrequire (\n\tgithub.com/go-chi/chi       v5.0.7   (network:read)\n\tgithub.com/mattn/go-sqlite3 v1.14.10 (file:read, file:write)\n\tgithub.com/sirupsen/logrus  v1.8.1   (os:stdout)\n\tgithub.com/yuin/goldmark    v1.4.4   ()\n)\n```\n\n`chi` would be able to receive network requests, `go-sqlite3` would be able to read and write files and `logrus` could\nwrite to stdout. But also all those modules would be limited to those capabilities and, for example, the logging\nlibrary `logrus` would not be able to interact with files, the network or execute code.\n\nChanges of dependencies would be much less critical in many cases, as a potential attacker would have only limited\nattack surface besides stealing your CPU cycles.\n\n## A simpler but working approach: GoCap\n\nImplementing the approach above would require changes to Go itself. So I came up with another, simpler approach: GoCap.\nGoCap can check and validate the source code of dependencies for their capabilities and is ment to be included into the\ntesting phase of the build process. This way GoCap can at least pin the capabilities of dependencies.\n\nGoCap provides simple capability checking for Go using a `go.cap` file. The\n`go.cap` files lists all package dependencies that require critical permissions like file access, execution rights or\nnetwork access. Unlike the idea above GoCap works on packages not modules and capabilities are based on the imported\npackages of the standard library.\n\nThe `go.cap` file for GoCap itself looks like this:\n\n```\ngithub.com/cugu/gocap (execute, file)\n\ngithub.com/alecthomas/kong (file, syscall)\ngithub.com/pkg/errors (runtime)\n```\n\n### Install GoCap\n\nYou can [download a release](https://github.com/cugu/gocap/releases) or run\n\n```shell\ngo install github.com/cugu/gocap@v0.1.0\n```\n\n### gocap generate\n\n`gocap generate \u003cpath\u003e` prints a valid `go.cap` file. It lists all dependency packages that require critical permissions\nlike file access, execution rights or network access.\n\n**! `gocap generate` runs on package basis and the path argument must point to a Go package (there must be .go files)\nnot a Go Module. Also `gocap generate` needs the dependencies downloaded before, e.g. run `go mod download`**.\n\n*Example*\n\n```shell\ncd ~/myProjects/gocap\ngo mod download\ngocap generate . \u003e go.cap\n```\n\n*go.cap*\n\n```\ngithub.com/cugu/gocap (execute, file)\n\ngithub.com/alecthomas/kong (file, syscall)\ngithub.com/pkg/errors (runtime)\n``` \n\n### gocap check\n\n`gocap check \u003cpath\u003e` compares a local `go.cap` file with the actual required capabilities by dependency packages. Any\nmismatch results in a non-zero exit code, so you can use GoCap check in your CI pipelines.\nSee [ci.yml](https://github.com/cugu/gocap/blob/main/.github/workflows/ci.yml#L28) for a working example.\n\n*Example*\n\n```shell\ngocap check .\n```\n\n*Output*\n\n```\ngithub.com/alecthomas/kong\n\tcapability 'syscall' not provided by go.cap file, add to go.cap file if you want to grant the capability\ngithub.com/pkg/errors\n\tunnecessary capability 'network', please remove from go.cap file\n``` \n\n## Capabilities\n\n| Name    | Description                                                                                                                         | Packages     |\n|---------|-------------------------------------------------------------------------------------------------------------------------------------|--------------|\n| file    | Read and write access to files                                                                                                      | os io/ioutil |\n| network | Read and write to the network                                                                                                       | net net/http |\n| execute | Execute other binaries                                                                                                              | os/exec      |\n| syscall | Perform any system call in context of the software                                                                                  | syscall, C   |\n| unsafe  | Usage of the unsafe package in combination with a //go:linkname compiler directive can be used to load external C or assembler code | unsafe       |\n| reflect | reflect.NewAt in combination with reflect#Value.Call might be used call arbitrary functions                                         | reflect      |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcugu%2Fgocap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcugu%2Fgocap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcugu%2Fgocap/lists"}