Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supply chain hardening #1402

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
13 changes: 7 additions & 6 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
with:
go-version: ${{ matrix.go-version }}

Expand All @@ -25,19 +25,20 @@ jobs:

- name: Send Coverage
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.23.x'
uses: shogo82148/actions-goveralls@v1
uses: shogo82148/actions-goveralls@e6875f831db61e6abffbd8df91a2eb6cd24b46c9 # v1.9.1
with:
path-to-profile: profile.cov

golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5.4.0
with:
go-version: 1.24.x
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
uses: golangci/golangci-lint-action@4696ba8babb6127d732c3c6dde519db15edab9ea # v6.5.1
with:
version: latest

70 changes: 41 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Package validator
=================

<img align="right" src="logo.png">![Project status](https://img.shields.io/badge/version-10.25.0-green.svg)
[![Build Status](https://github.com/go-playground/validator/actions/workflows/workflow.yml/badge.svg)](https://github.com/go-playground/validator/actions)
[![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/validator?branch=master)
Expand All @@ -11,15 +12,15 @@ Package validator implements value validations for structs and individual fields

It has the following **unique** features:

- Cross Field and Cross Struct validations by using validation tags or custom validators.
- Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated.
- Ability to dive into both map keys and values for validation
- Handles type interface by determining it's underlying type prior to validation.
- Handles custom field types such as sql driver Valuer see [Valuer](https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29)
- Alias validation tags, which allows for mapping of several validations to a single tag for easier defining of validations on structs
- Extraction of custom defined Field Name e.g. can specify to extract the JSON name while validating and have it available in the resulting FieldError
- Customizable i18n aware error messages.
- Default validator for the [gin](https://github.com/gin-gonic/gin) web framework; upgrading from v8 to v9 in gin see [here](https://github.com/go-playground/validator/tree/master/_examples/gin-upgrading-overriding)
- Cross Field and Cross Struct validations by using validation tags or custom validators.
- Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated.
- Ability to dive into both map keys and values for validation
- Handles type interface by determining it's underlying type prior to validation.
- Handles custom field types such as sql driver Valuer see [Valuer](https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29)
- Alias validation tags, which allows for mapping of several validations to a single tag for easier defining of validations on structs
- Extraction of custom defined Field Name e.g. can specify to extract the JSON name while validating and have it available in the resulting FieldError
- Customizable i18n aware error messages.
- Default validator for the [gin](https://github.com/gin-gonic/gin) web framework; upgrading from v8 to v9 in gin see [here](https://github.com/go-playground/validator/tree/master/_examples/gin-upgrading-overriding)

A Call for Maintainers
----------------------
Expand All @@ -31,11 +32,11 @@ Installation

Use go get.

go get github.com/go-playground/validator/v10
go get github.com/go-playground/validator/v10

Then import the validator package into your own code.

import "github.com/go-playground/validator/v10"
import "github.com/go-playground/validator/v10"

Error Return Value
-------
Expand All @@ -44,8 +45,8 @@ Validation functions return type error

They return type error to avoid the issue discussed in the following, where err is always != nil:

* http://stackoverflow.com/a/29138676/3158232
* https://github.com/go-playground/validator/issues/134
- <http://stackoverflow.com/a/29138676/3158232>
- <https://github.com/go-playground/validator/issues/134>

Validator returns only InvalidValidationError for bad validation input, nil or ValidationErrors as type error; so, in your code all you need to do is check if the error returned is not nil, and if it's not check if error is InvalidValidationError ( if necessary, most of the time it isn't ) type cast it to type ValidationErrors like so:

Expand All @@ -57,9 +58,9 @@ validationErrors := err.(validator.ValidationErrors)
Usage and documentation
------

Please see https://pkg.go.dev/github.com/go-playground/validator/v10 for detailed usage docs.
Please see <https://pkg.go.dev/github.com/go-playground/validator/v10> for detailed usage docs.

##### Examples:
##### Examples

- [Simple](https://github.com/go-playground/validator/blob/master/_examples/simple/main.go)
- [Custom Field Types](https://github.com/go-playground/validator/blob/master/_examples/custom/main.go)
Expand All @@ -71,13 +72,15 @@ Please see https://pkg.go.dev/github.com/go-playground/validator/v10 for detaile
Baked-in Validations
------

### Special Notes:
### Special Notes

- If new to using validator it is highly recommended to initialize it using the `WithRequiredStructEnabled` option which is opt-in to new behaviour that will become the default behaviour in v11+. See documentation for more details.

```go
validate := validator.New(validator.WithRequiredStructEnabled())
```

### Fields:
### Fields

| Tag | Description |
| - | - |
Expand All @@ -96,7 +99,7 @@ validate := validator.New(validator.WithRequiredStructEnabled())
| necsfield | Field Does Not Equal Another Field (relative) |
| nefield | Field Does Not Equal Another Field |

### Network:
### Network

| Tag | Description |
| - | - |
Expand Down Expand Up @@ -128,7 +131,7 @@ validate := validator.New(validator.WithRequiredStructEnabled())
| url_encoded | URL Encoded |
| urn_rfc2141 | Urn RFC 2141 String |

### Strings:
### Strings

| Tag | Description |
| - | - |
Expand All @@ -155,7 +158,8 @@ validate := validator.New(validator.WithRequiredStructEnabled())
| startswith | Starts With |
| uppercase | Uppercase |

### Format:
### Format

| Tag | Description |
| - | - |
| base64 | Base64 String |
Expand Down Expand Up @@ -211,6 +215,7 @@ validate := validator.New(validator.WithRequiredStructEnabled())
| uuid_rfc4122 | Universally Unique Identifier UUID RFC4122 |
| md4 | MD4 hash |
| md5 | MD5 hash |
| oci_tag | Open Container Initiative (OCI) Tag |
| sha256 | SHA256 hash |
| sha384 | SHA384 hash |
| sha512 | SHA512 hash |
Expand All @@ -223,7 +228,8 @@ validate := validator.New(validator.WithRequiredStructEnabled())
| ulid | Universally Unique Lexicographically Sortable Identifier ULID |
| cve | Common Vulnerabilities and Exposures Identifier (CVE id) |

### Comparisons:
### Comparisons

| Tag | Description |
| - | - |
| eq | Equals |
Expand All @@ -235,7 +241,8 @@ validate := validator.New(validator.WithRequiredStructEnabled())
| ne | Not Equal |
| ne_ignore_case | Not Equal ignoring case |

### Other:
### Other

| Tag | Description |
| - | - |
| dir | Existing Directory |
Expand Down Expand Up @@ -263,15 +270,18 @@ validate := validator.New(validator.WithRequiredStructEnabled())
| excluded_without_all | Excluded Without All |
| unique | Unique |

#### Aliases:
#### Aliases

| Tag | Description |
| - | - |
| iscolor | hexcolor\|rgb\|rgba\|hsl\|hsla |
| country_code | iso3166_1_alpha2\|iso3166_1_alpha3\|iso3166_1_alpha_numeric |

Benchmarks
------

###### Run on MacBook Pro Max M3

```go
go version go1.23.3 darwin/arm64
goos: darwin
Expand Down Expand Up @@ -347,8 +357,8 @@ Complementary Software

Here is a list of software that complements using this library either pre or post validation.

* [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.
* [mold](https://github.com/go-playground/mold) - A general library to help modify or set data within data structures and other objects
- [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.
- [mold](https://github.com/go-playground/mold) - A general library to help modify or set data within data structures and other objects

How to Contribute
------
Expand All @@ -360,20 +370,22 @@ Maintenance and support for SDK major versions

See prior discussion [here](https://github.com/go-playground/validator/discussions/1342) for more details.

This package is aligned with the [Go release policy](https://go.dev/doc/devel/release) in that support is guaranteed for
This package is aligned with the [Go release policy](https://go.dev/doc/devel/release) in that support is guaranteed for
the two most recent major versions.

This does not mean the package will not work with older versions of Go, only that we reserve the right to increase the
MSGV(Minimum Supported Go Version) when the need arises to address Security issues/patches, OS issues & support or newly
This does not mean the package will not work with older versions of Go, only that we reserve the right to increase the
MSGV(Minimum Supported Go Version) when the need arises to address Security issues/patches, OS issues & support or newly
introduced functionality that would greatly benefit the maintenance and/or usage of this package.

If and when the MSGV is increased it will be done so in a minimum of a `Minor` release bump.

License
-------

Distributed under MIT License, please see license file within the code for more details.

Maintainers
-----------

This project has grown large enough that more than one person is required to properly support the community.
If you are interested in becoming a maintainer please reach out to me https://github.com/deankarn
If you are interested in becoming a maintainer please reach out to me <https://github.com/deankarn>
6 changes: 6 additions & 0 deletions baked_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ var (
"mongodb_connection_string": isMongoDBConnectionString,
"cron": isCron,
"spicedb": isSpiceDB,
"oci_tag": isOciTag,
"ein": isEIN,
}
)
Expand Down Expand Up @@ -3067,6 +3068,11 @@ func isCron(fl FieldLevel) bool {
return cronRegex().MatchString(cronString)
}

// isOciTag is the validation function for validating if the current field's value is a valid OCI tag, as described in the OCI Distribution Specification: https://github.com/opencontainers/distribution-spec/blob/main/spec.md
func isOciTag(fl FieldLevel) bool {
return ociTagRegex().MatchString(fl.Field().String())
}

// isEIN is the validation function for validating if the current field's value is a valid U.S. Employer Identification Number (EIN)
func isEIN(fl FieldLevel) bool {
field := fl.Field()
Expand Down
6 changes: 6 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,12 @@ Example:
ConnectionStringField string `validate:"mongodb_connection_string"`
}

# OCI Tag

This validates that a string value is a valid OCI tag, as defined in the OCI Image Spec.

Usage: oci_tag

# Cron

This validates that a string value contains a valid cron expression.
Expand Down
2 changes: 2 additions & 0 deletions regexes.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const (
spicedbIDRegexString = `^(([a-zA-Z0-9/_|\-=+]{1,})|\*)$`
spicedbPermissionRegexString = "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$"
spicedbTypeRegexString = "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$"
ociTagRegexString = "^[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}$"
einRegexString = "^(\\d{2}-\\d{7})$"
)

Expand Down Expand Up @@ -161,5 +162,6 @@ var (
spicedbIDRegex = lazyRegexCompile(spicedbIDRegexString)
spicedbPermissionRegex = lazyRegexCompile(spicedbPermissionRegexString)
spicedbTypeRegex = lazyRegexCompile(spicedbTypeRegexString)
ociTagRegex = lazyRegexCompile(ociTagRegexString)
einRegex = lazyRegexCompile(einRegexString)
)
26 changes: 26 additions & 0 deletions validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9430,6 +9430,32 @@ func TestPointerAndOmitEmpty(t *testing.T) {
Equal(t, errs, nil)
}

func TestOciTag(t *testing.T) {
validate := New()

type Test struct {
Value string `validate:"oci_tag"`
}

var test Test

err := validate.Struct(test)
NotEqual(t, err, nil)
AssertError(t, err.(ValidationErrors), "Test.Value", "Test.Value", "Value", "Value", "oci_tag")

test.Value = "latest"
err = validate.Struct(test)
Equal(t, err, nil)

test.Value = "thisismorethanonehundredandtwentyeightcharactersthisismorethanonehundredandtwentyeightcharactersthisismorethanonehundredandtwenty"
err = validate.Struct(test)
AssertError(t, err.(ValidationErrors), "Test.Value", "Test.Value", "Value", "Value", "oci_tag")

test.Value = ""
err = validate.Struct(test)
AssertError(t, err.(ValidationErrors), "Test.Value", "Test.Value", "Value", "Value", "oci_tag")
}

func TestRequired(t *testing.T) {
validate := New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
Expand Down