[Bug 2150614] [NEW] release-upgrade to 26.04 truncates inline Signed-By GPG keys in deb822 .sources files when continuation contains a space-only blank line

Bernd Wahlen 2150614 at bugs.launchpad.net
Wed Apr 29 07:30:53 UTC 2026


Public bug reported:

**Package:** ubuntu-release-upgrader
**Affects:** Ubuntu 26.04 (Resolute Raccoon) — release-upgrade from 25.10 (Questing)

## Summary

When `do-release-upgrade` rewrites `/etc/apt/sources.list.d/*.sources`
files (to add `Enabled: no` to third-party sources for the upgrade), the
rewriter does not preserve a multi-line `Signed-By:` value whose
continuation block contains an empty line encoded as a single space (`"
\n"`). It treats that line as the end of the field, discards the rest of
the inline ASCII-armored key, and writes back a corrupted record.

The result is a `.sources` file containing only:

```
Signed-By: -----BEGIN PGP PUBLIC KEY BLOCK-----
Enabled: no
```

— no key body, no END marker. After re-enabling such a source post-
upgrade, `apt update` fails because the key is gone.

`apt` itself parses the original file fine, so this is a regression in
the rewriter, not a hardening of a previously-tolerated form.

## Root cause (precise)

In deb822, a blank line inside a multi-line value is conventionally
encoded as `" .\n"` (single space + dot + newline). Some files in the
wild instead use `" \n"` (single space + newline). `apt`'s deb822 parser
accepts both.

The rewriter used by `do-release-upgrade` accepts only the dotted form:

| Continuation form | apt parses | rewriter preserves |
|---|---|---|
| `" .\n"` (space-dot)  | yes | yes |
| `" \n"` (space-only)  | yes | **no — truncates field here** |

When the rewriter hits the space-only line, it stops reading the
`Signed-By:` value, drops everything after (including the rest of the
armored key and the `-----END PGP PUBLIC KEY BLOCK-----` marker), then
appends `Enabled: no`.

## Reproducer

Three `.sources` files placed in `/etc/apt/sources.list.d/` before `do-
release-upgrade` 25.10 → 26.04, then compared after.

### Case A — openvox8.sources (BROKEN: space-only blank line)

**Before** (`hexdump -C` of the relevant region shows `0a 20 0a` —
newline, space, newline):

```
Types: deb
URIs: https://apt.voxpupuli.org
Suites: ubuntu25.04
Components: openvox8
Signed-By:
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 
 mQENBGeGidcBCADjJzn2Mh7E7guNotcwRh1vvKQkQrw/TYY+xuKA2DGOvMrVYzyn
 [... ~30 lines of key body ...]
 -----END PGP PUBLIC KEY BLOCK-----
```

(Line 7 is a single space followed by `\n`.)

**After release-upgrade:**

```
Types: deb
URIs: https://apt.voxpupuli.org
Suites: ubuntu25.04
Components: openvox8
Signed-By: -----BEGIN PGP PUBLIC KEY BLOCK-----
Enabled: no
```

The entire key body and the END marker are gone.

### Case B — git-core.sources (PRESERVED: space-dot blank line)

**Before:**

```
Types: deb
URIs: https://ppa.launchpadcontent.net/git-core/ppa/ubuntu/
Suites: questing
Components: main
Signed-By: 
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 .
 mQINBGYo2OYBEADVRjI+o29u9izslaVr0Xqj8hpmo/2su/Iey1PgoS6A3hMxR4R4
 [...]
 -----END PGP PUBLIC KEY BLOCK-----
```

**After:**

```
Types: deb
URIs: https://ppa.launchpadcontent.net/git-core/ppa/ubuntu/
Suites: questing
Components: main
Signed-By: -----BEGIN PGP PUBLIC KEY BLOCK-----
 .
 mQINBGYo2OYBEADVRjI+o29u9izslaVr0Xqj8hpmo/2su/Iey1PgoS6A3hMxR4R4
 [...]
 -----END PGP PUBLIC KEY BLOCK-----
Enabled: no
```

Key fully preserved. The only changes are: first key line collapsed onto
the `Signed-By:` line (cosmetic, both forms are valid deb822), and
`Enabled: no` appended.

### Case C — haproxy.sources (PRESERVED: space-dot blank line)

Same shape as Case B — `" .\n"` continuation, key preserved end-to-end
after upgrade, `Enabled: no` appended.

## Diagnosis (byte level)

`od -c` of the broken pre-upgrade file around the `Signed-By:` field:

```
Signed-By:\n
\sp -----BEGIN PGP PUBLIC KEY BLOCK-----\n
\sp \n              ← space-only continuation, this is what trips the rewriter
\sp mQENBGeGidc...\n
```

vs the working files:

```
Signed-By: \n
\sp -----BEGIN PGP PUBLIC KEY BLOCK-----\n
\sp .\n             ← space-dot continuation, parses correctly
\sp mQINBGY...\n
```

`apt-get update` against the original openvox8 file (pre-upgrade)
succeeds — confirming `apt`'s own parser accepts both continuation
forms. The bug is in the upgrader's parser/rewriter only.

## Expected behaviour

The rewriter should either:

1. Accept `" \n"` as a continuation line (matching `apt`'s own behaviour), and re-emit it as `" .\n"` on write, or
2. Refuse to rewrite the file and leave it untouched, logging a warning, rather than silently writing a corrupted version (in my opinion its generally a bad idea to insert that line to disable. better move to some disabled folder)

Silently truncating the inline key and writing back an unusable
`.sources` file is the worst outcome — `Enabled: no` masks the
corruption until the user re-enables the source after upgrade, at which
point `apt update` fails with a key error and the original key material
is no longer recoverable from the file.

## Suggested severity

Medium. Affects anyone who has a third-party `.sources` file with an
inline armored key generated by tooling that emits the space-only blank-
line form. The damage is silent during upgrade and only surfaces when
the user re-enables sources afterwards. Original key recovery requires
going back to the upstream repo's documentation.

## Test files

Full pre/post pairs available on request — clean minimal reproducer,
four files each side, ~30 lines per file.

** Affects: ubuntu-release-upgrader (Ubuntu)
     Importance: Undecided
         Status: New

-- 
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to ubuntu-release-upgrader in
Ubuntu.
https://bugs.launchpad.net/bugs/2150614

Title:
  release-upgrade to 26.04 truncates inline Signed-By GPG keys in deb822
  .sources files when continuation contains a space-only blank line

Status in ubuntu-release-upgrader package in Ubuntu:
  New

Bug description:
  **Package:** ubuntu-release-upgrader
  **Affects:** Ubuntu 26.04 (Resolute Raccoon) — release-upgrade from 25.10 (Questing)

  ## Summary

  When `do-release-upgrade` rewrites `/etc/apt/sources.list.d/*.sources`
  files (to add `Enabled: no` to third-party sources for the upgrade),
  the rewriter does not preserve a multi-line `Signed-By:` value whose
  continuation block contains an empty line encoded as a single space
  (`" \n"`). It treats that line as the end of the field, discards the
  rest of the inline ASCII-armored key, and writes back a corrupted
  record.

  The result is a `.sources` file containing only:

  ```
  Signed-By: -----BEGIN PGP PUBLIC KEY BLOCK-----
  Enabled: no
  ```

  — no key body, no END marker. After re-enabling such a source post-
  upgrade, `apt update` fails because the key is gone.

  `apt` itself parses the original file fine, so this is a regression in
  the rewriter, not a hardening of a previously-tolerated form.

  ## Root cause (precise)

  In deb822, a blank line inside a multi-line value is conventionally
  encoded as `" .\n"` (single space + dot + newline). Some files in the
  wild instead use `" \n"` (single space + newline). `apt`'s deb822
  parser accepts both.

  The rewriter used by `do-release-upgrade` accepts only the dotted
  form:

  | Continuation form | apt parses | rewriter preserves |
  |---|---|---|
  | `" .\n"` (space-dot)  | yes | yes |
  | `" \n"` (space-only)  | yes | **no — truncates field here** |

  When the rewriter hits the space-only line, it stops reading the
  `Signed-By:` value, drops everything after (including the rest of the
  armored key and the `-----END PGP PUBLIC KEY BLOCK-----` marker), then
  appends `Enabled: no`.

  ## Reproducer

  Three `.sources` files placed in `/etc/apt/sources.list.d/` before
  `do-release-upgrade` 25.10 → 26.04, then compared after.

  ### Case A — openvox8.sources (BROKEN: space-only blank line)

  **Before** (`hexdump -C` of the relevant region shows `0a 20 0a` —
  newline, space, newline):

  ```
  Types: deb
  URIs: https://apt.voxpupuli.org
  Suites: ubuntu25.04
  Components: openvox8
  Signed-By:
   -----BEGIN PGP PUBLIC KEY BLOCK-----
   
   mQENBGeGidcBCADjJzn2Mh7E7guNotcwRh1vvKQkQrw/TYY+xuKA2DGOvMrVYzyn
   [... ~30 lines of key body ...]
   -----END PGP PUBLIC KEY BLOCK-----
  ```

  (Line 7 is a single space followed by `\n`.)

  **After release-upgrade:**

  ```
  Types: deb
  URIs: https://apt.voxpupuli.org
  Suites: ubuntu25.04
  Components: openvox8
  Signed-By: -----BEGIN PGP PUBLIC KEY BLOCK-----
  Enabled: no
  ```

  The entire key body and the END marker are gone.

  ### Case B — git-core.sources (PRESERVED: space-dot blank line)

  **Before:**

  ```
  Types: deb
  URIs: https://ppa.launchpadcontent.net/git-core/ppa/ubuntu/
  Suites: questing
  Components: main
  Signed-By: 
   -----BEGIN PGP PUBLIC KEY BLOCK-----
   .
   mQINBGYo2OYBEADVRjI+o29u9izslaVr0Xqj8hpmo/2su/Iey1PgoS6A3hMxR4R4
   [...]
   -----END PGP PUBLIC KEY BLOCK-----
  ```

  **After:**

  ```
  Types: deb
  URIs: https://ppa.launchpadcontent.net/git-core/ppa/ubuntu/
  Suites: questing
  Components: main
  Signed-By: -----BEGIN PGP PUBLIC KEY BLOCK-----
   .
   mQINBGYo2OYBEADVRjI+o29u9izslaVr0Xqj8hpmo/2su/Iey1PgoS6A3hMxR4R4
   [...]
   -----END PGP PUBLIC KEY BLOCK-----
  Enabled: no
  ```

  Key fully preserved. The only changes are: first key line collapsed
  onto the `Signed-By:` line (cosmetic, both forms are valid deb822),
  and `Enabled: no` appended.

  ### Case C — haproxy.sources (PRESERVED: space-dot blank line)

  Same shape as Case B — `" .\n"` continuation, key preserved end-to-end
  after upgrade, `Enabled: no` appended.

  ## Diagnosis (byte level)

  `od -c` of the broken pre-upgrade file around the `Signed-By:` field:

  ```
  Signed-By:\n
  \sp -----BEGIN PGP PUBLIC KEY BLOCK-----\n
  \sp \n              ← space-only continuation, this is what trips the rewriter
  \sp mQENBGeGidc...\n
  ```

  vs the working files:

  ```
  Signed-By: \n
  \sp -----BEGIN PGP PUBLIC KEY BLOCK-----\n
  \sp .\n             ← space-dot continuation, parses correctly
  \sp mQINBGY...\n
  ```

  `apt-get update` against the original openvox8 file (pre-upgrade)
  succeeds — confirming `apt`'s own parser accepts both continuation
  forms. The bug is in the upgrader's parser/rewriter only.

  ## Expected behaviour

  The rewriter should either:

  1. Accept `" \n"` as a continuation line (matching `apt`'s own behaviour), and re-emit it as `" .\n"` on write, or
  2. Refuse to rewrite the file and leave it untouched, logging a warning, rather than silently writing a corrupted version (in my opinion its generally a bad idea to insert that line to disable. better move to some disabled folder)

  Silently truncating the inline key and writing back an unusable
  `.sources` file is the worst outcome — `Enabled: no` masks the
  corruption until the user re-enables the source after upgrade, at
  which point `apt update` fails with a key error and the original key
  material is no longer recoverable from the file.

  ## Suggested severity

  Medium. Affects anyone who has a third-party `.sources` file with an
  inline armored key generated by tooling that emits the space-only
  blank-line form. The damage is silent during upgrade and only surfaces
  when the user re-enables sources afterwards. Original key recovery
  requires going back to the upstream repo's documentation.

  ## Test files

  Full pre/post pairs available on request — clean minimal reproducer,
  four files each side, ~30 lines per file.

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/ubuntu-release-upgrader/+bug/2150614/+subscriptions





More information about the foundations-bugs mailing list