Snap cataloger doesn't follow default channels
- Dominant language
- Go
- Stars
- 9.6k
- Forks
- 954
- Avg merge
- 23h 27m
- Merged PRs (30d)
- 48
Description
**What happened**:
Snaps that have no revisions published in the `stable` or `latest/stable` (or other 'default') tracks/channels are not found by syft. The snap exists, is available in my region for my architecture, and can be installed via `snap install` and downloaded via `snap download`, but `syft snap:$(snapname)` fails to download the snap.
**What you expected to happen**:
Syft should follow the same path to get from the specified (or default) `stable` or `latest/stable` channel to whichever is the 'default' channel for the application.
**Steps to reproduce the issue**:
Use syft to generate an SBOM for the `openstack` snap.
```bash
syft snap:openstack
[0000] ERROR could not determine source: errors occurred attempting to resolve 'openstack':
- snap: snap file "openstack" does not exist
- snap: no matching snap found for openstack@stable (amd64)
```
Specifying the track/channel explicitly works:
```
syft snap:openstack@2024.1/stable -o syft-json=openstack.json
✔ Downloaded snap openstack@2024.1/stable (amd64)
✔ Indexed file system f6rE7kIZIe7ZypsQE4xkBst7yLGKQ11A_783.snap
✔ Cataloged contents 156d269f5b5c1fe7b2b8991f27a0c5ac5b0eace99055ec088e6cd3ca9d780767
├── ✔ Packages [367 packages]
├── ✔ Executables [160 executables]
├── ✔ File metadata [574 locations]
└── ✔ File digests [574 files]
```
I believe that I shouldn't _need_ to do that. Syft should behave like `snap` does, pulling the default.
**Anything else we need to know?**:
Documentation: https://snapcraft.io/docs/channels
Snaps can be published to tracks, risks, and branches. The format is: `//`, so a valid command might be `snap install mysnap --channel 6.0/candidate/fix-bug-123`, but more often `snap install mysnap --channel latest/stable`, `snap install mysnap --channel stable` or even just `snap install mysnap` - which typically defaults to `stable` or `latest/stable`.
**However**: It's also possible to have a bunch of tracks and not actually publish to the default `latest` track. As I understand it, the `snap` command line tool (or the store, or something in between) decides that `snap install openstack` means `snap install openstack --channel latest/stable`, but as there is no `latest` track, the user ends up effectively getting the result of `snap install openstack --channel 2024.1/stable`. Thus:
```
$ snap install openstack
Download snap "openstack" (783) from channel "2024.1/stable"
```
Here's the channel map for the openstack snap:
```
name: openstack
summary: Your own enterprise-grade cloud platform
publisher: Canonical✓
store-url: https://snapcraft.io/openstack
contact: https://matrix.to/#/#openstack-sunbeam:ubuntu.com
...
base: core24
snap-id: f6rE7kIZIe7ZypsQE4xkBst7yLGKQ11A
channels:
2024.1/stable: 2024.1 2025-08-21 (783) 165MB -
2024.1/candidate: 2024.1 2025-10-31 (828) 165MB -
2024.1/beta: 2024.1 2025-09-17 (796) 179MB -
2024.1/edge: 2024.1 2025-12-12 (854) 180MB -
yoga/stable: –
yoga/candidate: –
yoga/beta: –
yoga/edge: yoga 2023-05-31 (133) 92MB -
2025.1/stable: –
2025.1/candidate: –
2025.1/beta: –
2025.1/edge: 2024.1 2025-12-12 (854) 180MB -
2023.2/stable: 2023.2 2023-12-06 (335) 153MB -
2023.2/candidate: 2023.2 2024-05-24 (509) 133MB -
2023.2/beta: ↑
2023.2/edge: 2023.2 2024-05-24 (510) 132MB -
2023.1/stable: 2023.1 2023-11-13 (324) 135MB -
2023.1/candidate: 2023.1 2024-01-12 (352) 153MB -
2023.1/beta: ↑
2023.1/edge: 2023.1 2024-01-12 (354) 153MB -
```
Log:
```
syft -vvv snap:openstack
[0000] INFO syft version: 1.38.2
[0000] DEBUG config:
log:
quiet: false
level: trace
file: ""
dev:
profile: none
config: ""
output:
- syft-table
format:
pretty: null
template:
path: ""
legacy: false
json:
legacy: false
pretty: false
spdx-json:
pretty: false
cyclonedx-json:
pretty: false
cyclonedx-xml:
pretty: false
check-for-app-update: true
default-catalogers: []
select-catalogers: []
package:
search-unindexed-archives: false
search-indexed-archives: true
exclude-binary-overlap-by-ownership: true
license:
content: none
coverage: 75
file:
metadata:
selection: owned-by-package
digests:
- sha1
- sha256
content:
skip-files-above-size: 256000
globs: []
executable:
globs: []
scope: squashed
parallelism: 0
relationships:
package-file-ownership: true
package-file-ownership-overlap: true
compliance:
missing-name: drop
missing-version: stub
enrich: []
dotnet:
dep-packages-must-have-dll: false
dep-packages-must-claim-dll: true
propagate-dll-claims-to-parents: true
relax-dll-claims-when-bundling-detected: true
golang:
search-local-mod-cache-licenses: null
local-mod-cache-dir: /home/alan/go/pkg/mod
search-local-vendor-licenses: null
local-vendor-dir: ""
search-remote-licenses: null
proxy: https://proxy.golang.org,direct
no-proxy: ""
main-module-version:
from-ld-flags: true
from-contents: false
from-build-settings: true
java:
use-network: null
use-maven-local-repository: null
maven-local-repository-dir: /home/alan/.m2/repository
maven-url: https://repo1.maven.org/maven2
max-parent-recursive-depth: 0
resolve-transitive-dependencies: false
javascript:
search-remote-licenses: null
npm-base-url: ""
include-dev-dependencies: null
linux-kernel:
catalog-modules: true
nix:
capture-owned-files: false
python:
search-remote-licenses: null
pypi-base-url: ""
guess-unpinned-requirements: null
registry:
insecure-skip-tls-verify: false
insecure-use-http: false
auth: []
ca-cert: ""
from: []
platform: ""
source:
name: ""
version: ""
supplier: ""
source: ""
base-path: ""
file:
digests:
- SHA-256
image:
default-pull-source: ""
max-layer-size: ""
exclude: []
unknowns:
remove-when-packages-defined: true
executables-without-packages: true
unexpanded-archives: true
cache:
dir: /home/alan/.cache/syft
ttl: 7d
[0000] DEBUG checking if a new version of syft is available
[0000] DEBUG no new syft update available
[0000] TRACE looking for matching encoder name=syft-table version=
[0000] TRACE considering format aliases=[json syft] name=syft-json version=16.1.0
[0000] TRACE considering format aliases=[table] name=syft-table version=
[0000] TRACE considering format aliases=[text] name=syft-text version=
[0000] TRACE considering format aliases=[purl] name=purls version=
[0000] TRACE considering format aliases=[github] name=github-json version=
[0000] TRACE considering format aliases=[cyclonedx cyclone cdx] name=cyclonedx-xml version=1.0
[0000] TRACE considering format aliases=[cyclonedx cyclone cdx] name=cyclonedx-xml version=1.1
[0000] TRACE considering format aliases=[cyclonedx cyclone cdx] name=cyclonedx-xml version=1.2
[0000] TRACE considering format aliases=[cyclonedx cyclone cdx] name=cyclonedx-xml version=1.3
[0000] TRACE considering format aliases=[cyclonedx cyclone cdx] name=cyclonedx-xml version=1.4
[0000] TRACE considering format aliases=[cyclonedx cyclone cdx] name=cyclonedx-xml version=1.5
[0000] TRACE considering format aliases=[cyclonedx cyclone cdx] name=cyclonedx-xml version=1.6
[0000] TRACE considering format aliases=[] name=cyclonedx-json version=1.2
[0000] TRACE considering format aliases=[] name=cyclonedx-json version=1.3
[0000] TRACE considering format aliases=[] name=cyclonedx-json version=1.4
[0000] TRACE considering format aliases=[] name=cyclonedx-json version=1.5
[0000] TRACE considering format aliases=[] name=cyclonedx-json version=1.6
[0000] TRACE considering format aliases=[] name=spdx-json version=2.2
[0000] TRACE considering format aliases=[] name=spdx-json version=2.3
[0000] TRACE considering format aliases=[spdx spdx-tv] name=spdx-tag-value version=2.1
[0000] TRACE considering format aliases=[spdx spdx-tv] name=spdx-tag-value version=2.2
[0000] TRACE considering format aliases=[spdx spdx-tv] name=spdx-tag-value version=2.3
[0000] TRACE found matching encoder name=syft-table version=
[0000] TRACE requesting snap info architecture=amd64 channel=stable name=openstack
[0000] TRACE worker stopped component=eventloop
[0000] TRACE signal exit component=eventloop
[0000] ERROR could not determine source: errors occurred attempting to resolve 'openstack':
- snap: snap file "openstack" does not exist
- snap: no matching snap found for openstack@stable (amd64)
```
**Environment**:
- Output of `syft version`:
```
snap version
snap 2.72
snapd 2.72
series 16
ubuntu 24.04
kernel 6.8.0-63-generic
architecture amd64
```
- OS (e.g: `cat /etc/os-release` or similar):
```
cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04.3 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.3 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
```
Contributor guide
Research direction
Start by running `syft snap:openstack` and compare its channel lookup with `snap install openstack`, then trace the Snap cataloger's request from the `snap:openstack` entry point. The change is done when a snap without a `latest/stable` revision resolves through its effective default channel and the existing explicit-channel behavior remains working.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100