Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/cli/root.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cli

import (
"fmt"
"os"

"github.com/spf13/cobra"
Expand All @@ -18,6 +19,7 @@ var rootCmd = &cobra.Command{
func Execute() {
err := rootCmd.Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
require (
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/cli v28.1.1+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.3 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6N
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v28.1.1+incompatible h1:eyUemzeI45DY7eDPuwUcmDyDj1pM98oD5MdSpiItp8k=
github.com/docker/cli v28.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
Expand Down
14 changes: 11 additions & 3 deletions internal/docker/fucntion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,28 @@ func TestValidateDockerImageName(t *testing.T) {
image string
expected bool
}{
// Valid image names
// Valid image names (following Docker and OCI standards)
{"Valid image name without registry or tag", "ubuntu", true},
{"Valid image name with namespace", "library/ubuntu", true},
{"Valid image name with registry", "docker.io/library/ubuntu", true},
{"Valid image name with custom registry and port", "localhost:5000/myproject/ubuntu", true},
{"Valid image name with tag", "myregistry/myproject/ubuntu:latest", true},
{"Valid image name with digest", "myregistry/myproject/ubuntu@sha256:abc123", true},
{"Valid image name with version tag", "nginx:1.21.0", true},
{"Valid image name with custom tag", "myapp:v1.0.0-beta", true},
{"Valid image name with underscore", "my_project/app:latest", true},
{"Valid image name with multiple slashes", "org/team/project/app:latest", true},
{"Valid image name with IP address registry", "192.168.1.100:5000/app:latest", true},

// Invalid image names
{"Invalid image name with uppercase letters in repository", "MyRegistry/MyProject/Ubuntu", false},
{"Invalid image name with invalid characters", "invalid!@#/image/name", false},
{"Invalid image name with empty repository", "", false},
{"Invalid image name with empty string", "", false},
{"Invalid image name with only slashes", "///", false},
{"Invalid image name with multiple @ symbols", "invalid@image@name", false},
{"Invalid image name with invalid tag characters", "app:tag:with:colons", false},
{"Invalid image name with leading slash", "/app:latest", false},
{"Invalid image name with trailing slash", "app/:latest", false},
{"Invalid image name with consecutive slashes", "app//name:latest", false},
}

for _, tt := range tests {
Expand Down
19 changes: 10 additions & 9 deletions internal/docker/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,30 @@ import (
"net/http"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync/atomic"
"time"

"403unlocker-cli/internal/common"

"github.com/distribution/reference"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-containerregistry/pkg/v1/tarball"
)

// DockerImageValidator validates a Docker image name using a regular expression.
// DockerImageValidator validates a Docker image name using the same method as kubectl.
// This uses reference.ReferenceRegexp from github.com/distribution/reference package
// which provides comprehensive validation for Docker image references.
func DockerImageValidator(imageName string) bool {
pattern := `^(?:[a-zA-Z0-9\-._]+(?::[0-9]+)?/)?` +
`(?:[a-z0-9\-._]+/)?` +
`[a-z0-9\-._]+` +
`(?::[a-zA-Z0-9\-._]+)?` +
`(?:@[a-zA-Z0-9\-._:]+)?$`
regex := regexp.MustCompile(pattern)
return regex.MatchString(imageName) && !strings.Contains(imageName, "@@")
if imageName == "" {
return false
}

// Use the same validation method as kubectl
return reference.ReferenceRegexp.MatchString(imageName)
}

// customTransport tracks the number of bytes transferred during HTTP requests.
Expand Down