diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml
index 37866ff00f2c..11c1a5a4fb38 100644
--- a/.golangci.next.reference.yml
+++ b/.golangci.next.reference.yml
@@ -57,6 +57,7 @@ linters:
     - godot
     - godox
     - goheader
+    - golicenser
     - gomoddirectives
     - gomodguard
     - goprintffuncname
@@ -165,6 +166,7 @@ linters:
     - godot
     - godox
     - goheader
+    - golicenser
     - gomoddirectives
     - gomodguard
     - goprintffuncname
@@ -1279,6 +1281,79 @@ linters:
       # Default: ""
       template-path: /path/to/my/template.tmpl
 
+    golicenser:
+      # Regexp used to detect license/copyright headers.
+      # This will be used to detect the existence of a copyright header in a file.
+      # If the first comment in a Go source file does not match this, then a license header will be generated.
+      # For the license header to be updated, it must also match the header matcher.
+      # Default: "(?i)copyright"
+      copyright-header-matcher: "(?i)copyright"
+
+      header:
+        # The project author name used in the `author` template variable.
+        # Required value.
+        author: "My Name"
+        # Regexp used to match the project author (`author` variable).
+        # Default: regexp-escaped value of `author`.
+        author-regexp: "(My Name|Your Name)"
+        # Style of comment to use in license headers.
+        # More information: https://github.com/joshuasing/golicenser#comment-styles
+        # Valid options are: `line`, `block`.
+        # Default: "line"
+        comment-style: "line"
+        # License header template (using Go text/template: https://pkg.go.dev/text/template).
+        # More information: https://github.com/joshuasing/golicenser#templates
+        # Built-in variables:
+        # - `year`: Copyright year(s) for the file. The format is configurable with `year-mode`.
+        # - `author`: The copyright author (provided by `author`).
+        # - `filename`: The current filename.
+        # Custom variables can be provided in `variables` below.
+        # Required value.
+        template: |-
+          Copyright (c) {{.year}} {{.author}}. All rights reserved.
+          Use of this source code is governed by a BSD-style
+          license that can be found in the LICENSE file.
+        # Path to file containing license header template.
+        # This is an alternative to `template`, and `template` will take priority if set.
+        # By default, if a path is relative, it is relative to the directory where the golangci-lint command is executed.
+        # The placeholder '${base-path}' is substituted with a path relative to the mode defined with `run.relative-path-mode`.
+        # The placeholder '${config-path}' is substituted with a path relative to the configuration file.
+        # Default: ""
+        template-path: /path/to/my/template.tmpl
+        # License header match regexp.
+        # More information: https://github.com/joshuasing/golicenser#matcher
+        # Matched headers will be updated or replaced by the header template.
+        # Default: regexp-escaped value of `template`.
+        matcher: |-
+          Copyright \(c\) {{.year}} {{.author}}.(\s*All rights reserved.)?
+          Use of this source code is governed by a BSD-style
+          license that can be found in the LICENSE file.
+        # Enable to regexp-escape the header matcher.
+        # Useful if you want to provide a license header instead of regexp expression.
+        # Default: false
+        matcher-escape: false
+        # Variables to provide to the header template.
+        # Due to a limitation of Viper, the configuration loader used by golangci-lint, variable names will always be
+        # provided as lowercase to the template.
+        # Default: {}
+        variables:
+          email:
+            regexp: "(.+)@mycompany\\.com"
+          project-name:
+            value: "My project"
+        # Copyright year formatting mode.
+        # More information: https://github.com/joshuasing/golicenser#year-modes
+        # Available year modes are:
+        # - `preserve`: Current year in new headers, existing year in updated headers.
+        # - `preserve-this-year-range`: Current year in new headers, existing year to current year in updated headers.
+        # - `preserve-modified-range`: Last modified year in new headers, existing year to last modified year in updated headers.
+        # - `this-year`: Current year.
+        # - `last-modified`: File last modified year.
+        # - `git-range`: Git history creation year to last modified year (e.g. `2022-2025`)
+        # - `git-modified-list`: List of all modified years from Git history (e.g. `2022, 2024, 2025`)
+        # Default: "preserve"
+        year-mode: "git-range"
+
     gomoddirectives:
       # Allow local `replace` directives.
       # Default: false
diff --git a/go.mod b/go.mod
index 00695fdf37ad..d578ca60a048 100644
--- a/go.mod
+++ b/go.mod
@@ -60,6 +60,7 @@ require (
 	github.com/jgautheron/goconst v1.8.1
 	github.com/jingyugao/rowserrcheck v1.1.1
 	github.com/jjti/go-spancheck v0.6.4
+	github.com/joshuasing/golicenser v0.3.1
 	github.com/julz/importas v0.2.0
 	github.com/karamaru-alpha/copyloopvar v1.2.1
 	github.com/kisielk/errcheck v1.9.0
@@ -141,6 +142,7 @@ require (
 	github.com/Masterminds/semver/v3 v3.3.1 // indirect
 	github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
+	github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect
 	github.com/ccojocar/zxcvbn-go v1.0.2 // indirect
 	github.com/cespare/xxhash/v2 v2.3.0 // indirect
 	github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
diff --git a/go.sum b/go.sum
index 9bc80fb7cd9b..34110c6920fc 100644
--- a/go.sum
+++ b/go.sum
@@ -96,6 +96,8 @@ github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5
 github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo=
 github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M=
 github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k=
+github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
+github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
 github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ=
 github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg=
 github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE=
@@ -337,6 +339,8 @@ github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjz
 github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c=
 github.com/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc=
 github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk=
+github.com/joshuasing/golicenser v0.3.1 h1:M05PUCcA+CTTZJCcsyI/tAyAAEzu0JBV1f/iChfmIFE=
+github.com/joshuasing/golicenser v0.3.1/go.mod h1:v1ivFA0z+ZXvm/GMpfBygQHk8I7YgGJw6EUPeQAkoFs=
 github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json
index 0f2ef5fcc50b..427edd221583 100644
--- a/jsonschema/golangci.next.jsonschema.json
+++ b/jsonschema/golangci.next.jsonschema.json
@@ -757,6 +757,7 @@
             "godox",
             "err113",
             "goheader",
+            "golicenser",
             "gomoddirectives",
             "gomodguard",
             "goprintffuncname",
@@ -1935,6 +1936,96 @@
             { "required": ["template-path"] }
           ]
         },
+        "golicenserSettings": {
+          "type": "object",
+          "additionalProperties": false,
+          "properties": {
+            "copyright-header-matcher": {
+              "description": "Regexp used to detect license/copyright headers. This is used to detect the existence of any copyright header in a file.",
+              "type": "string",
+              "default": "(?i)copyright"
+            },
+            "header": {
+              "description": "License header settings.",
+              "type": "object",
+              "properties": {
+                "template": {
+                  "description": "License header template (using Go text/template)\nhttps://github.com/joshuasing/golicenser#templates",
+                  "type": "string",
+                  "examples": [
+                    "Copyright (c) {{.year}} {{.author}}. All rights reserved.\nUse of this source code is governed by a BSD-style\nlicense that can be found in the LICENSE file."
+                  ]
+                },
+                "template-path": {
+                  "description": "Path to file containing license header template",
+                  "type": "string",
+                  "examples": [
+                    "license.txt",
+                    "license-header.txt"
+                  ]
+                },
+                "matcher": {
+                  "description": "License header matcher regexp\nhttps://github.com/joshuasing/golicenser#matcher",
+                  "type": "string",
+                  "examples": [
+                    "Copyright \\(c\\) {{.year}} {{.author}}(.|\\s<.+@example.com>)"
+                  ]
+                },
+                "matcher-escape": {
+                  "description": "Enable to regexp-escape the header matcher. Useful for providing a license template instead of regexp.",
+                  "type": "boolean",
+                  "default": false
+                },
+                "author": {
+                  "description": "Project author name (used in the `author` template variable).",
+                  "type": "string"
+                },
+                "author-regexp": {
+                  "description": "Regexp used to match the project author (`author` variable)",
+                  "type": "string"
+                },
+                "variables": {
+                  "description": "Custom variables to provide to the header template\nNote: Due to a limitation of Viper, the configuration loader used by golangci-lint, variable names will always be provided as lowercase to the template.",
+                  "type": "object",
+                  "additionalProperties": false,
+                  "patternProperties": {
+                    "^[a-z\\-]+$": {
+                      "type": "object",
+                      "additionalProperties": false,
+                      "properties": {
+                        "value": {
+                          "description": "Variable value",
+                          "type": "string"
+                        },
+                        "regexp": {
+                          "description": "Variable matcher regexp",
+                          "type": "string"
+                        }
+                      }
+                    }
+                  }
+                },
+                "year-mode": {
+                  "description": "Copyright year formatting mode.\nhttps://github.com/joshuasing/golicenser#year-modes",
+                  "type": "string",
+                  "enum": ["preserve", "preserve-this-year-range", "preserve-modified-range", "this-year", "last-modified", "git-range", "git-modified-list"],
+                  "default": "preserve"
+                },
+                "comment-style": {
+                  "description": "Style of comment to use in license headers.\nhttps://github.com/joshuasing/golicenser#comment-styles",
+                  "type": "string",
+                  "enum": ["line", "block"],
+                  "default": "line"
+                }
+              },
+              "oneOf": [
+                { "required": ["template", "author"] },
+                { "required": ["template-path", "author"] }
+              ]
+            }
+          },
+          "required": ["header"]
+        },
         "goimportsSettings": {
           "type": "object",
           "additionalProperties": false,
@@ -4399,6 +4490,9 @@
             "goheader": {
               "$ref": "#/definitions/settings/definitions/goheaderSettings"
             },
+            "golicenser": {
+              "$ref": "#/definitions/settings/definitions/golicenserSettings"
+            },
             "gomoddirectives": {
               "$ref": "#/definitions/settings/definitions/gomoddirectivesSettings"
             },
diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go
index 16a8bb9501b9..c39762d3a5cc 100644
--- a/pkg/config/linters_settings.go
+++ b/pkg/config/linters_settings.go
@@ -232,6 +232,7 @@ type LintersSettings struct {
 	Godot           GodotSettings           `mapstructure:"godot"`
 	Godox           GodoxSettings           `mapstructure:"godox"`
 	Goheader        GoHeaderSettings        `mapstructure:"goheader"`
+	Golicenser      GoLicenserSettings      `mapstructure:"golicenser"`
 	GoModDirectives GoModDirectivesSettings `mapstructure:"gomoddirectives"`
 	Gomodguard      GoModGuardSettings      `mapstructure:"gomodguard"`
 	Gosec           GoSecSettings           `mapstructure:"gosec"`
@@ -510,6 +511,28 @@ type GoHeaderSettings struct {
 	TemplatePath string                       `mapstructure:"template-path"`
 }
 
+type GoLicenserSettings struct {
+	Header                 GoLicenserHeaderSettings `mapstructure:"header"`
+	CopyrightHeaderMatcher string                   `mapstructure:"copyright-header-matcher"`
+}
+
+type GoLicenserHeaderSettings struct {
+	Template      string                   `mapstructure:"template"`
+	TemplatePath  string                   `mapstructure:"template-path"`
+	Matcher       string                   `mapstructure:"matcher"`
+	MatcherEscape bool                     `mapstructure:"matcher-escape"`
+	Author        string                   `mapstructure:"author"`
+	AuthorRegexp  string                   `mapstructure:"author-regexp"`
+	Variables     map[string]GoLicenserVar `mapstructure:"variables"`
+	YearMode      string                   `mapstructure:"year-mode"`
+	CommentStyle  string                   `mapstructure:"comment-style"`
+}
+
+type GoLicenserVar struct {
+	Value  string `mapstructure:"value"`
+	Regexp string `mapstructure:"regexp"`
+}
+
 type GoModDirectivesSettings struct {
 	ReplaceAllowList          []string `mapstructure:"replace-allow-list"`
 	ReplaceLocal              bool     `mapstructure:"replace-local"`
diff --git a/pkg/golinters/golicenser/golicenser.go b/pkg/golinters/golicenser/golicenser.go
new file mode 100644
index 000000000000..0c2f22f79b6b
--- /dev/null
+++ b/pkg/golinters/golicenser/golicenser.go
@@ -0,0 +1,94 @@
+package golicenser
+
+import (
+	"fmt"
+	"os"
+	"strings"
+
+	"github.com/joshuasing/golicenser"
+	"golang.org/x/tools/go/analysis"
+
+	"github.com/golangci/golangci-lint/v2/pkg/config"
+	"github.com/golangci/golangci-lint/v2/pkg/goanalysis"
+	"github.com/golangci/golangci-lint/v2/pkg/golinters/internal"
+)
+
+const linterName = "golicenser"
+
+func New(settings *config.GoLicenserSettings, replacer *strings.Replacer) *goanalysis.Linter {
+	conf, err := createConfig(settings, replacer)
+	if err != nil {
+		internal.LinterLogger.Fatalf("%s: parse year mode: %v", linterName, err)
+	}
+
+	analyzer, err := golicenser.NewAnalyzer(conf)
+	if err != nil {
+		internal.LinterLogger.Fatalf("%s: create analyzer: %v", linterName, err)
+	}
+
+	return goanalysis.NewLinter(
+		linterName,
+		"Powerful license header linter",
+		[]*analysis.Analyzer{analyzer},
+		nil,
+	).WithLoadMode(goanalysis.LoadModeSyntax)
+}
+
+func createConfig(settings *config.GoLicenserSettings, replacer *strings.Replacer) (golicenser.Config, error) {
+	if settings == nil {
+		return golicenser.Config{}, nil
+	}
+
+	header := golicenser.HeaderOpts{
+		Matcher:       settings.Header.Matcher,
+		MatcherEscape: settings.Header.MatcherEscape,
+		Author:        settings.Header.Author,
+		AuthorRegexp:  settings.Header.AuthorRegexp,
+		Template:      settings.Header.Template,
+		Variables:     make(map[string]*golicenser.Var, len(settings.Header.Variables)),
+	}
+
+	// Template from config takes priority over template from 'template-path'.
+	if header.Template == "" && settings.Header.TemplatePath != "" {
+		b, err := os.ReadFile(replacer.Replace(settings.Header.TemplatePath))
+		if err != nil {
+			return golicenser.Config{}, fmt.Errorf("read the template file: %w", err)
+		}
+
+		// Use template from a file (trim newline from the end of file)
+		header.Template = strings.TrimSuffix(strings.TrimSuffix(string(b), "\n"), "\r")
+	}
+
+	var err error
+	if settings.Header.YearMode != "" {
+		header.YearMode, err = golicenser.ParseYearMode(settings.Header.YearMode)
+		if err != nil {
+			return golicenser.Config{}, fmt.Errorf("parse year mode: %w", err)
+		}
+	}
+
+	if settings.Header.CommentStyle != "" {
+		header.CommentStyle, err = golicenser.ParseCommentStyle(settings.Header.CommentStyle)
+		if err != nil {
+			return golicenser.Config{}, fmt.Errorf("parse comment style: %w", err)
+		}
+	}
+
+	for k, v := range settings.Header.Variables {
+		header.Variables[k] = &golicenser.Var{
+			Value:  v.Value,
+			Regexp: v.Regexp,
+		}
+	}
+
+	return golicenser.Config{
+		Header:                 header,
+		CopyrightHeaderMatcher: settings.CopyrightHeaderMatcher,
+
+		// NOTE(ldez): not wanted for now.
+		// And an empty slice is used because of a wrong default inside the linter.
+		Exclude: []string{},
+		// NOTE(ldez): golangci-lint already handles concurrency.
+		MaxConcurrent: 1,
+	}, nil
+}
diff --git a/pkg/golinters/golicenser/golicenser_integration_test.go b/pkg/golinters/golicenser/golicenser_integration_test.go
new file mode 100644
index 000000000000..b4325fc46c65
--- /dev/null
+++ b/pkg/golinters/golicenser/golicenser_integration_test.go
@@ -0,0 +1,19 @@
+package golicenser
+
+import (
+	"testing"
+
+	"github.com/golangci/golangci-lint/v2/test/testshared/integration"
+)
+
+func TestFromTestdata(t *testing.T) {
+	integration.RunTestdata(t)
+}
+
+func TestFix(t *testing.T) {
+	integration.RunFix(t)
+}
+
+func TestFixPathPrefix(t *testing.T) {
+	integration.RunFixPathPrefix(t)
+}
diff --git a/pkg/golinters/golicenser/testdata/fix/in/golicenser_author.go b/pkg/golinters/golicenser/testdata/fix/in/golicenser_author.go
new file mode 100644
index 000000000000..9ab229621b38
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/fix/in/golicenser_author.go
@@ -0,0 +1,13 @@
+// Copyright (c) 2025 golangci-lint <someone@example.com>.
+// This file is a part of golangci-lint.
+
+//golangcitest:args -Egolicenser
+//golangcitest:expected_exitcode 0
+//golangcitest:config_path testdata/golicenser-fix.yml
+package testdata
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, world!")
+}
diff --git a/pkg/golinters/golicenser/testdata/fix/in/golicenser_change_comment_style.go b/pkg/golinters/golicenser/testdata/fix/in/golicenser_change_comment_style.go
new file mode 100644
index 000000000000..35b435aa0579
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/fix/in/golicenser_change_comment_style.go
@@ -0,0 +1,9 @@
+/*
+Copyright (c) 2025 golangci-lint <test@example.com>.
+This file is a part of golangci-lint.
+*/
+
+//golangcitest:args -Egolicenser
+//golangcitest:expected_exitcode 0
+//golangcitest:config_path testdata/golicenser-fix.yml
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/fix/in/golicenser_no_changes.go b/pkg/golinters/golicenser/testdata/fix/in/golicenser_no_changes.go
new file mode 100644
index 000000000000..a255ae4c02ae
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/fix/in/golicenser_no_changes.go
@@ -0,0 +1,8 @@
+// Copyright (c) 2025 Someone else
+// This file has a different license header which matches the copyright header
+// matcher but not the license header matcher, therefore it should not be updated.
+
+//golangcitest:args -Egolicenser
+//golangcitest:expected_exitcode 0
+//golangcitest:config_path testdata/golicenser-fix.yml
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/fix/in/golicenser_no_header.go b/pkg/golinters/golicenser/testdata/fix/in/golicenser_no_header.go
new file mode 100644
index 000000000000..b20aa9063a26
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/fix/in/golicenser_no_header.go
@@ -0,0 +1,4 @@
+//golangcitest:args -Egolicenser
+//golangcitest:expected_exitcode 0
+//golangcitest:config_path testdata/golicenser-fix.yml
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/fix/in/golicenser_package_comment.go b/pkg/golinters/golicenser/testdata/fix/in/golicenser_package_comment.go
new file mode 100644
index 000000000000..1923408bd058
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/fix/in/golicenser_package_comment.go
@@ -0,0 +1,7 @@
+// Package testdata is used for testing whether golicenser works correctly.
+// golicenser should ignore this package comment and add a license header above it.
+//
+//golangcitest:args -Egolicenser
+//golangcitest:expected_exitcode 0
+//golangcitest:config_path testdata/golicenser-fix.yml
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/fix/out/golicenser_author.go b/pkg/golinters/golicenser/testdata/fix/out/golicenser_author.go
new file mode 100644
index 000000000000..721ea8d5e851
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/fix/out/golicenser_author.go
@@ -0,0 +1,13 @@
+// Copyright (c) 2025 golangci-lint <test@example.com>.
+// This file is a part of golangci-lint.
+
+//golangcitest:args -Egolicenser
+//golangcitest:expected_exitcode 0
+//golangcitest:config_path testdata/golicenser-fix.yml
+package testdata
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, world!")
+}
diff --git a/pkg/golinters/golicenser/testdata/fix/out/golicenser_change_comment_style.go b/pkg/golinters/golicenser/testdata/fix/out/golicenser_change_comment_style.go
new file mode 100644
index 000000000000..142b7a398a47
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/fix/out/golicenser_change_comment_style.go
@@ -0,0 +1,7 @@
+// Copyright (c) 2025 golangci-lint <test@example.com>.
+// This file is a part of golangci-lint.
+
+//golangcitest:args -Egolicenser
+//golangcitest:expected_exitcode 0
+//golangcitest:config_path testdata/golicenser-fix.yml
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/fix/out/golicenser_no_changes.go b/pkg/golinters/golicenser/testdata/fix/out/golicenser_no_changes.go
new file mode 100644
index 000000000000..a255ae4c02ae
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/fix/out/golicenser_no_changes.go
@@ -0,0 +1,8 @@
+// Copyright (c) 2025 Someone else
+// This file has a different license header which matches the copyright header
+// matcher but not the license header matcher, therefore it should not be updated.
+
+//golangcitest:args -Egolicenser
+//golangcitest:expected_exitcode 0
+//golangcitest:config_path testdata/golicenser-fix.yml
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/fix/out/golicenser_no_header.go b/pkg/golinters/golicenser/testdata/fix/out/golicenser_no_header.go
new file mode 100644
index 000000000000..142b7a398a47
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/fix/out/golicenser_no_header.go
@@ -0,0 +1,7 @@
+// Copyright (c) 2025 golangci-lint <test@example.com>.
+// This file is a part of golangci-lint.
+
+//golangcitest:args -Egolicenser
+//golangcitest:expected_exitcode 0
+//golangcitest:config_path testdata/golicenser-fix.yml
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/fix/out/golicenser_package_comment.go b/pkg/golinters/golicenser/testdata/fix/out/golicenser_package_comment.go
new file mode 100644
index 000000000000..cde2984c8eff
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/fix/out/golicenser_package_comment.go
@@ -0,0 +1,10 @@
+// Copyright (c) 2025 golangci-lint <test@example.com>.
+// This file is a part of golangci-lint.
+
+// Package testdata is used for testing whether golicenser works correctly.
+// golicenser should ignore this package comment and add a license header above it.
+//
+//golangcitest:args -Egolicenser
+//golangcitest:expected_exitcode 0
+//golangcitest:config_path testdata/golicenser-fix.yml
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/golicenser-fix.yml b/pkg/golinters/golicenser/testdata/golicenser-fix.yml
new file mode 100644
index 000000000000..07fd90c9a2b7
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/golicenser-fix.yml
@@ -0,0 +1,16 @@
+version: "2"
+
+linters:
+  settings:
+    golicenser:
+      header:
+        author: "golangci-lint"
+        template: |-
+          Copyright (c) {{.year}} {{.author}} <{{.email}}>.
+          This file is a part of {{.projectname}}.
+        variables:
+          email:
+            value: "test@example.com"
+            regexp: "(.+)@example\\.com"
+          projectname:
+            value: "golangci-lint"
diff --git a/pkg/golinters/golicenser/testdata/golicenser-template-path.yml b/pkg/golinters/golicenser/testdata/golicenser-template-path.yml
new file mode 100644
index 000000000000..5590532eb655
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/golicenser-template-path.yml
@@ -0,0 +1,14 @@
+version: "2"
+
+linters:
+  settings:
+    golicenser:
+      header:
+        author: "golangci-lint"
+        template-path: "${config-path}/license-example.txt"
+        variables:
+          email:
+            value: "test@example.com"
+            regexp: "(.+)@example\\.com"
+          projectname:
+            value: "golangci-lint"
diff --git a/pkg/golinters/golicenser/testdata/golicenser.yml b/pkg/golinters/golicenser/testdata/golicenser.yml
new file mode 100644
index 000000000000..9db8e570bedf
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/golicenser.yml
@@ -0,0 +1,20 @@
+version: "2"
+
+linters:
+  settings:
+    golicenser:
+      header:
+        author: "golangci-lint"
+        template: |-
+          Copyright (c) {{.year}} {{.author}} <{{.email}}>.
+          This file is a part of {{.projectname}}.
+        # Allow matcher to match "// want" comments, otherwise they break matching.
+        matcher: |-
+          Copyright \(c\) {{.year}} {{.author}} <{{.email}}>\.(\s// want.+)?
+          This file is a part of {{.projectname}}\.
+        variables:
+          email:
+            value: "test@example.com"
+            regexp: "(.+)@example\\.com"
+          projectname:
+            value: "golangci-lint"
diff --git a/pkg/golinters/golicenser/testdata/golicenser_cgo.go b/pkg/golinters/golicenser/testdata/golicenser_cgo.go
new file mode 100644
index 000000000000..9cd30c66f7ac
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/golicenser_cgo.go
@@ -0,0 +1,28 @@
+//go:build ignore
+
+// Copyright (c) 2025 golangci-lint <someone@example.com>. // want "invalid license header"
+// This file is a part of golangci-lint.
+
+//golangcitest:args -Egolicenser
+//golangcitest:config_path testdata/golicenser.yml
+package testdata
+
+/*
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ void myprint(char* s) {
+ 	printf("%d\n", s);
+ }
+*/
+import "C"
+
+import (
+	"unsafe"
+)
+
+func _() {
+	cs := C.CString("Hello from stdio\n")
+	C.myprint(cs)
+	C.free(unsafe.Pointer(cs))
+}
diff --git a/pkg/golinters/golicenser/testdata/golicenser_different.go b/pkg/golinters/golicenser/testdata/golicenser_different.go
new file mode 100644
index 000000000000..1ee781e3d6a0
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/golicenser_different.go
@@ -0,0 +1,8 @@
+// Copyright (c) 2025 Someone else
+// This file has a different license header which matches the copyright header
+// matcher but not the license header matcher, therefore it should not be updated.
+
+//golangcitest:args -Egolicenser
+//golangcitest:config_path testdata/golicenser.yml
+//golangcitest:expected_exitcode 0
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/golicenser_good.go b/pkg/golinters/golicenser/testdata/golicenser_good.go
new file mode 100644
index 000000000000..1e4f25d66703
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/golicenser_good.go
@@ -0,0 +1,7 @@
+// Copyright (c) 2025 golangci-lint <test@example.com>.
+// This file is a part of golangci-lint.
+
+//golangcitest:args -Egolicenser
+//golangcitest:config_path testdata/golicenser.yml
+//golangcitest:expected_exitcode 0
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/golicenser_missing.go b/pkg/golinters/golicenser/testdata/golicenser_missing.go
new file mode 100644
index 000000000000..754a6f1e1edb
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/golicenser_missing.go
@@ -0,0 +1,5 @@
+// want "missing license header"
+
+//golangcitest:args -Egolicenser
+//golangcitest:config_path testdata/golicenser.yml
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/golicenser_missing_tp.go b/pkg/golinters/golicenser/testdata/golicenser_missing_tp.go
new file mode 100644
index 000000000000..2d6de7710f0d
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/golicenser_missing_tp.go
@@ -0,0 +1,5 @@
+// want "missing license header"
+
+//golangcitest:args -Egolicenser
+//golangcitest:config_path testdata/golicenser-template-path.yml
+package testdata
diff --git a/pkg/golinters/golicenser/testdata/golicenser_outdated.go b/pkg/golinters/golicenser/testdata/golicenser_outdated.go
new file mode 100644
index 000000000000..bd6ff941d60c
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/golicenser_outdated.go
@@ -0,0 +1,12 @@
+// Copyright (c) 2025 golangci-lint <someone@example.com>. // want "invalid license header"
+// This file is a part of golangci-lint.
+
+//golangcitest:args -Egolicenser
+//golangcitest:config_path testdata/golicenser.yml
+package testdata
+
+import "fmt"
+
+func main() {
+	fmt.Println("Hello, world!")
+}
diff --git a/pkg/golinters/golicenser/testdata/license-example.txt b/pkg/golinters/golicenser/testdata/license-example.txt
new file mode 100644
index 000000000000..e668545c2548
--- /dev/null
+++ b/pkg/golinters/golicenser/testdata/license-example.txt
@@ -0,0 +1,2 @@
+Copyright (c) {{.year}} {{.author}} <{{.email}}>.
+This file is a part of {{.projectname}}.
diff --git a/pkg/lint/lintersdb/builder_linter.go b/pkg/lint/lintersdb/builder_linter.go
index 5ac3e5ba2fb0..8e701a0e1462 100644
--- a/pkg/lint/lintersdb/builder_linter.go
+++ b/pkg/lint/lintersdb/builder_linter.go
@@ -47,6 +47,7 @@ import (
 	"github.com/golangci/golangci-lint/v2/pkg/golinters/gofumpt"
 	"github.com/golangci/golangci-lint/v2/pkg/golinters/goheader"
 	"github.com/golangci/golangci-lint/v2/pkg/golinters/goimports"
+	"github.com/golangci/golangci-lint/v2/pkg/golinters/golicenser"
 	"github.com/golangci/golangci-lint/v2/pkg/golinters/golines"
 	"github.com/golangci/golangci-lint/v2/pkg/golinters/gomoddirectives"
 	"github.com/golangci/golangci-lint/v2/pkg/golinters/gomodguard"
@@ -353,6 +354,11 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
 			WithAutoFix().
 			WithURL("https://github.com/denis-tingaikin/go-header"),
 
+		linter.NewConfig(golicenser.New(&cfg.Linters.Settings.Golicenser, placeholderReplacer)).
+			WithSince("v2.2.0").
+			WithAutoFix().
+			WithURL("https://github.com/joshuasing/golicenser"),
+
 		linter.NewConfig(goimports.New(&cfg.Linters.Settings.GoImports)).
 			WithSince("v1.20.0").
 			WithAutoFix().