Skip to content

Commit 1216044

Browse files
committed
feat: add Go ecosystem support to supply-chain plugin
1 parent ff338a3 commit 1216044

11 files changed

Lines changed: 982 additions & 10 deletions

File tree

SUPPLY-CHAIN.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@ and on **clone/pull** (you download a poisoned repo).
2727
- Non-registry sources (vcs/url/editable, inline `git`/`url`/`path`, PEP 508 direct URLs).
2828
- Unpinned requirements and typosquats.
2929

30+
**Go** (`go.mod`, `go.sum`):
31+
32+
- `replace` directives pointing at local filesystem paths or redirecting to a different remote
33+
module.
34+
- Suspicious module hosts: raw IPv4, `localhost`, or module paths containing `http://`.
35+
- Pseudo-versions, `+incompatible` versions, changed `toolchain` directives, and added `exclude`
36+
directives.
37+
- Typosquatted module paths checked against the offline `lib/data/go-popular.js` list.
38+
- `go.sum` lockfile lines with suspicious module hosts.
39+
- `vendor/modules.txt` is not scanned.
40+
41+
These heuristics are a warning layer, not a guarantee. Absence of findings does not mean a repo is
42+
safe.
43+
3044
**Behaviour:** non-blocking by default (findings are surfaced for review), or configured to
3145
**hard-block** at/above a severity you choose.
3246

@@ -240,7 +254,7 @@ Set `GIT_PROXY_SUPPLY_CHAIN_CONFIG` to a JSON file:
240254
{
241255
"enabled": true,
242256
"failOn": "off",
243-
"ecosystems": { "npm": true, "python": true },
257+
"ecosystems": { "npm": true, "python": true, "go": true },
244258
"typosquat": true,
245259
"allowPackages": [],
246260
"npmRegistryHosts": ["registry.npmjs.org"],
@@ -250,7 +264,8 @@ Set `GIT_PROXY_SUPPLY_CHAIN_CONFIG` to a JSON file:
250264

251265
- `failOn` / `pull.failOn` - `"off"` (warn only) | `"low"` | `"medium"` | `"high"` | `"critical"`.
252266
A push/clone whose highest finding meets or exceeds the threshold is blocked.
253-
- `allowPackages` - names to exempt from typosquat / new-dependency flags.
267+
- `allowPackages` - package names and full Go module paths to exempt from typosquat /
268+
new-dependency flags.
254269
- `npmRegistryHosts` - registry hosts treated as "expected" for lockfile source checks.
255270

256271
---
@@ -286,7 +301,7 @@ Set `GIT_PROXY_SUPPLY_CHAIN_CONFIG` to a JSON file:
286301
the scanned content can differ from what is delivered.
287302
- On an allowed clone the proxy fetches the repo once to scan it and the client fetches again
288303
(a double fetch); a future optimisation serves the pack from the scanned copy.
289-
- Coverage is **npm + Python**; Go/Cargo/RubyGems are planned.
304+
- Coverage is **npm + Python + Go**; Cargo/RubyGems are planned.
290305

291306
---
292307

plugins/git-proxy-plugin-supply-chain/README.md

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,27 @@ On any push that changes `requirements*.txt`, `pyproject.toml`, `setup.py`, `set
4444
- **Lockfile sources** - git or plain-http package sources newly introduced in `poetry.lock` /
4545
`Pipfile.lock`.
4646

47-
> Coverage is npm + Python today. Go, Cargo, RubyGems and others are planned - each is a new
47+
## What it checks (Go)
48+
49+
On any push that changes `go.mod` or `go.sum`:
50+
51+
- **Replace directives** - local filesystem paths (HIGH) and remote redirects to a different
52+
module path (HIGH).
53+
- **Suspicious hosts** - raw IPv4 module hosts (CRITICAL), plus `localhost` or `http://` module
54+
paths (HIGH).
55+
- **Version signals** - pseudo-versions (LOW) and `+incompatible` versions (INFO) on newly-added
56+
require entries.
57+
- **Toolchain directives** - added or changed `toolchain` values (MEDIUM on changed files, INFO
58+
on fresh-file scans).
59+
- **Exclude entries** - newly-added `exclude` directives (INFO).
60+
- **Typosquats** - newly-added module paths compared with the offline list in
61+
`lib/data/go-popular.js` (HIGH).
62+
- **go.sum suspicious hosts** - newly-added lockfile lines whose module host is raw IPv4,
63+
`localhost`, or contains `http://`.
64+
65+
`vendor/modules.txt` is not scanned.
66+
67+
> Coverage is npm + Python + Go today; Cargo, RubyGems and others are planned - each is a new
4868
> module under `lib/ecosystems/` plus an entry in `lib/manifests.js`; the plugin wiring is shared.
4969
5070
## How it runs
@@ -59,8 +79,8 @@ manifest with `git show <newCommit>:<path>` and diffs it against `git show <oldC
5979
The plugin also scans repositories **as they are cloned/fetched through the proxy**, so a developer
6080
is warned - or the clone is blocked - before pulling a poisoned repository. On a
6181
`git clone`/`fetch`, the plugin (running once the repo is confirmed authorised) shallow-clones the
62-
default branch, enumerates its manifests (`git ls-tree`) and scans them with the same npm/Python
63-
analyzers, treating the whole tree as newly introduced.
82+
default branch, enumerates its manifests (`git ls-tree`) and scans them with the same
83+
npm/Python/Go analyzers, treating the whole tree as newly introduced.
6484

6585
- **Warn (default):** findings are logged server-side and the clone proceeds.
6686
- **Block (`pull.failOn` set):** a clone whose highest finding meets/exceeds the threshold **fails**,
@@ -99,7 +119,7 @@ Set the `GIT_PROXY_SUPPLY_CHAIN_CONFIG` environment variable to a JSON file to o
99119
{
100120
"enabled": true,
101121
"failOn": "off",
102-
"ecosystems": { "npm": true, "python": true },
122+
"ecosystems": { "npm": true, "python": true, "go": true },
103123
"typosquat": true,
104124
"allowPackages": [],
105125
"npmRegistryHosts": ["registry.npmjs.org"],
@@ -110,7 +130,8 @@ Set the `GIT_PROXY_SUPPLY_CHAIN_CONFIG` environment variable to a JSON file to o
110130
- `failOn` - `"off"` (default, annotate only) | `"low"` | `"medium"` | `"high"` | `"critical"`.
111131
When set, a push whose highest finding severity meets/exceeds the threshold is **blocked**
112132
(returned as an error to the pusher's terminal).
113-
- `allowPackages` - package names to exempt from typosquat/new-dependency flags.
133+
- `allowPackages` - package names and Go module paths to exempt from typosquat/new-dependency
134+
flags. For Go, use full module paths such as `github.com/stretchr/testify`.
114135
- `npmRegistryHosts` - registry hosts treated as "expected" for lockfile source checks.
115136
- `pull.enabled` - turn pull/clone scanning on or off.
116137
- `pull.failOn` - block threshold for clones (same scale as `failOn`; default `"off"` = warn-only).

plugins/git-proxy-plugin-supply-chain/lib/analyze.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616

1717
import { analyzeNpm } from './ecosystems/npm.js';
1818
import { analyzePython } from './ecosystems/python.js';
19+
import { analyzeGo } from './ecosystems/go.js';
1920
import { maxSeverity } from './severity.js';
2021

2122
// Registry of per-ecosystem analyzers. Add go/cargo/... here as they are implemented.
2223
const ANALYZERS = {
2324
npm: analyzeNpm,
2425
python: analyzePython,
26+
go: analyzeGo,
2527
};
2628

2729
/**

plugins/git-proxy-plugin-supply-chain/lib/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const DEFAULT_CONFIG = {
2525
// 'off' | 'low' | 'medium' | 'high' | 'critical' - block the push when the highest finding
2626
// severity meets/exceeds this threshold. 'off' never blocks (annotate-only).
2727
failOn: 'off',
28-
ecosystems: { npm: true, python: true },
28+
ecosystems: { npm: true, python: true, go: true },
2929
typosquat: true,
3030
allowPackages: [],
3131
npmRegistryHosts: ['registry.npmjs.org'],
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/**
2+
* Copyright 2026 GitProxy Contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Popular Go modules for typosquat detection.
19+
* @type {string[]}
20+
*/
21+
export const GO_POPULAR = [
22+
'golang.org/x/net',
23+
'golang.org/x/sys',
24+
'golang.org/x/text',
25+
'golang.org/x/crypto',
26+
'golang.org/x/tools',
27+
'golang.org/x/mod',
28+
'golang.org/x/sync',
29+
'golang.org/x/time',
30+
'golang.org/x/term',
31+
'golang.org/x/oauth2',
32+
'golang.org/x/exp',
33+
'google.golang.org/grpc',
34+
'google.golang.org/protobuf',
35+
'google.golang.org/api',
36+
'google.golang.org/genproto',
37+
'cloud.google.com/go',
38+
'github.com/stretchr/testify',
39+
'github.com/stretchr/objx',
40+
'github.com/davecgh/go-spew',
41+
'github.com/pmezard/go-difflib',
42+
'github.com/sirupsen/logrus',
43+
'github.com/rs/zerolog',
44+
'go.uber.org/zap',
45+
'go.uber.org/multierr',
46+
'go.uber.org/atomic',
47+
'github.com/pkg/errors',
48+
'github.com/spf13/cobra',
49+
'github.com/spf13/viper',
50+
'github.com/spf13/pflag',
51+
'github.com/spf13/cast',
52+
'github.com/spf13/afero',
53+
'github.com/gin-gonic/gin',
54+
'github.com/gorilla/mux',
55+
'github.com/gorilla/websocket',
56+
'github.com/go-chi/chi',
57+
'github.com/labstack/echo',
58+
'github.com/gofiber/fiber',
59+
'github.com/valyala/fasthttp',
60+
'github.com/julienschmidt/httprouter',
61+
'github.com/urfave/cli',
62+
'github.com/mitchellh/mapstructure',
63+
'github.com/google/uuid',
64+
'github.com/google/go-cmp',
65+
'github.com/google/go-github',
66+
'github.com/gofrs/uuid',
67+
'github.com/golang/protobuf',
68+
'github.com/golang/mock',
69+
'github.com/gogo/protobuf',
70+
'github.com/golang-jwt/jwt',
71+
'github.com/dgrijalva/jwt-go',
72+
'github.com/go-sql-driver/mysql',
73+
'github.com/lib/pq',
74+
'github.com/jackc/pgx',
75+
'github.com/jmoiron/sqlx',
76+
'github.com/mattn/go-sqlite3',
77+
'gorm.io/gorm',
78+
'github.com/redis/go-redis',
79+
'github.com/go-redis/redis',
80+
'go.mongodb.org/mongo-driver',
81+
'github.com/aws/aws-sdk-go',
82+
'github.com/aws/aws-sdk-go-v2',
83+
'github.com/azure/azure-sdk-for-go',
84+
'k8s.io/client-go',
85+
'k8s.io/api',
86+
'k8s.io/apimachinery',
87+
'sigs.k8s.io/yaml',
88+
'gopkg.in/yaml',
89+
'gopkg.in/check',
90+
'github.com/prometheus/client_golang',
91+
'go.opentelemetry.io/otel',
92+
'github.com/grpc-ecosystem/grpc-gateway',
93+
'github.com/hashicorp/vault',
94+
'github.com/hashicorp/consul',
95+
'github.com/hashicorp/go-multierror',
96+
'github.com/hashicorp/hcl',
97+
'github.com/hashicorp/go-retryablehttp',
98+
'github.com/fsnotify/fsnotify',
99+
'github.com/joho/godotenv',
100+
'github.com/kelseyhightower/envconfig',
101+
'github.com/fatih/color',
102+
'github.com/cenkalti/backoff',
103+
'github.com/patrickmn/go-cache',
104+
'github.com/robfig/cron',
105+
'github.com/shopspring/decimal',
106+
'github.com/pelletier/go-toml',
107+
'github.com/burntsushi/toml',
108+
'github.com/klauspost/compress',
109+
'github.com/miekg/dns',
110+
'github.com/nats-io/nats.go',
111+
'github.com/segmentio/kafka-go',
112+
'github.com/go-playground/validator',
113+
'github.com/docker/docker',
114+
];

0 commit comments

Comments
 (0)