package capabilities import ( "bytes" "io" "strings" "testing" "time" "github.com/docker/docker/api/types" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/pkg/stdcopy" "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/fakecontext" "gotest.tools/v3/assert" "gotest.tools/v3/poll" ) func TestNoNewPrivileges(t *testing.T) { ctx := setupTest(t) withFileCapability := ` FROM debian:bullseye-slim RUN apt-get update && apt-get install -y libcap2-bin --no-install-recommends RUN setcap CAP_DAC_OVERRIDE=+eip /bin/cat RUN echo "hello" > /txt && chown 0:0 /txt && chmod 700 /txt RUN useradd -u 1500 test ` imageTag := "captest" source := fakecontext.New(t, "", fakecontext.WithDockerfile(withFileCapability)) defer source.Close() client := testEnv.APIClient() // Build image resp, err := client.ImageBuild(ctx, source.AsTarReader(t), types.ImageBuildOptions{ Tags: []string{imageTag}, }) assert.NilError(t, err) _, err = io.Copy(io.Discard, resp.Body) assert.NilError(t, err) resp.Body.Close() testCases := []struct { doc string opts []func(*container.TestContainerConfig) stdOut, stdErr string }{ { doc: "CapabilityRequested=true", opts: []func(*container.TestContainerConfig){ container.WithUser("test"), container.WithCapability("CAP_DAC_OVERRIDE"), }, stdOut: "hello", }, { doc: "CapabilityRequested=false", opts: []func(*container.TestContainerConfig){ container.WithUser("test"), container.WithDropCapability("CAP_DAC_OVERRIDE"), }, stdErr: "exec /bin/cat: operation not permitted", }, } for _, tc := range testCases { tc := tc t.Run(tc.doc, func(t *testing.T) { ctx := testutil.StartSpan(ctx, t) // Run the container with the image opts := append(tc.opts, container.WithImage(imageTag), container.WithCmd("/bin/cat", "/txt"), container.WithSecurityOpt("no-new-privileges=true"), ) cid := container.Run(ctx, t, client, opts...) poll.WaitOn(t, container.IsInState(ctx, client, cid, "exited"), poll.WithDelay(100*time.Millisecond)) // Assert on outputs logReader, err := client.ContainerLogs(ctx, cid, containertypes.LogsOptions{ ShowStdout: true, ShowStderr: true, }) assert.NilError(t, err) defer logReader.Close() var actualStdout, actualStderr bytes.Buffer _, err = stdcopy.StdCopy(&actualStdout, &actualStderr, logReader) assert.NilError(t, err) stdOut := strings.TrimSpace(actualStdout.String()) stdErr := strings.TrimSpace(actualStderr.String()) if stdOut != tc.stdOut { t.Fatalf("test produced invalid output: %q, expected %q. Stderr:%q", stdOut, tc.stdOut, stdErr) } if stdErr != tc.stdErr { t.Fatalf("test produced invalid error: %q, expected %q. Stdout:%q", stdErr, tc.stdErr, stdOut) } }) } }