diff --git a/.golangci.reference.yml b/.golangci.reference.yml
index fda48cce..bc30cd62 100644
--- a/.golangci.reference.yml
+++ b/.golangci.reference.yml
@@ -1209,6 +1209,17 @@ linters-settings:
     ignore-words:
       - someword
 
+  musttag:
+    # A set of custom functions to check in addition to the builtin ones.
+    # Default: json, xml, gopkg.in/yaml.v3, BurntSushi/toml, mitchellh/mapstructure
+    functions:
+        # The full name of the function, including the package.
+      - name: github.com/jmoiron/sqlx.Get
+        # The struct tag whose presence should be ensured.
+        tag: db
+        # The position of the argument to check.
+        arg-pos: 1
+
   nakedret:
     # Make an issue if func has more lines of code than this setting, and it has naked returns.
     # Default: 30
@@ -2037,6 +2048,7 @@ linters:
     - makezero
     - maligned
     - misspell
+    - musttag
     - nakedret
     - nestif
     - nilerr
@@ -2145,6 +2157,7 @@ linters:
     - makezero
     - maligned
     - misspell
+    - musttag
     - nakedret
     - nestif
     - nilerr
diff --git a/go.mod b/go.mod
index 47dd406f..4848f9bc 100644
--- a/go.mod
+++ b/go.mod
@@ -51,6 +51,7 @@ require (
 	github.com/jingyugao/rowserrcheck v1.1.1
 	github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af
 	github.com/julz/importas v0.1.0
+	github.com/junk1tm/musttag v0.4.1
 	github.com/kisielk/errcheck v1.6.3
 	github.com/kkHAIKE/contextcheck v1.1.3
 	github.com/kulti/thelper v0.6.3
diff --git a/go.sum b/go.sum
index 6ee4c629..76332121 100644
--- a/go.sum
+++ b/go.sum
@@ -308,6 +308,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY=
 github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0=
+github.com/junk1tm/musttag v0.4.1 h1:RepN7vE8xObm/AC3WiynRcpFBt8paQR7ztgi09xhTsU=
+github.com/junk1tm/musttag v0.4.1/go.mod h1:XkcL/9O6RmD88JBXb+I15nYRl9W4ExhgQeCBEhfMC8U=
 github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8=
 github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw=
 github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go
index dfc0dc8b..76a16b87 100644
--- a/pkg/config/linters_settings.go
+++ b/pkg/config/linters_settings.go
@@ -179,6 +179,7 @@ type LintersSettings struct {
 	Makezero         MakezeroSettings
 	Maligned         MalignedSettings
 	Misspell         MisspellSettings
+	MustTag          MustTagSettings
 	Nakedret         NakedretSettings
 	Nestif           NestifSettings
 	NilNil           NilNilSettings
@@ -538,6 +539,14 @@ type MisspellSettings struct {
 	IgnoreWords []string `mapstructure:"ignore-words"`
 }
 
+type MustTagSettings struct {
+	Functions []struct {
+		Name   string `mapstructure:"name"`
+		Tag    string `mapstructure:"tag"`
+		ArgPos int    `mapstructure:"arg-pos"`
+	} `mapstructure:"functions"`
+}
+
 type NakedretSettings struct {
 	MaxFuncLines int `mapstructure:"max-func-lines"`
 }
diff --git a/pkg/golinters/musttag.go b/pkg/golinters/musttag.go
new file mode 100644
index 00000000..75500b5a
--- /dev/null
+++ b/pkg/golinters/musttag.go
@@ -0,0 +1,29 @@
+package golinters
+
+import (
+	"github.com/junk1tm/musttag"
+	"golang.org/x/tools/go/analysis"
+
+	"github.com/golangci/golangci-lint/pkg/config"
+	"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
+)
+
+func NewMustTag(setting *config.MustTagSettings) *goanalysis.Linter {
+	var funcs []musttag.Func
+
+	if setting != nil {
+		for _, fn := range setting.Functions {
+			funcs = append(funcs, musttag.Func{
+				Name:   fn.Name,
+				Tag:    fn.Tag,
+				ArgPos: fn.ArgPos,
+			})
+		}
+	}
+
+	a := musttag.New(funcs...)
+
+	return goanalysis.
+		NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil).
+		WithLoadMode(goanalysis.LoadModeTypesInfo)
+}
diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go
index ab8f1835..6ea531b8 100644
--- a/pkg/lint/lintersdb/manager.go
+++ b/pkg/lint/lintersdb/manager.go
@@ -147,6 +147,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
 		makezeroCfg         *config.MakezeroSettings
 		malignedCfg         *config.MalignedSettings
 		misspellCfg         *config.MisspellSettings
+		musttagCfg          *config.MustTagSettings
 		nakedretCfg         *config.NakedretSettings
 		nestifCfg           *config.NestifSettings
 		nilNilCfg           *config.NilNilSettings
@@ -224,6 +225,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
 		makezeroCfg = &m.cfg.LintersSettings.Makezero
 		malignedCfg = &m.cfg.LintersSettings.Maligned
 		misspellCfg = &m.cfg.LintersSettings.Misspell
+		musttagCfg = &m.cfg.LintersSettings.MustTag
 		nakedretCfg = &m.cfg.LintersSettings.Nakedret
 		nestifCfg = &m.cfg.LintersSettings.Nestif
 		nilNilCfg = &m.cfg.LintersSettings.NilNil
@@ -632,6 +634,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
 			WithAutoFix().
 			WithURL("https://github.com/client9/misspell"),
 
+		linter.NewConfig(golinters.NewMustTag(musttagCfg)).
+			WithSince("v1.51.0").
+			WithLoadForGoAnalysis().
+			WithPresets(linter.PresetStyle, linter.PresetBugs).
+			WithURL("https://github.com/junk1tm/musttag"),
+
 		linter.NewConfig(golinters.NewNakedret(nakedretCfg)).
 			WithSince("v1.19.0").
 			WithPresets(linter.PresetStyle).
diff --git a/test/testdata/configs/musttag.yml b/test/testdata/configs/musttag.yml
new file mode 100644
index 00000000..399e236b
--- /dev/null
+++ b/test/testdata/configs/musttag.yml
@@ -0,0 +1,9 @@
+linters-settings:
+  musttag:
+    functions:
+      - name: encoding/asn1.Marshal
+        tag: asn1
+        arg-pos: 0
+      - name: encoding/asn1.Unmarshal
+        tag: asn1
+        arg-pos: 1
diff --git a/test/testdata/musttag.go b/test/testdata/musttag.go
new file mode 100644
index 00000000..daf84298
--- /dev/null
+++ b/test/testdata/musttag.go
@@ -0,0 +1,27 @@
+//golangcitest:args -Emusttag
+package testdata
+
+import (
+	"encoding/asn1"
+	"encoding/json"
+)
+
+// builtin functions:
+func musttagJSON() {
+	var user struct { // want `exported fields should be annotated with the "json" tag`
+		Name  string
+		Email string `json:"email"`
+	}
+	json.Marshal(user)
+	json.Unmarshal(nil, &user)
+}
+
+// custom functions from config:
+func musttagASN1() {
+	var user struct {
+		Name  string
+		Email string `asn1:"email"`
+	}
+	asn1.Marshal(user)
+	asn1.Unmarshal(nil, &user)
+}
diff --git a/test/testdata/musttag_custom.go b/test/testdata/musttag_custom.go
new file mode 100644
index 00000000..42bdea3f
--- /dev/null
+++ b/test/testdata/musttag_custom.go
@@ -0,0 +1,28 @@
+//golangcitest:args -Emusttag
+//golangcitest:config_path testdata/configs/musttag.yml
+package testdata
+
+import (
+	"encoding/asn1"
+	"encoding/json"
+)
+
+// builtin functions:
+func musttagJSONCustom() {
+	var user struct { // want `exported fields should be annotated with the "json" tag`
+		Name  string
+		Email string `json:"email"`
+	}
+	json.Marshal(user)
+	json.Unmarshal(nil, &user)
+}
+
+// custom functions from config:
+func musttagASN1Custom() {
+	var user struct { // want `exported fields should be annotated with the "asn1" tag`
+		Name  string
+		Email string `asn1:"email"`
+	}
+	asn1.Marshal(user)
+	asn1.Unmarshal(nil, &user)
+}