{"id":22177057,"url":"https://github.com/cokebeer/goot","last_synced_at":"2025-06-26T00:04:49.774Z","repository":{"id":58508111,"uuid":"528636487","full_name":"cokeBeer/goot","owner":"cokeBeer","description":"a dataflow analysis framework implemented in Go, like soot","archived":false,"fork":false,"pushed_at":"2022-09-22T07:17:30.000Z","size":772,"stargazers_count":34,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-03T07:43:00.620Z","etag":null,"topics":["analysis-framework","go","static-analysis","taint-analysis","taint-tracking","vulnerability-detection"],"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/cokeBeer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-25T00:18:20.000Z","updated_at":"2025-03-25T13:19:14.000Z","dependencies_parsed_at":"2023-01-18T17:00:56.779Z","dependency_job_id":null,"html_url":"https://github.com/cokeBeer/goot","commit_stats":null,"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/cokeBeer/goot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cokeBeer%2Fgoot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cokeBeer%2Fgoot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cokeBeer%2Fgoot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cokeBeer%2Fgoot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cokeBeer","download_url":"https://codeload.github.com/cokeBeer/goot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cokeBeer%2Fgoot/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261973725,"owners_count":23238586,"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":["analysis-framework","go","static-analysis","taint-analysis","taint-tracking","vulnerability-detection"],"created_at":"2024-12-02T08:25:12.575Z","updated_at":"2025-06-26T00:04:49.751Z","avatar_url":"https://github.com/cokeBeer.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"goot-logo.png\" height=\"200\" style=\"border-radius:10px;\"\u003e\n\n # goot\n\u003c/div\u003e\n\n- [goot](#goot)\n\t- [What is goot?](#what-is-goot)\n\t- [Get started](#get-started)\n\t- [Use taint analysis](#use-taint-analysis)\n\t- [Save to neo4j](#save-to-neo4j)\n\t- [Use as a framework](#use-as-a-framework)\n\t- [Tips](#tips)\n\t- [Thanks](#thanks)\n## What is goot?\n\n[goot](https://github.com/cokeBeer/goot) is a static analysis framework for Go. goot is easy-to-learn, easy-to-use and highly extensible, allowing you to easily develop new analyses on top of it.\n\nCurrently, goot provides the following major analysis components (and more analyses are on the way):\n\n- Control/Data-flow analysis framework\n  - Control-flow graph construction\n  - Classic data-flow analyses, e.g. taint analysis\n  - Your dataflow analyses\n\n## Get started\n\nIntall goot by\n\n```\ngo get -u github.com/cokeBeer/goot\n```\n\n##  Use taint analysis\nWrite code below in the project to be analysed, e.g `cmd/taint/main.go`\n```go\npackage main\n\nimport \"github.com/cokeBeer/goot/pkg/example/dataflow/taint\"\n\nfunc main() {\n\t// if this file is cmd/taint/main.go\n\t// and you want to analyse package pkg\n\t// the path should be \"../../pkg\"\n\t// or \"../../pkg...\" for all packages under pkg\n\trunner := taint.NewRunner(\"relative/path/to/package\")\n\t// for this project, is \"github.com/cokeBeer/goot\"\n\trunner.ModuleName = \"module-name\"\n\trunner.PassThroughDstPath = \"passthrough.json\"\n\trunner.TaintGraphDstPath = \"taintgraph.json\"\n\trunner.Run()\n}\n```\nRun the code, and you will get a `passthrough.json` in the same directory, which contains taint passthrough information of all functions in your project\\\nYou can see key `fmt.Sprintf` holds a value object \n```json\n{\n    \"fmt.Sprintf\": {\n        \"Recv\": null,\n        \"Results\": [\n            [0, 1]\n        ],\n        \"Params\": [\n            [0, 1],\n            [1]\n        ]\n    }\n}\n```\nThis means three things\n- the first parameter's taint and the second parameter's taint are passed to the first return value,\n- the first parameter receives the first parameter's taint\n- the second parameter receives the second parameter's taint\n\nAlso, you will get a `taintgraph.json` in the same directory\\\nYou can see the json file contains taint edges from one call parameter to another call parameter\n```json\n{\n    \"(*github.com/example/runnner.Runner).RunCmd#0#(*os/exec.Cmd).StdoutPipe#0\": {\n        \"From\": \"(*github.com/example/runnner.Runner).RunCmd\",\n        \"FromIndex\": 0,\n        \"To\": \"(*os/exec.Cmd).StdoutPipe\",\n        \"ToIndex\": 0,\n        \"ToIsMethod\": false,\n        \"ToIsSink\": true,\n        \"ToIsSignature\": false,\n        \"ToIsStatic\": true\n    }\n}\n```\nThis means there is a taint edge from position `0` of `RunCmd` (in this case, the parameter is the receiver `runner.Runner` itself ) to position `0` of `StdoutPipe` (in this case, the parameter is ther recevier `exec.Cmd` iteself, too)\n\n## Save to neo4j\nTo view taint edges better, you can load them to neo4j by set these parameters (for more detailed options, see [options of runner](pkg/example/dataflow/taint/README.md))\n```go\nfunc main() {\n\trunner := taint.NewRunner(\"../../internal...\")\n\trunner.ModuleName = \"gitlab.com/gitlab-org/gitlab-workhorse\"\n\t// parameters about neo4j\n\trunner.PersistToNeo4j = true\n\trunner.Neo4jURI = \"bolt://localhost:7687\"\n\trunner.Neo4jUsername = \"neo4j\"\n\trunner.Neo4jPassword = \"password\"\n\terr := runner.Run()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n```\nWhen analysis is end, you can find nodes and taint edges in your neo4j database\\\nFor example, we run taint analysis on [gitlab.com/gitlab-org/gitlab-workhorse@v13.10.0](https://gitlab.com/gitlab-org/gitlab/-/tree/v13.10.0-ee/workhorse)，which has a RCE vulnerability [CVE-2021-22225](https://hackerone.com/reports/1154542)\\\nUsing query below to find taint paths\n```\nMATCH (source:Source),(sink:Sink {name:\"os/exec.CommandContext\"}),p=(source)-[*7]-\u003e(sink) RETURN p\n```\nWe can get a graph like this: (the red nodes are sink, the brown nodes are intra functions and the green nodes are source)\n![](assets/images/workhorse.png)\nWhich reveals two taint paths from source to sink `os/exec.CommandContext`, the same as [CVE-2021-22225](https://hackerone.com/reports/1154542)\n## Use as a framework\nTo use goot as a framework, first create two structs implementing  `pkg/toolkits/scalar.FlowAnalysis` interface\n\n```go\n// FlowAnalysis represents a flow analysis\ntype FlowAnalysis interface {\n\tGetGraph() *graph.UnitGraph\n\tIsForward() bool\n\tComputations() int\n\tFlowThrougth(inMap *map[any]any, unit ssa.Instruction, outMap *map[any]any)\n\tNewInitalFlow() *map[any]any\n\tEntryInitalFlow() *map[any]any\n\tCopy(srcMap *map[any]any, dstMap *map[any]any)\n\tMergeInto(Unit ssa.Instruction, inout *map[any]any, in *map[any]any)\n\tEnd(universe []*entry.Entry)\n}\n```\n\nand `pkg/golang/switcher.Switcher` interface seperately\n\n```go\n// Switcher represents a ssa instruction switcher\ntype Switcher interface {\n\tCaseAlloc(inst *ssa.Alloc)\n\tCasePhi(inst *ssa.Phi)\n\tCaseCall(inst *ssa.Call)\n\tCaseBinOp(inst *ssa.BinOp)\n\tCaseUnOp(inst *ssa.UnOp)\n\t...\n\tCaseGo(inst *ssa.Go)\n\tCaseDefer(inst *ssa.Defer)\n\tCaseSend(inst *ssa.Send)\n\tCaseStore(inst *ssa.Store)\n\tCaseMapUpdate(inst *ssa.MapUpdate)\n\tCaseDebugRef(inst *ssa.DebugRef)\n}\n```\n\nDon't worry for these apis. An easy way to implement them is using compose like `pkg/toolkits/scalar.BaseFlowAnalysis`\n\n```go\n// ConstantPropagationAnalysis represents a constant propagtion analysis\ntype ConstantPropagationAnalysis struct {\n\tscalar.BaseFlowAnalysis\n\tconstantPropagationSwitcher *ConstantPropagationSwitcher\n}\n```\n\nand `pkg/golang/switcher.BaseSwitcher`\n\n```go\n// ConstantPropagationSwitcher represents a constant propagtion switcher\ntype ConstantPropagationSwitcher struct {\n\tswitcher.BaseSwitcher\n\tconstanctPropagationAnalysis *ConstantPropagationAnalysis\n\tinMap                        *map[any]any\n\toutMap                       *map[any]any\n}\n```\n\nThese can make you focus on the core methods you really need to design carefully in specific analyses\\\nYou can learn more information about **how to use goot as a framework** and **how to run an analysis** from a tiny example I prepared for you in [how to use](pkg/example/dataflow/constantpropagation) and [how to run](cmd/constantpropagationanalysis/) which demonstrates a `constant propagation analysis`\n\n\n## Tips\n\n- goot's api is similar to [soot](https://github.com/soot-oss/soot), so if you wonder how goot's api work, you can [learn soot](https://github.com/soot-oss/soot/wiki/Implementing-an-intra-procedural-data-flow-analysis-in-Soot) first\n- goot uses `*map[any]any` as flow and `ssa.Instruction` as unit, so please be careful of type assertion\n\n## Thanks\n\n- [soot](https://github.com/soot-oss/soot)\n- [Tai-e](https://github.com/pascal-lab/Tai-e)\n- [tabby](https://github.com/wh1t3p1g/tabby)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcokebeer%2Fgoot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcokebeer%2Fgoot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcokebeer%2Fgoot/lists"}