Skip to content

Commit

Permalink
remediate some vulnerabilities found by semgrep and grype
Browse files Browse the repository at this point in the history
  • Loading branch information
ayee808 committed Dec 6, 2024
1 parent ded9890 commit 8acbcf4
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 8 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/manual-delivery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,7 @@ jobs:
run: |
echo "## Docker Action Image Build and Push Summary" >> $GITHUB_STEP_SUMMARY
echo ":white_check_mark: Docker Action Image Build and Push" >> $GITHUB_STEP_SUMMARY
echo ":white_check_mark: Image (Docker CLI): ghcr.io/easy-up/portage:${{ steps.vars.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
echo ":white_check_mark: Image (Podman CLI): ghcr.io/easy-up/portage:podman-${{ steps.vars.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
# echo ":white_check_mark: Image (Docker CLI): ghcr.io/easy-up/portage:${{ steps.vars.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
# echo ":white_check_mark: Image (Podman CLI): ghcr.io/easy-up/portage:podman-${{ steps.vars.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
echo ":white_check_mark: Image (Docker CLI): ghcr.io/easy-up/portage:${GITHUB_SHA::8}" >> $GITHUB_STEP_SUMMARY
echo ":white_check_mark: Image (Podman CLI): ghcr.io/easy-up/portage:podman-${GITHUB_SHA::8}" >> $GITHUB_STEP_SUMMARY
7 changes: 6 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ WORKDIR /app

ENV PORTAGE_CODE_SCAN_SEMGREP_EXPERIMENTAL="true"

# Create non-root user and group
RUN addgroup -S portage && adduser -S portage -G portage
USER portage

ENTRYPOINT ["portage"]

LABEL org.opencontainers.image.title="portage-docker"
Expand Down Expand Up @@ -144,7 +148,8 @@ LABEL org.opencontainers.image.title="portage-podman"

FROM portage-base

# Install docker CLI
USER root
RUN apk update && apk add --no-cache docker-cli-buildx
USER portage

LABEL org.opencontainers.image.title="portage-docker"
10 changes: 8 additions & 2 deletions cmd/portage/cli/v1/run-task.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,16 @@ var runImagePushTask = &cobra.Command{
PreRunE: configPreRunE,
RunE: func(cmd *cobra.Command, args []string) error {
if *flagPodmanInterface {
task := tasks.NewGenericImagePushTask("podman", config.ImageTag)
task, err := tasks.NewGenericImagePushTask("podman", config.ImageTag)
if err != nil {
return err
}
return task.Run(cmd.Context(), cmd.ErrOrStderr())
}
task := tasks.NewGenericImagePushTask("docker", config.ImageTag)
task, err := tasks.NewGenericImagePushTask("docker", config.ImageTag)
if err != nil {
return err
}
return task.Run(cmd.Context(), cmd.ErrOrStderr())
},
}
Expand Down
8 changes: 8 additions & 0 deletions pkg/tasks/image-build.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ func NewImageBuildTask(cliInterface string, opts ...taskOptionFunc) ImageBuildTa
}

func NewGenericImageBuildTask(cmdString string) *GenericImageBuildTask {
if cmdString != "docker" && cmdString != "podman" {
panic("cmdString must be either 'docker' or 'podman'")
}

return &GenericImageBuildTask{
cmdString: cmdString,
args: make([]string, 0),
Expand Down Expand Up @@ -112,6 +116,10 @@ func (t *GenericImageBuildTask) Run(ctx context.Context, stderr io.Writer) error
return err
}

if t.cmdString != "docker" && t.cmdString != "podman" {
return fmt.Errorf("invalid command string: must be either 'docker' or 'podman'")
}

buildCmd := exec.CommandContext(ctx, t.cmdString, t.args...)
return StreamStderr(buildCmd, stderr, fmt.Sprintf("%s build", t.cmdString))
}
Expand Down
18 changes: 16 additions & 2 deletions pkg/tasks/image-push.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,35 @@ package tasks

import (
"context"
"errors"
"fmt"
"io"
"os/exec"
)

// Add a whitelist of allowed CLI tools
var allowedCLITools = map[string]bool{
"docker": true,
"podman": true,
"buildah": true,
// Add other valid CLI tools as needed
}

type GenericImagePushTask struct {
TagName string
cmdName string
}

func NewGenericImagePushTask(cliInterface string, tagName string) *GenericImagePushTask {
func NewGenericImagePushTask(cliInterface string, tagName string) (*GenericImagePushTask, error) {
// Validate CLI interface against whitelist
if !allowedCLITools[cliInterface] {
return nil, errors.New("invalid CLI interface specified")
}

return &GenericImagePushTask{
TagName: tagName,
cmdName: cliInterface,
}
}, nil
}

func (t *GenericImagePushTask) Run(ctx context.Context, stderr io.Writer) error {
Expand Down
23 changes: 22 additions & 1 deletion pkg/tasks/image-save.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,32 @@ type GenericImageSaveTask struct {
cmdName string
}

func isValidImageName(name string) bool {
// Only allow characters typically used in Docker image names:
// - Lowercase letters, numbers
// - Allowed special chars: period, underscore, hyphen
// - Forward slash for image paths (e.g., "repository/image")
// - Colon for tags (e.g., "image:tag")
for _, char := range name {
if !((char >= 'a' && char <= 'z') ||
(char >= '0' && char <= '9') ||
char == '.' || char == '_' || char == '-' ||
char == '/' || char == ':') {
return false
}
}
return len(name) > 0
}

func (t *GenericImageSaveTask) Run(ctx context.Context, stderr io.Writer) error {
if strings.EqualFold(t.opts.ImageName, "") {
return errors.New("image name is required")
}

if !isValidImageName(t.opts.ImageName) {
return errors.New("invalid image name: must contain only lowercase letters, numbers, and allowed special characters (./_-/:)")
}

// let the open file command handle any invalid filename errors
// run this first just incase to fail early if something goes wrong
imageSaveFile, err := os.OpenFile(t.opts.ImageTarFilename, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o644)
Expand All @@ -60,7 +81,7 @@ func (t *GenericImageSaveTask) Run(ctx context.Context, stderr io.Writer) error

mw := io.MultiWriter(imageSaveFile, smWriter)

imageSaveCmd := exec.CommandContext(ctx, t.cmdName, "save", t.opts.ImageName)
imageSaveCmd := exec.CommandContext(ctx, t.cmdName, []string{"save", t.opts.ImageName}...)
imageSaveCmd.Stdout = mw

err = StreamStderr(imageSaveCmd, stderr, "image save")
Expand Down

0 comments on commit 8acbcf4

Please sign in to comment.