Compare commits
2
Commits
b93d09d027
...
9733cb7833
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9733cb7833 | ||
|
|
b656617183 |
No files matched your search
+22
-12
@@ -3,6 +3,9 @@ version: "2"
|
|||||||
# Config schema uses the golangci-lint v2 layout (settings live under
|
# Config schema uses the golangci-lint v2 layout (settings live under
|
||||||
# linters.settings, not top-level linters-settings) so that the
|
# linters.settings, not top-level linters-settings) so that the
|
||||||
# thresholds below are actually applied by golangci-lint >= v2.
|
# thresholds below are actually applied by golangci-lint >= v2.
|
||||||
|
#
|
||||||
|
# This file has no formatters section, so golangci-lint run does not run
|
||||||
|
# gofmt. A repository's script/fmt-check runs it, on the host.
|
||||||
|
|
||||||
run:
|
run:
|
||||||
timeout: 5m
|
timeout: 5m
|
||||||
@@ -16,17 +19,15 @@ linters:
|
|||||||
- gomodguard_v2
|
- gomodguard_v2
|
||||||
disable:
|
disable:
|
||||||
# Genuinely incompatible with project patterns
|
# Genuinely incompatible with project patterns
|
||||||
- exhaustruct # Requires all struct fields
|
- exhaustruct_v5 # Requires all struct fields
|
||||||
- exhaustruct_v5 # Requires all struct fields (successor to exhaustruct)
|
|
||||||
- godot # Requires comments to end with periods
|
- godot # Requires comments to end with periods
|
||||||
- wrapcheck # Too verbose for internal packages
|
- wrapcheck # Too verbose for internal packages
|
||||||
- varnamelen # Short names like db, id are idiomatic Go
|
- varnamelen # Short names like db, id are idiomatic Go
|
||||||
# Deprecated: the warning is attached to the old name, so it is
|
# Deprecated: the warning is attached to the old name, so it is
|
||||||
# silenced by disabling that name, not by enabling the successor.
|
# silenced by disabling that name, not by enabling the successor.
|
||||||
|
- exhaustruct # Deprecated, replaced by exhaustruct_v5
|
||||||
- wsl # Deprecated, replaced by wsl_v5
|
- wsl # Deprecated, replaced by wsl_v5
|
||||||
- gomodguard # Deprecated, replaced by gomodguard_v2
|
- gomodguard # Deprecated, replaced by gomodguard_v2
|
||||||
# Misses findings at random in v2.14.0; back once a pinned release fixes it
|
|
||||||
- canonicalheader
|
|
||||||
settings:
|
settings:
|
||||||
lll:
|
lll:
|
||||||
line-length: 88
|
line-length: 88
|
||||||
@@ -42,7 +43,10 @@ linters:
|
|||||||
# test-support package exists to hand a test privileges the program
|
# test-support package exists to hand a test privileges the program
|
||||||
# itself must never have, so a file that is not a test must not import
|
# itself must never have, so a file that is not a test must not import
|
||||||
# one. Test files, and the files inside a package whose directory name
|
# one. Test files, and the files inside a package whose directory name
|
||||||
# ends in `test`, are where that code belongs, and are exempt.
|
# ends in `test`, are where that code belongs, and are exempt. A package
|
||||||
|
# in a subdirectory of that directory is not exempt. `${base-path}` is
|
||||||
|
# the directory holding this file, so the name of the directory a
|
||||||
|
# repository is cloned into does not count.
|
||||||
#
|
#
|
||||||
# The deny list below is the one part of this file a repository is
|
# The deny list below is the one part of this file a repository is
|
||||||
# expected to extend, and the only part it may. depguard matches an
|
# expected to extend, and the only part it may. depguard matches an
|
||||||
@@ -57,24 +61,25 @@ linters:
|
|||||||
files:
|
files:
|
||||||
- "$all"
|
- "$all"
|
||||||
- "!$test"
|
- "!$test"
|
||||||
- "!**/*test/**"
|
- "!${base-path}**/*test/*"
|
||||||
deny:
|
deny:
|
||||||
- pkg: net/http/httptest
|
- pkg: net/http/httptest
|
||||||
desc: >-
|
desc: >-
|
||||||
Test-support code belongs in test files and in packages whose
|
Test-support code belongs in test files and in packages whose
|
||||||
directory name ends in test, not in the shipped binary.
|
directory name ends in test, not in the shipped binary.
|
||||||
# Only decisions already recorded in the Go package defaults are
|
# Each entry names a module not to use and what to use instead. Every
|
||||||
# listed here. Every entry matches the module path exactly.
|
# entry matches the module path exactly.
|
||||||
gomodguard_v2:
|
gomodguard_v2:
|
||||||
blocked:
|
blocked:
|
||||||
- module: github.com/rs/zerolog
|
- module: github.com/rs/zerolog
|
||||||
recommendations:
|
recommendations:
|
||||||
- log/slog
|
- log/slog
|
||||||
reason: "Structured logging is stdlib log/slog."
|
reason: "Structured logging is stdlib log/slog."
|
||||||
# One entry per pre-fork module path, because the later releases
|
# These entries cover only the github.com/go-redis/redis module paths,
|
||||||
# are separate paths. A prefix match would be shorter but would
|
# one entry per path, because the later releases are separate paths.
|
||||||
# also reach github.com/go-redis/redismock, the test double for
|
# A prefix match would be shorter but would also reach
|
||||||
# the successor these entries recommend.
|
# github.com/go-redis/redismock/v9, the test double for the successor
|
||||||
|
# these entries recommend.
|
||||||
- module: github.com/go-redis/redis
|
- module: github.com/go-redis/redis
|
||||||
recommendations:
|
recommendations:
|
||||||
- github.com/redis/go-redis/v9
|
- github.com/redis/go-redis/v9
|
||||||
@@ -87,6 +92,10 @@ linters:
|
|||||||
recommendations:
|
recommendations:
|
||||||
- github.com/redis/go-redis/v9
|
- github.com/redis/go-redis/v9
|
||||||
reason: "Pre-fork module; use the maintained go-redis v9."
|
reason: "Pre-fork module; use the maintained go-redis v9."
|
||||||
|
- module: github.com/go-redis/redis/v9
|
||||||
|
recommendations:
|
||||||
|
- github.com/redis/go-redis/v9
|
||||||
|
reason: "Pre-fork module; use the maintained go-redis v9."
|
||||||
- module: github.com/sergi/go-diff
|
- module: github.com/sergi/go-diff
|
||||||
recommendations:
|
recommendations:
|
||||||
- github.com/aymanbagabas/go-udiff
|
- github.com/aymanbagabas/go-udiff
|
||||||
@@ -110,3 +119,4 @@ linters:
|
|||||||
issues:
|
issues:
|
||||||
max-issues-per-linter: 0
|
max-issues-per-linter: 0
|
||||||
max-same-issues: 0
|
max-same-issues: 0
|
||||||
|
uniq-by-line: false
|
||||||
@@ -21,6 +21,36 @@ fmt-check, and commit.
|
|||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
|
- 2026-11-03: The canonical golangci-lint is now v2.15.0, still built with
|
||||||
|
go1.27.0, so the `go` directive rule is unchanged (issue 142). Repositories
|
||||||
|
pick this up on their next re-vendor. Each item in the canonical
|
||||||
|
`.golangci.yml` was tried on a scratch module. These changed:
|
||||||
|
- `canonicalheader` is enabled again, because v2.15.0 fixes the random
|
||||||
|
misses behind issue 105.
|
||||||
|
- The `depguard` exemption covers only the files directly inside a directory
|
||||||
|
whose name ends in `test`. It used to reach every directory below that one
|
||||||
|
too. The name of the directory a repository is cloned into no longer
|
||||||
|
counts.
|
||||||
|
- `gomodguard_v2` also blocks `github.com/go-redis/redis/v9`, whose
|
||||||
|
pre-releases can still be imported under that path.
|
||||||
|
- `uniq-by-line` is now `false`, so a line that trips two linters reports
|
||||||
|
both findings.
|
||||||
|
- Three comments are corrected:
|
||||||
|
- `exhaustruct` is listed as deprecated.
|
||||||
|
- The test double is named `github.com/go-redis/redismock/v9`.
|
||||||
|
- The claim that every blocked module is in the Go package defaults is
|
||||||
|
gone.
|
||||||
|
- A comment says the file has no `formatters` section, so
|
||||||
|
`golangci-lint run` does not run `gofmt`.
|
||||||
|
- 2026-11-03: A package from the distribution's own package index now needs no
|
||||||
|
version and no hash, and pulling that index is allowed
|
||||||
|
(https://git.eeqj.de/sneak/prompts/issues/72), on sneak's answer at
|
||||||
|
https://git.eeqj.de/sneak/prompts/issues/72#issuecomment-165196. The
|
||||||
|
distribution is the pinned base image's in a `Dockerfile` and the host's on a
|
||||||
|
host. It is trusted, and everything else stays pinned by hash. A package
|
||||||
|
source that a `Dockerfile` adds itself does not get the exception. The pinning
|
||||||
|
rule of `REPO_POLICIES.md` and both checklists say so, and the canonical Go
|
||||||
|
`Dockerfile`'s `apk add` line has a comment saying why it is allowed.
|
||||||
- 2026-11-03: A first test run that timed out now gets no verbose rerun
|
- 2026-11-03: A first test run that timed out now gets no verbose rerun
|
||||||
(https://git.eeqj.de/sneak/prompts/issues/61), on sneak's approval at
|
(https://git.eeqj.de/sneak/prompts/issues/61), on sneak's approval at
|
||||||
https://git.eeqj.de/sneak/prompts/issues/61#issuecomment-165195. The Go recipe
|
https://git.eeqj.de/sneak/prompts/issues/61#issuecomment-165195. The Go recipe
|
||||||
|
|||||||
@@ -216,7 +216,12 @@ with your task.
|
|||||||
- [ ] Pre-commit hook is installed (`make hooks`)
|
- [ ] Pre-commit hook is installed (`make hooks`)
|
||||||
- [ ] No secrets in the repo (`.env`, keys, credentials)
|
- [ ] No secrets in the repo (`.env`, keys, credentials)
|
||||||
- [ ] No mutable references in Dockerfiles or scripts (tags, `@latest`) — all
|
- [ ] No mutable references in Dockerfiles or scripts (tags, `@latest`) — all
|
||||||
pinned by cryptographic hash with version/date comment
|
pinned by cryptographic hash with version/date comment. The one exception
|
||||||
|
is a package from the distribution's own package index, which needs no
|
||||||
|
version and no hash. Pulling that index is also allowed. In a
|
||||||
|
`Dockerfile`, the distribution is the pinned base image's. On a host, it
|
||||||
|
is the host's. A package source that a `Dockerfile` adds itself does not
|
||||||
|
get this exception
|
||||||
- [ ] Using `yarn`, not `npm` (JS projects)
|
- [ ] Using `yarn`, not `npm` (JS projects)
|
||||||
|
|
||||||
# Directory Structure
|
# Directory Structure
|
||||||
|
|||||||
@@ -243,7 +243,11 @@ are thin shims calling them. Model scripts:
|
|||||||
final stage is missing its `COPY --from=` edge to the gate phases.
|
final stage is missing its `COPY --from=` edge to the gate phases.
|
||||||
- [ ] No secrets in repo, and none in the build context: enumerate a probe image
|
- [ ] No secrets in repo, and none in the build context: enumerate a probe image
|
||||||
rather than reading `.dockerignore`
|
rather than reading `.dockerignore`
|
||||||
- [ ] No mutable image/package references
|
- [ ] No mutable image/package references. The one exception is a package from
|
||||||
|
the distribution's own package index, which needs no version and no hash.
|
||||||
|
Pulling that index is also allowed. In a `Dockerfile`, the distribution is
|
||||||
|
the pinned base image's. On a host, it is the host's. A package source
|
||||||
|
that a `Dockerfile` adds itself does not get this exception
|
||||||
- [ ] No unnecessary files in repo root
|
- [ ] No unnecessary files in repo root
|
||||||
- [ ] All dates written as YYYY-MM-DD
|
- [ ] All dates written as YYYY-MM-DD
|
||||||
|
|
||||||
|
|||||||
+39
-21
@@ -20,19 +20,36 @@ style conventions are in separate documents:
|
|||||||
`last_modified: YYYY-MM-DD` in the YAML front matter so it can be kept in sync
|
`last_modified: YYYY-MM-DD` in the YAML front matter so it can be kept in sync
|
||||||
with the authoritative source as policies evolve.
|
with the authoritative source as policies evolve.
|
||||||
|
|
||||||
- **ALL external references must be pinned by cryptographic hash.** This
|
- **External references must be pinned by cryptographic hash.** This includes
|
||||||
includes Docker base images, Go modules, npm packages, GitHub Actions, and
|
Docker base images, Go modules, npm packages, GitHub Actions, and anything
|
||||||
anything else fetched from a remote source. Version tags (`@v4`, `@latest`,
|
else fetched from a remote source. Version tags (`@v4`, `@latest`, `:3.21`,
|
||||||
`:3.21`, etc.) are server-mutable and therefore remote code execution
|
etc.) are server-mutable and therefore remote code execution vulnerabilities.
|
||||||
vulnerabilities. The ONLY acceptable way to reference an external dependency
|
Reference an external dependency by its content hash (Docker `@sha256:...`, Go
|
||||||
is by its content hash (Docker `@sha256:...`, Go module hash in `go.sum`, npm
|
module hash in `go.sum`, npm integrity hash in lockfile, GitHub Actions
|
||||||
integrity hash in lockfile, GitHub Actions `@<commit-sha>`). No exceptions.
|
`@<commit-sha>`). This also means never `curl | bash` to install tools like
|
||||||
This also means never `curl | bash` to install tools like pyenv, nvm, rustup,
|
pyenv, nvm, rustup, etc. Instead, download a specific release archive from
|
||||||
etc. Instead, download a specific release archive from GitHub, verify its hash
|
GitHub, verify its hash (hardcoded in the Dockerfile or script), and only then
|
||||||
(hardcoded in the Dockerfile or script), and only then install. Unverified
|
install. Unverified install scripts are arbitrary remote code execution. This
|
||||||
install scripts are arbitrary remote code execution. This is the single most
|
is the single most important rule in this document. Double-check every
|
||||||
important rule in this document. Double-check every external reference in
|
external reference in every file before committing.
|
||||||
every file before committing. There are zero exceptions to this rule.
|
|
||||||
|
There is one exception: a package from the distribution's own package index
|
||||||
|
needs no version and no hash. Pulling that index is also allowed. The
|
||||||
|
distribution is trusted. In a `Dockerfile`, it is the pinned base image's
|
||||||
|
distribution. On a host, it is the host's. These commands are examples:
|
||||||
|
- `apt-get update`
|
||||||
|
- `apt-get install`
|
||||||
|
- `apk update`
|
||||||
|
- `apk add`
|
||||||
|
|
||||||
|
These are not trusted, so everything from them stays pinned by hash:
|
||||||
|
- Docker Hub
|
||||||
|
- PyPI
|
||||||
|
- npm
|
||||||
|
- `go get`
|
||||||
|
|
||||||
|
A package source that a `Dockerfile` adds itself is not the distribution's
|
||||||
|
own, so the exception does not cover it.
|
||||||
|
|
||||||
- Every repo with software must have a root `Makefile` with these targets:
|
- Every repo with software must have a root `Makefile` with these targets:
|
||||||
`make bootstrap`, `make setup`, `make test`, `make lint`, `make fmt` (writes),
|
`make bootstrap`, `make setup`, `make test`, `make lint`, `make fmt` (writes),
|
||||||
@@ -259,6 +276,8 @@ style conventions are in separate documents:
|
|||||||
# run unless lint and test passed.
|
# run unless lint and test passed.
|
||||||
# golang:1.x-alpine, YYYY-MM-DD
|
# golang:1.x-alpine, YYYY-MM-DD
|
||||||
FROM golang@sha256:... AS builder
|
FROM golang@sha256:... AS builder
|
||||||
|
# git comes from the base image's own distribution package index, which
|
||||||
|
# is trusted, so it needs no version and no hash.
|
||||||
RUN apk add --no-cache git
|
RUN apk add --no-cache git
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
@@ -394,11 +413,10 @@ style conventions are in separate documents:
|
|||||||
`Pipfile.lock`. It installs no Python there: the tests use the base
|
`Pipfile.lock`. It installs no Python there: the tests use the base
|
||||||
image's Python, which the image's hash pins. If it installs anything else
|
image's Python, which the image's hash pins. If it installs anything else
|
||||||
there, the step goes after `ARG CACHEBUST`.
|
there, the step goes after `ARG CACHEBUST`.
|
||||||
- Every external reference must be pinned by hash, so `script/bootstrap`
|
- PyPI is not trusted, so `script/bootstrap` installs pipenv and its
|
||||||
installs pipenv and its dependencies by hash. It does so with
|
dependencies by hash. It does so with `pip install --require-hashes -r`
|
||||||
`pip install --require-hashes -r` and a requirements file in `script/`
|
and a requirements file in `script/` that lists each of them with `==` and
|
||||||
that lists each of them with `==` and its `--hash`. pip refuses to install
|
its `--hash`. pip refuses to install a dependency the file does not list.
|
||||||
a dependency the file does not list.
|
|
||||||
- It then runs `pipenv install --deploy`, with `--dev` when the tests need
|
- It then runs `pipenv install --deploy`, with `--dev` when the tests need
|
||||||
the development packages. `--deploy` installs only what `Pipfile.lock`
|
the development packages. `--deploy` installs only what `Pipfile.lock`
|
||||||
names, checks every package against the lockfile's hashes, and fails when
|
names, checks every package against the lockfile's hashes, and fails when
|
||||||
@@ -698,10 +716,10 @@ style conventions are in separate documents:
|
|||||||
`test-support` depguard rule, where a repo names its own test-support packages
|
`test-support` depguard rule, where a repo names its own test-support packages
|
||||||
by full import path. A repo adds entries there and changes nothing else, and a
|
by full import path. A repo adds entries there and changes nothing else, and a
|
||||||
re-vendor carries its entries forward. The canonical golangci-lint version is
|
re-vendor carries its entries forward. The canonical golangci-lint version is
|
||||||
v2.14.0 (released 2026-09-24), pinned as the digest of the lint phase's base
|
v2.15.0 (released 2026-10-16), pinned as the digest of the lint phase's base
|
||||||
image
|
image
|
||||||
(`golangci/golangci-lint@sha256:ad862ba6b3798cbe0fd9fd7408d498fd74fbd2623a92406b2fd3898faf0bf98f`,
|
(`golangci/golangci-lint@sha256:fbfcfd12a6f8d7f1b97b3362ca80fc2a244d46863148c73cb88e7793af96c481`,
|
||||||
which reports `2.14.0 built with go1.27.0 from 114493f9`). A module's `go`
|
which reports `2.15.0 built with go1.27.0 from 25c5369a`). A module's `go`
|
||||||
directive must not name a newer Go minor version than the one golangci-lint
|
directive must not name a newer Go minor version than the one golangci-lint
|
||||||
was built with, or golangci-lint refuses to lint it: this release lints
|
was built with, or golangci-lint refuses to lint it: this release lints
|
||||||
`go 1.27.1` but not `go 1.28`. That digest is the only pin, since no repo
|
`go 1.27.1` but not `go 1.28`. That digest is the only pin, since no repo
|
||||||
|
|||||||
Reference in new issue
Block a user