Allow packages from the distribution's own package index unpinned (closes #72)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
A package from the distribution's own package index now needs no version and no hash, and pulling that index is allowed, on sneak's answer at #72 (comment). 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. Model: opus-5-5
This commit was merged in pull request #145.
This commit is contained in:
@@ -21,6 +21,15 @@ fmt-check, and commit.
|
|||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
|
- 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
|
||||||
|
|
||||||
|
|||||||
+36
-18
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user