{"id":50769910,"url":"https://github.com/unidoc/unisupply","last_synced_at":"2026-06-11T17:03:58.761Z","repository":{"id":361438723,"uuid":"1208439743","full_name":"unidoc/unisupply","owner":"unidoc","description":"Go supply chain security analysis – finds vulnerabilities, weak maintainers, typosquatting, and CI/CD risks. SBOM + enterprise PDF reports.","archived":false,"fork":false,"pushed_at":"2026-06-07T16:14:08.000Z","size":646,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-07T18:10:34.523Z","etag":null,"topics":["audit-report","ci-cd-security","cyclonedx","dependency-analysis","go","go-modules","golang","maintainer-analysis","risk-assessment","sbom","sca","slsa","software-composition-analysis","spdx","supply-chain-security","typosquatting"],"latest_commit_sha":null,"homepage":"https://unidoc.io","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/unidoc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-12T09:30:37.000Z","updated_at":"2026-05-31T18:05:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/unidoc/unisupply","commit_stats":null,"previous_names":["unidoc/unisupply"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/unidoc/unisupply","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unidoc%2Funisupply","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unidoc%2Funisupply/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unidoc%2Funisupply/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unidoc%2Funisupply/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unidoc","download_url":"https://codeload.github.com/unidoc/unisupply/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unidoc%2Funisupply/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34208769,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["audit-report","ci-cd-security","cyclonedx","dependency-analysis","go","go-modules","golang","maintainer-analysis","risk-assessment","sbom","sca","slsa","software-composition-analysis","spdx","supply-chain-security","typosquatting"],"created_at":"2026-06-11T17:03:57.822Z","updated_at":"2026-06-11T17:03:58.749Z","avatar_url":"https://github.com/unidoc.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# unisupply\n\n\u003e Go supply chain risk assessment — vulnerabilities, maintainer health, typosquatting, AI-generated code risk, CI/CD audit, SBOM, policy enforcement.\n\n\u003c!--\nTODO (PR 11 / M5.5): the repository is currently private. When it goes public,\nreplace this comment block with the live badge row below.\n\n[![CI](https://github.com/unidoc/unisupply/actions/workflows/ci.yml/badge.svg)](https://github.com/unidoc/unisupply/actions/workflows/ci.yml)\n[![Release](https://github.com/unidoc/unisupply/actions/workflows/release.yml/badge.svg)](https://github.com/unidoc/unisupply/actions/workflows/release.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/unidoc/unisupply)](https://goreportcard.com/report/github.com/unidoc/unisupply)\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\n\nCoverage badge intentionally omitted — no Codecov / Coveralls integration yet.\nDo not surface an integrity signal that is not backed by a verification\nmechanism (OWASP SCVS V4.1).\n--\u003e\n\n## What it does\n\n`unisupply` analyzes a Go project's full module dependency chain and produces a\nsupply chain risk assessment. It runs nine focused scanners — vulnerability\nlookup, maintenance health, maintainer analysis, typosquatting detection,\nresilience scoring, AI-generated code heuristics, CI/CD pipeline audit, build\nfile inspection, and Trust Index lookup — combines the in-tree scanner signals\ninto a weighted risk score per dependency, attaches the optional Trust Index\ndata to each report alongside that score, and renders the result as a colored terminal\nsummary, machine-readable JSON, an enterprise PDF report, or a CycloneDX /\nSPDX SBOM. A built-in policy engine fails CI on configurable thresholds\n(critical vulns, max age, blocked modules, unpinned actions, ...).\n\nIt is intended for engineering teams that need to make merge-time and\nrelease-time decisions about third-party Go code.\n\n## Install\n\n```bash\n# Latest release (Go 1.25+ required)\ngo install github.com/unidoc/unisupply/cmd/unisupply@latest\n\n# Or download a prebuilt binary from the Releases page\n#   https://github.com/unidoc/unisupply/releases\n```\n\nHomebrew and other package-manager distribution channels are tracked as\npost-1.0 follow-ups; for now use `go install` or the release tarballs.\n\n## Quick start\n\n```bash\n# Scan the current module\nunisupply ./\n\n# JSON output for CI ingestion\nunisupply ./ --format json --output results.json\n\n# Full PDF report (requires UNIDOC_LICENSE_API_KEY for PDF generation)\nunisupply ./ \\\n    --format pdf \\\n    --output report.pdf \\\n    --github-token \"$GITHUB_TOKEN\"\n\n# Policy-enforced run — exits 2 on violation\nunisupply ./ --policy-preset strict\n```\n\nA typical text-format run against a small project looks like this (truncated\nfor the README — your output will list every direct and transitive\ndependency):\n\n```\nunisupply v0.4.0 — Go Supply Chain Risk Assessment\nby UniDoc (unidoc.io)\n\nProject: github.com/example/app\nDependencies: 4 direct, 38 transitive (42 total, 113 graph edges)\n\n═══════════════════════════════════════════════════\nOVERALL SUPPLY CHAIN RISK SCORE: 26/100 (MEDIUM)\n═══════════════════════════════════════════════════\n\nHIGH RISK (3 dependencies)\n────────────────────────────────────────\n● golang.org/x/net      Risk: 51/100  (transitive)\n  ├─ 4 known vulnerabilities with available fixes\n  ├─ Resilience: 70/100 (frequent cadence, 53 releases)\n  └─ Score: vuln=100×40% maint=0×25% depth=0×15% maintainer=0×10% maturity=0×10%\n\nMEDIUM RISK (19 dependencies)   [...]\nLOW RISK (20 dependencies)      [use --verbose to see details]\n\nPACKAGES ELIGIBLE FOR MAINTENANCE TAKEOVER\n────────────────────────────────────────\n  ● widely-used/inactive-pkg   Activity: inactive   Bus factor: 1\n```\n\nPass `--verbose` for full per-dependency breakdowns including the dependency\npath that pulled the module in.\n\n## Scanners\n\n| Scanner          | What it checks                                          | Data source                |\n| ---------------- | ------------------------------------------------------- | -------------------------- |\n| Vulnerability    | Known CVEs in dependencies                              | Go vuln DB (vuln.go.dev)   |\n| Maintenance      | Last release, archive status, deprecation               | Go Module Proxy            |\n| Maintainer       | Contributors, bus factor, activity, org verification    | GitHub API                 |\n| Typosquatting    | Levenshtein-similarity to ~75 well-known modules        | Built-in list              |\n| Resilience       | Release cadence, governance files, version scheme       | GitHub API                 |\n| AI-Generated     | Fresh modules, few releases, generic names (heuristics) | Module metadata            |\n| CI/CD            | Action pinning, permissions, secret exposure            | `.github/workflows/*.yml`  |\n| Build files      | Unpinned Docker images, `curl \\| bash` patterns         | Dockerfile, Makefile, *.sh |\n| Trust Index      | Curated trust scores                                    | unitrust API (optional)    |\n\nThe risk score is a weighted composite:\n\n```\nRisk Score (0–100) =\n    Vulnerabilities × 0.40\n  + Maintenance     × 0.25\n  + Depth           × 0.15\n  + Maintainer Risk × 0.10\n  + Maturity        × 0.10\n  + Typosquat Penalty      (0–20)\n  + AI-Gen Penalty         (0–15)\n  + Low-Resilience Penalty (0–6)  // adds when resilience score \u003c 30\n```\n\nLevels: **LOW** 0–25 · **MEDIUM** 26–50 · **HIGH** 51–75 · **CRITICAL** 76–100.\n\n## Output formats\n\n| Format                | Flag                       | Use                                                 |\n| --------------------- | -------------------------- | --------------------------------------------------- |\n| Text (colored)        | `--format text` (default)  | Interactive terminal use                            |\n| JSON                  | `--format json`            | CI ingestion, dashboards, programmatic consumers    |\n| PDF                   | `--format pdf`             | Enterprise reports (built with UniPDF + UniChart)   |\n| CycloneDX SBOM        | `--format sbom-cyclonedx`  | Standard CycloneDX 1.5 software bill of materials   |\n| SPDX SBOM             | `--format sbom-spdx`       | SPDX 2.3 software bill of materials                 |\n\n## Policy engine\n\n`unisupply` ships two presets and accepts a custom JSON policy file. Policy\nviolations cause the binary to exit `2`, which is the convention CI systems\nexpect for a deliberate fail-fast.\n\n```bash\n# Built-in presets\nunisupply ./ --policy-preset strict\nunisupply ./ --policy-preset moderate\n\n# Custom policy\nunisupply ./ --policy ./security-policy.json\n```\n\nA minimal custom policy (every field is optional — see\n[`pkg/policy/engine.go`](pkg/policy/engine.go) for the full set):\n\n```json\n{\n  \"max_overall_score\": 50,\n  \"max_risk_score\": 75,\n  \"no_critical_vulns\": true,\n  \"no_archived\": true,\n  \"no_deprecated\": true,\n  \"no_typosquatting\": true,\n  \"no_unmaintained_months\": 24,\n  \"max_depth\": 8,\n  \"max_ci_score\": 50,\n  \"blocked_modules\": [\"github.com/suspicious/pkg\"],\n  \"allowed_modules\": [\"golang.org/x/\", \"github.com/unidoc/\"]\n}\n```\n\nNotable fields:\n\n- `no_known_vulns` / `no_critical_vulns` — fail on any vuln, or only on\n  high/critical-severity vulns.\n- `no_single_maintainer` — fail if any **direct** dependency has bus factor ≤ 1.\n- `allowed_modules` — when set, acts as a strict whitelist applied to **direct\n  dependencies only**; transitive modules are not gated by this rule. Each\n  entry matches by exact module path or by path-prefix (`\"golang.org/x/\"`\n  matches `golang.org/x/net`); glob patterns are not supported.\n- `blocked_modules` — applies to direct and transitive dependencies, with the\n  same exact-or-prefix matching rule.\n- `max_ci_score` — gate on the CI/CD scanner's overall risk score (requires\n  `--scan-ci`).\n\n\u003c!-- TODO (PR 08 / M6.5): once the examples/ directory lands, link to ready-to-copy policy files here. --\u003e\n\n## Trust Index integration\n\n`unisupply` can enrich a scan with curated trust data from a running\n[unitrust](https://github.com/unidoc/unitrust) instance. The Trust Index is\nUniDoc's curated database of Go module trustworthiness — it goes beyond what\npublic APIs and heuristics can tell you (vulnerability feeds, GitHub\ncontributor counts, release cadence) and adds **vetted, human-reviewed**\nmetadata: who actually maintains the package, what country and organization\nthey operate from, whether their identity is verified, the package's\nstewardship status, and — when a module is known-risky — a recommended safer\nalternative.\n\n### How it works\n\nWhen `--trust-index-url` points at a reachable unitrust instance, every\ndiscovered module (direct and transitive) is sent in a **single batched\nHTTP request** to `POST /api/v1/lookup`. The returned data is folded into\neach dependency's report alongside the in-tree scanner output. No per-module\ncalls, no fan-out — one round trip regardless of graph size.\n\n```bash\n# Hosted unitrust (production CI)\nunisupply ./ \\\n    --trust-index-url https://unitrust.unidoc.io \\\n    --format json --output results.json\n```\n\n### What the Trust Index adds to a report\n\nFor every module that unitrust has data on, the report gains:\n\n| Field                     | What it tells you                                                    |\n| ------------------------- | -------------------------------------------------------------------- |\n| `trust_score`             | Composite curated trust score (0–100)                                |\n| `maintainer_trust`        | Curated confidence in the maintainer's identity and track record     |\n| `resilience_score`        | Project resilience as assessed by UniDoc, not just heuristics        |\n| `security_score`          | Curated security posture (review history, hardening, response time)  |\n| `community_score`         | Community health beyond raw star/fork counts                         |\n| `maintainer_name`         | Real maintainer name where known                                     |\n| `maintainer_org`          | Sponsoring or employing organization                                 |\n| `maintainer_country`      | Maintainer jurisdiction — relevant for compliance / sanctions checks |\n| `maintainer_verified`     | Whether UniDoc has verified the maintainer's identity                |\n| `stewardship_status`      | `actively_maintained`, `community`, `inactive`, `abandoned`, …       |\n| `safer_alternative`       | Recommended replacement module, if the entry is flagged as risky     |\n| `is_unidoc_maintained`    | True for modules under UniDoc's own stewardship                      |\n\nThe full schema lives in\n[`pkg/scanner/trustindex.go`](pkg/scanner/trustindex.go) (`TrustIndexEntry`).\nModules unitrust has no entry for are reported with their normal scanner\noutput unchanged.\n\n### When to use it\n\n- **CI gating** — combine `--trust-index-url` with `--policy-preset strict`\n  to fail builds on known-risky modules whose risk isn't yet visible in the\n  CVE feeds.\n- **Procurement / vendor review** — the maintainer name, country, and\n  verification flag are the fields enterprise reviewers actually need; they\n  are not derivable from `go.mod` alone.\n- **Supply-chain incident response** — the `safer_alternative` field\n  short-circuits \"what should we replace this with?\" during a live\n  incident.\n\n### Privacy and operational notes\n\n- The lookup payload contains **only module paths** — the same information\n  that is already in your published `go.mod`. Versions are not transmitted,\n  and the request includes no source code, scan results, or other\n  project-identifying data.\n- The whole feature is **opt-in and additive**. Leaving `--trust-index-url`\n  off produces a fully self-contained scan — `unisupply` never reaches out\n  to unitrust by default and has no implicit endpoint.\n- Failures of the Trust Index call (network errors, non-200 responses) are\n  surfaced as warnings; they do not abort the scan or alter risk scores\n  derived from the in-tree scanners.\n\n## Architecture\n\n```\nCLI (pflag)\n  │\n  ├── Parse go.mod / go.sum          pkg/parser/\n  ├── Resolve dependency graph        pkg/resolver/\n  ├── Run 9 security scanners        pkg/scanner/\n  │   ├── Vulnerability (govulncheck)\n  │   ├── Maintenance health\n  │   ├── Maintainer analysis (GitHub API)\n  │   ├── Typosquatting detection\n  │   ├── Resilience scoring\n  │   ├── AI-generated code risk\n  │   ├── CI/CD pipeline audit\n  │   ├── Trust Index lookup (unitrust, optional)\n  │   └── Build file scanning\n  ├── Compute risk scores             pkg/scorer/\n  ├── Evaluate org policies           pkg/policy/\n  └── Generate reports                pkg/report/\n      ├── Text (colored terminal)\n      ├── JSON (machine-readable)\n      ├── PDF (UniPDF)\n      └── SBOM (CycloneDX, SPDX)\n```\n\n## Configuration reference\n\nThe full flag set is always available via:\n\n```bash\nunisupply --help\n```\n\nThe most frequently used flags:\n\n| Flag                    | Purpose                                                       |\n| ----------------------- | ------------------------------------------------------------- |\n| `-f, --format`          | `text`, `json`, `pdf`, `sbom-cyclonedx`, `sbom-spdx`          |\n| `-o, --output`          | Output file (default: stdout for text/json/sbom)              |\n| `--github-token`        | GitHub API token (or `GITHUB_TOKEN` env)                      |\n| `--trust-index-url`     | unitrust endpoint for curated trust scores                    |\n| `--policy-preset`       | `strict` or `moderate`                                        |\n| `--policy`              | Path to a custom policy JSON file                             |\n| `--scan-workflows`      | Audit `.github/workflows/*.yml` and `*.yaml` only             |\n| `--scan-ci`             | Full CI/CD audit: workflows + Dockerfile / Makefile / scripts |\n| `--min-risk`            | Hide dependencies below the given score                       |\n| `--direct-only`         | Skip transitive dependencies                                  |\n| `-v, --verbose`         | Per-dependency breakdown                                      |\n\nEnvironment variables:\n\n| Variable          | Purpose                                                          |\n| ----------------- | ---------------------------------------------------------------- |\n| `GITHUB_TOKEN`    | Higher GitHub API rate limits and access to private repositories |\n| `UNIDOC_LICENSE_API_KEY` | UniDoc license key (required for PDF report generation)   |\n\n## Documentation\n\n- [docs/scanners.md](docs/scanners.md) — scanner reference and the canonical risk-scoring formula\n- [SECURITY.md](SECURITY.md) — vulnerability reporting and supported versions\n- [CONTRIBUTING.md](CONTRIBUTING.md) — development setup and PR process\n- [CHANGELOG.md](CHANGELOG.md) — release notes (Keep a Changelog 1.1)\n- [RELEASING.md](RELEASING.md) — maintainer release procedure\n- [LICENSE](LICENSE) — Apache License 2.0\n\n## License\n\nApache License 2.0 — see [LICENSE](LICENSE) for the full text.\n\nCopyright © UniDoc ehf.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funidoc%2Funisupply","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funidoc%2Funisupply","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funidoc%2Funisupply/lists"}