Disabling Syft network calls from the CLI

Hi all,

I’d like to start a discussion about running syft in a fully offline mode — meaning a configuration where syft is guaranteed not to make any outbound network call.

Why I need it

My organization places constraints on outbound traffic from the environments where syft runs. What I need in those cases is a guarantee that this invocation of syft does not talk to the network.

Where I currently see calls happening

As far as I can tell the network-touching paths are independent of each other and each has its own knob, or none:

  • the application update check (SYFT_CHECK_FOR_APP_UPDATE)
    • Can be disabled
  • remote license/enrichment lookups for some ecosystems — see Enabling Syft network features from the CLI
    • Deactivated by default
  • image resolution itself: when a reference isn’t present locally, it gets pulled from the registry.
    • This is the one I care most about and the one the thread above doesn’t cover

What I tried myself

I got reasonably far by constraining things from the outside: pinning the input to explicit local schemes so resolution can’t fall through to a registry, and turning the update check off via the env var. That covers the call sites I know about, but it only works because I know about them — the property lives in how I invoke syft rather than in syft’s own configuration, and I have to re-verify it on every upgrade.

When I looked at making it a real setting, the image-source side is where I got stuck: the pull happens in stereoscope, so there’s no obvious single point in syft where I could enforce “no remote sources” for the whole run without either touching stereoscope as well or scattering checks around. I didn’t see an easy way that felt like it matched the existing design.

Open questions

Mostly I’d like to hear what shape you’d consider acceptable, rather than propose something and have it be wrong:

  • Is this actually a feature / configuration option that you could see in the product?
  • Is a single top-level switch the right model at all — something like --offline / SYFT_OFFLINE=true that makes any operation requiring the network a hard error instead of a fallback? If so, how should it interact with --enrich and the more granular settings; does offline always win regardless of precedence?
  • Or does this belong lower down, as a “no remote sources” option in stereoscope that syft just surfaces? That seems closer to where the behaviour actually lives, but it’s a larger surface.
  • Is “fail loudly” the behaviour you’d want, or would you expect offline to degrade gracefully (skip enrichment, emit a warning) and only hard-fail when the image itself can’t be resolved?

Contributing

I’m happy to contribute hre rather than just file a request.

Two things held me back from opening a PR directly: it looks like it touches both syft and stereoscope, and I wasn’t sure what you’d expect in terms of style and structure across the two repos — and more importantly I didn’t want to build something in a direction that wouldn’t be accepted.

Thanks!

One thing that helped me with similar requirements is enforcing the guarantee at the environment level as well, e.g. running syft against a local directory or OCI archive inside a container started with --network none (or an empty network namespace). Then any unexpected network call fails loudly instead of silently succeeding, and you can re-run that check in CI after each syft upgrade. It doesn’t replace a proper --offline switch, but it makes the regression you mention easy to catch. Have you seen whether the update check still attempts a connection when SYFT_CHECK_FOR_APP_UPDATE=false is set?

Thanks for the answer!

That’s my go to so far as well. Saving the image as a docker archive and then ingesting it into syft.

However that results in giving up on all the logic inside syft that’s related to resolving and querying the different local daemons.

Regarding the last question: I didn’t notice syft attempting an update connection when SYFT_CHECK_FOR_APP_UPDATE=false is set.

I’m not sure what you mean here. It sounds like you don’t want Syft to make outgoing network calls, but you do want Syft to do work to figure out which services on the box already have the image cached? That sounds to me like you’re fetching the image for Syft but then not telling Syft where it is.

I think you’re right that this is a missing config option today; it would have to be something like, “ask podman, docker, local fs about , but don’t pull anything and don’t use the registry client”. This is further complicated because asking the docker daemon for an image will cause the daemon to pull it if it’s not available locally, though that’s not Syft doing a network call so maybe that’s ok for your setup?

I’m curious what the actual setup would be though. It sounds like you want to guarantee that the image is locally available on the host (otherwise something has to make a network call), but don’t want to tell Syft exactly where the image is. You could make sure the local docker cache has it, and then use --from docker - that way Syft will only ask the docker daemon on the host for it, and that host already caches it. But right now there’s no, “–disable registry” or whatever, which it seems like what you’re asking for.

Sorry if I’m missing something here; I’m just trying to understand exactly what’s being asked and what, if anything, is missing and makes sense to add to Syft.