security: verify Hugo binary checksum after download #162

Closed
opened 2026-05-23 08:55:41 +00:00 by guettlibot · 0 comments
guettlibot commented 2026-05-23 08:55:41 +00:00 (Migrated from codeberg.org)

Problem

The website build container downloads Hugo at runtime with no integrity check (ci/main.go ~line 314):

```go
WithExec([]string{"curl", "-sL",
"https://github.com/gohugoio/hugo/releases/download/v0.152.2/hugo_extended_0.152.2_linux-amd64.tar.gz",
"-o", "/tmp/hugo.tar.gz"}).
```

If the release artifact at that URL is replaced (compromised GitHub release, CDN substitution, or network-level MITM), an arbitrary binary runs with access to the deploy SSH key. Hugo is used inside the container that then deploys to the production server via the SSH key.

The tag `v0.152.2` is not immutable — GitHub allows deleting and recreating releases/tags.

Fix

Add a SHA-256 check immediately after the download. The checksum is published by the Hugo project at the same release URL:

```
https://github.com/gohugoio/hugo/releases/download/v0.152.2/hugo_extended_0.152.2_checksums.txt
```

```go
// After the curl step:
WithExec([]string{"sh", "-c",
"echo 'EXPECTED_SHA256 /tmp/hugo.tar.gz' | sha256sum -c -"}).
```

Get the expected SHA-256 by running (on a trusted machine):
```
curl -sL https://github.com/gohugoio/hugo/releases/download/v0.152.2/hugo_extended_0.152.2_checksums.txt
| grep linux-amd64.tar.gz
```

Hardcode the hash in ci/main.go next to the download URL so they stay in sync during version bumps.

## Problem The website build container downloads Hugo at runtime with no integrity check (ci/main.go ~line 314): \`\`\`go WithExec([]string{"curl", "-sL", "https://github.com/gohugoio/hugo/releases/download/v0.152.2/hugo_extended_0.152.2_linux-amd64.tar.gz", "-o", "/tmp/hugo.tar.gz"}). \`\`\` If the release artifact at that URL is replaced (compromised GitHub release, CDN substitution, or network-level MITM), an arbitrary binary runs with access to the deploy SSH key. Hugo is used inside the container that then deploys to the production server via the SSH key. The tag \`v0.152.2\` is not immutable — GitHub allows deleting and recreating releases/tags. ## Fix Add a SHA-256 check immediately after the download. The checksum is published by the Hugo project at the same release URL: \`\`\` https://github.com/gohugoio/hugo/releases/download/v0.152.2/hugo_extended_0.152.2_checksums.txt \`\`\` \`\`\`go // After the curl step: WithExec([]string{"sh", "-c", "echo 'EXPECTED_SHA256 /tmp/hugo.tar.gz' | sha256sum -c -"}). \`\`\` Get the expected SHA-256 by running (on a trusted machine): \`\`\` curl -sL https://github.com/gohugoio/hugo/releases/download/v0.152.2/hugo_extended_0.152.2_checksums.txt \ | grep linux-amd64.tar.gz \`\`\` Hardcode the hash in ci/main.go next to the download URL so they stay in sync during version bumps.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: guettli/sharedinbox#162