Skip to content

apt: remote repositories are written with [trusted=yes], disabling GPG verification on network sources #784

Description

@planitron

Summary

When Pigsty renders APT source lists, it marks remote repositories as [trusted=yes]. That option tells APT to accept packages from those sources without verifying their signatures.

The result is that a default Pigsty installation fetches and installs packages from the network — including repo.pigsty.io, PGDG and the OS mirrors — with authentication switched off. Any party able to interfere with those transports (a compromised or hijacked mirror, a DNS answer, an intercepting proxy, a plain-HTTP hop) can serve an arbitrary package, and dpkg will execute its maintainer scripts as root at install time.

This is not about the local repository: see "Scope" below.

Scope — 2 of the 6 occurrences are legitimate, 4 are not

I want to be precise, because half of these are fine and should stay as they are.

Legitimate (please keep): the machine-local repository, which is unsigned by construction and reached over no network at all:

{# roles/repo/tasks/build.yml:236 and roles/repo/tasks/main.yml:86 #}
echo "deb [trusted=yes] file:{{ repo_home }}/{{ repo_name }}/ ./" > /etc/apt/sources.list.d/pigsty-local.list

The actual issue — remote sources:

{# roles/repo/tasks/build.yml:83 and :85 #}
deb [trusted=yes] {{ repo.baseurl[region] | replace('${admin_ip}', admin_ip) | ... }}
deb [trusted=yes] {{ repo.baseurl.default | replace('${admin_ip}', admin_ip) | ... }}
{# roles/node/tasks/pkg.yml:60 and :62 — same pattern #}
deb [trusted=yes] {{ repo.baseurl[region] | ... }}
deb [trusted=yes] {{ repo.baseurl.default | ... }}

repo.baseurl here resolves to upstream network endpoints, so GPG verification is disabled on exactly the sources where it matters most.

Environment

Pigsty v4.4.0 and v4.5.0 (unchanged between the two tags)
OS Ubuntu 24.04 LTS
Files roles/repo/tasks/build.yml, roles/repo/tasks/main.yml, roles/node/tasks/pkg.yml

Occurrence counts are identical in both tags (build.yml: 3, main.yml: 1, pkg.yml: 2).

Why the fix is known to work

Pigsty already installs the keyrings it needs/etc/apt/keyrings/pigsty.gpg and /etc/apt/keyrings/pgdg.gpg are present on a stock install, and the OS keyring ships with the distribution. The signing material is therefore in place; only the reference to it is missing from the rendered source lines.

The Pigsty repositories themselves do publish signed indexes. #673 shows a user hitting NO_PUBKEY E7935D8DB9BD8B20 on repo.pigsty.cc/apt/infra and /apt/pgsql — an error that can only occur when APT is verifying signatures. So the signing material exists on both ends: the repository signs, the keyring is installed, and only the rendered source line tells APT to skip the check.

I have been running a Pigsty node for two months with every remote repository rewritten by hand from [trusted=yes] to [signed-by=…], across repo.pigsty.io, PGDG, the OS mirrors and one third-party repo. Package installation, upgrades and repository refreshes all behave normally — including the Pigsty-built packages. So this is not a theoretical hardening request: the signed configuration is a working one, it simply is not what Pigsty renders by default.

Suggested fix

Emit signed-by= instead of trusted=yes for remote repositories, pointing at the keyring Pigsty already deploys for that source, e.g.:

deb [signed-by=/etc/apt/keyrings/pigsty.gpg] https://repo.pigsty.io/apt/infra/ generic main

A per-repository key/keyring attribute in the repository definition would let each entry declare its own keyring, with the local file: repository keeping trusted=yes since it has no signature to verify.

If a fully signed default is considered too disruptive for existing offline or air-gapped setups, exposing it as a variable (defaulting to the current behaviour) would already let operators opt into verified sources without patching the roles — which is what has to be done today, and re-done after every version bump.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions