Action Commands (run/shell/exec) Against Library URIs Ignore Configured Remote Endpoint
Description
Singularity is an open source container platform. In verions 3.7.2 and 3.7.3, Dde to incorrect use of a default URL, singularity action commands (run/shell/exec) specifying a container using a library:// URI will always attempt to retrieve the container from the default remote endpoint (cloud.sylabs.io) rather than the configured remote endpoint. An attacker may be able to push a malicious container to the default remote endpoint with a URI that is identical to the URI used by a victim with a non-default remote endpoint, thus executing the malicious container. Only action commands (run/shell/exec) against library:// URIs are affected. Other commands such as pull / push respect the configured remote endpoint. The vulnerability is patched in Singularity version 3.7.4. Two possible workarounds exist: Users can only interact with the default remote endpoint, or an installation can have an execution control list configured to restrict execution to containers signed with specific secure keys.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Singularity 3.7.2-3.7.3 ignores configured remote endpoint for library:// URIs, allowing a malicious container from the default endpoint to be executed.
Vulnerability
In Singularity versions 3.7.2 and 3.7.3, action commands (run, shell, exec) that specify a container using a library:// URI always retrieve the container from the default remote endpoint (cloud.sylabs.io) instead of the user-configured remote endpoint [1][4]. This flaw is due to incorrect use of a default URL in the handleLibrary function, which directly used endpoint.SCSDefaultLibraryURI rather than the current remote configuration [3]. Only run/shell/exec commands against library:// URIs are affected; pull and push commands correctly respect the configured endpoint [1].
Exploitation
An attacker can push a malicious container to the default remote endpoint (cloud.sylabs.io) with a library:// URI identical to one that a victim expects to pull from their non-default, configured remote endpoint [1][4]. When the victim runs singularity run library://attacker/container:tag, the action command ignores the configured endpoint and fetches the attacker's container from the default endpoint instead [1]. No additional authentication or user interaction beyond the victim executing the action command is required [1].
Impact
Successful exploitation allows the attacker to execute an arbitrary malicious container on the victim's system [1]. Depending on the container's content, this can lead to arbitrary code execution, data exfiltration, privilege escalation, or other compromise of the host system [1][4]. The victim runs the container with their own privileges, so the attacker's code inherits the victim's user permissions [2].
Mitigation
The vulnerability is patched in Singularity version 3.7.4, released on 2021-05-28 [1][4]. Users should upgrade to 3.7.4 or later. Two workarounds exist for users who cannot upgrade immediately: they can limit interaction to only the default remote endpoint, or they can configure an execution control list (ECL) to restrict execution to containers signed with specific secure keys [1]. The vulnerability is not currently listed on the CISA Known Exploited Vulnerabilities (KEV) catalog.
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/sylabs/singularityGo | >= 3.7.2, < 3.7.4 | 3.7.4 |
Affected products
3- ghsa-coords2 versions
>= 3.7.2, < 3.7.4+ 1 more
- (no CPE)range: >= 3.7.2, < 3.7.4
- (no CPE)range: < 3.8.3-1.2
- sylabs/singularityv5Range: >= 3.7.2, <= 3.7.3
Patches
1d52ae9d13979Merge pull request from GHSA-5mv9-q7fq-9394
3 files changed · +71 −2
cmd/internal/cli/actions.go+2 −2 modified@@ -21,7 +21,6 @@ import ( "github.com/sylabs/singularity/internal/pkg/client/oci" "github.com/sylabs/singularity/internal/pkg/client/oras" "github.com/sylabs/singularity/internal/pkg/client/shub" - "github.com/sylabs/singularity/internal/pkg/remote/endpoint" "github.com/sylabs/singularity/internal/pkg/util/uri" "github.com/sylabs/singularity/pkg/sylog" ) @@ -75,7 +74,8 @@ func handleOras(ctx context.Context, imgCache *cache.Handle, cmd *cobra.Command, } func handleLibrary(ctx context.Context, imgCache *cache.Handle, pullFrom string) (string, error) { - c, err := getLibraryClientConfig(endpoint.SCSDefaultLibraryURI) + // Pass uri="" to use current remote + c, err := getLibraryClientConfig("") if err != nil { return "", err }
e2e/actions/actions.go+3 −0 modified@@ -2198,6 +2198,8 @@ func E2ETests(env e2e.TestEnv) testhelper.Tests { env: env, } + np := testhelper.NoParallel + return testhelper.Tests{ "action URI": c.RunFromURI, // action_URI "exec": c.actionExec, // singularity exec @@ -2230,5 +2232,6 @@ func E2ETests(env e2e.TestEnv) testhelper.Tests { "bind image": c.bindImage, // test bind image "umask": c.actionUmask, // test umask propagation "no-mount": c.actionNoMount, // test --no-mount + "invalidRemote": np(c.invalidRemote), // GHSA-5mv9-q7fq-9394 } }
e2e/actions/regressions.go+66 −0 modified@@ -616,3 +616,69 @@ func (c actionTests) issue5690(t *testing.T) { e2e.ExpectExit(0), ) } + +// If an invalid remote is set, we should not pull a container from the default +// library. +// GHSA-5mv9-q7fq-9394 +func (c actionTests) invalidRemote(t *testing.T) { + testEndpoint := "invalid" + testEndpointURI := "https://cloud.example.com" + testImage := "library://alpine" + + // Exec library image from the default remote... ensure it succeeds + argv := []string{testImage, "/bin/true"} + c.env.RunSingularity( + t, + e2e.AsSubtest("exec default"), + e2e.WithProfile(e2e.UserProfile), + e2e.WithCommand("exec"), + e2e.WithArgs(argv...), + e2e.ExpectExit(0), + ) + + // Add another endpoint + argv = []string{"add", "--no-login", testEndpoint, testEndpointURI} + c.env.RunSingularity( + t, + e2e.AsSubtest("remote add"), + e2e.WithProfile(e2e.UserProfile), + e2e.WithCommand("remote"), + e2e.WithArgs(argv...), + e2e.ExpectExit(0), + ) + // Remove test remote when we are done here + defer func(t *testing.T) { + argv := []string{"remove", testEndpoint} + c.env.RunSingularity( + t, + e2e.AsSubtest("remote remove"), + e2e.WithProfile(e2e.UserProfile), + e2e.WithCommand("remote"), + e2e.WithArgs(argv...), + e2e.ExpectExit(0), + ) + }(t) + + // Set as default + argv = []string{"use", testEndpoint} + c.env.RunSingularity( + t, + e2e.AsSubtest("remote use"), + e2e.WithProfile(e2e.UserProfile), + e2e.WithCommand("remote"), + e2e.WithArgs(argv...), + e2e.ExpectExit(0), + ) + + // Exec library image from the invalid remote, should fail + argv = []string{testImage, "/bin/true"} + c.env.RunSingularity( + t, + e2e.AsSubtest("exec invalid"), + e2e.WithProfile(e2e.UserProfile), + e2e.WithCommand("exec"), + e2e.WithArgs(argv...), + e2e.ExpectExit(255), + ) + +}
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-5mv9-q7fq-9394ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2021-32635ghsaADVISORY
- security.gentoo.org/glsa/202107-50ghsavendor-advisoryx_refsource_GENTOOWEB
- github.com/hpcng/singularity/security/advisories/GHSA-jq42-hfch-42f3ghsaWEB
- github.com/sylabs/singularity/commit/d52ae9d13979733c5e987a566fae59ed6f1bf796ghsaWEB
- github.com/sylabs/singularity/releases/tag/v3.7.4ghsax_refsource_MISCWEB
- github.com/sylabs/singularity/security/advisories/GHSA-5mv9-q7fq-9394ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.