diff --git a/internal/rule/ruleconfiguration/ruleconfiguration.go b/internal/rule/ruleconfiguration/ruleconfiguration.go
index 208aa9f9..c8a95daf 100644
--- a/internal/rule/ruleconfiguration/ruleconfiguration.go
+++ b/internal/rule/ruleconfiguration/ruleconfiguration.go
@@ -2857,6 +2857,38 @@ var configurations = []Type{
 		ErrorModes:       []rulemode.Type{rulemode.Default},
 		RuleFunction:     rulefunction.PackageIndexMissing,
 	},
+	{
+		ProjectType:      projecttype.PackageIndex,
+		SuperprojectType: projecttype.All,
+		Category:         "data",
+		Subcategory:      "general",
+		ID:               "IS002",
+		Brief:            "invalid filename",
+		Description:      "",
+		MessageTemplate:  "Invalid package index filename {{.}}. See: https://arduino.github.io/arduino-cli/latest/package_index_json-specification/",
+		DisableModes:     []rulemode.Type{rulemode.Official},
+		EnableModes:      []rulemode.Type{rulemode.Default},
+		InfoModes:        nil,
+		WarningModes:     nil,
+		ErrorModes:       []rulemode.Type{rulemode.Default},
+		RuleFunction:     rulefunction.PackageIndexFilenameInvalid,
+	},
+	{
+		ProjectType:      projecttype.PackageIndex,
+		SuperprojectType: projecttype.All,
+		Category:         "data",
+		Subcategory:      "general",
+		ID:               "IS003",
+		Brief:            "invalid official filename",
+		Description:      "",
+		MessageTemplate:  "Invalid official package index filename {{.}}. See: https://arduino.github.io/arduino-cli/latest/package_index_json-specification/",
+		DisableModes:     []rulemode.Type{rulemode.Default},
+		EnableModes:      []rulemode.Type{rulemode.Official},
+		InfoModes:        nil,
+		WarningModes:     nil,
+		ErrorModes:       []rulemode.Type{rulemode.Default},
+		RuleFunction:     rulefunction.PackageIndexOfficialFilenameInvalid,
+	},
 	{
 		ProjectType:      projecttype.PackageIndex,
 		SuperprojectType: projecttype.All,
diff --git a/internal/rule/rulefunction/packageindex.go b/internal/rule/rulefunction/packageindex.go
index 13fe707c..a112c012 100644
--- a/internal/rule/rulefunction/packageindex.go
+++ b/internal/rule/rulefunction/packageindex.go
@@ -16,6 +16,7 @@
 package rulefunction
 
 import (
+	"github.com/arduino/arduino-lint/internal/project/packageindex"
 	"github.com/arduino/arduino-lint/internal/project/projectdata"
 	"github.com/arduino/arduino-lint/internal/rule/ruleresult"
 )
@@ -31,6 +32,32 @@ func PackageIndexMissing() (result ruleresult.Type, output string) {
 	return ruleresult.Pass, ""
 }
 
+// PackageIndexFilenameInvalid checks whether the package index's filename is valid for 3rd party projects.
+func PackageIndexFilenameInvalid() (result ruleresult.Type, output string) {
+	if projectdata.ProjectPath() == nil {
+		return ruleresult.NotRun, "Package index not found"
+	}
+
+	if packageindex.HasValidFilename(projectdata.ProjectPath(), false) {
+		return ruleresult.Pass, ""
+	}
+
+	return ruleresult.Fail, projectdata.ProjectPath().Base()
+}
+
+// PackageIndexOfficialFilenameInvalid checks whether the package index's filename is valid for official projects.
+func PackageIndexOfficialFilenameInvalid() (result ruleresult.Type, output string) {
+	if projectdata.ProjectPath() == nil {
+		return ruleresult.NotRun, "Package index not found"
+	}
+
+	if packageindex.HasValidFilename(projectdata.ProjectPath(), true) {
+		return ruleresult.Pass, ""
+	}
+
+	return ruleresult.Fail, projectdata.ProjectPath().Base()
+}
+
 // PackageIndexJSONFormat checks whether the package index file is a valid JSON document.
 func PackageIndexJSONFormat() (result ruleresult.Type, output string) {
 	if projectdata.ProjectPath() == nil {
diff --git a/internal/rule/rulefunction/packageindex_test.go b/internal/rule/rulefunction/packageindex_test.go
index 74868de6..e2f17022 100644
--- a/internal/rule/rulefunction/packageindex_test.go
+++ b/internal/rule/rulefunction/packageindex_test.go
@@ -69,6 +69,28 @@ func TestPackageIndexMissing(t *testing.T) {
 	checkPackageIndexRuleFunction(PackageIndexMissing, testTables, t)
 }
 
+func TestPackageIndexFilenameInvalid(t *testing.T) {
+	testTables := []packageIndexRuleFunctionTestTable{
+		{"Missing", "missing", ruleresult.NotRun, ""},
+		{"Valid 3rd party", "3rd-party-filename", ruleresult.Pass, ""},
+		{"Valid official", "official-filename", ruleresult.Fail, "^package_index.json$"},
+		{"Invalid", "invalid-filename", ruleresult.Fail, "^invalid-filename.json$"},
+	}
+
+	checkPackageIndexRuleFunction(PackageIndexFilenameInvalid, testTables, t)
+}
+
+func TestPackageIndexOfficialFilenameInvalid(t *testing.T) {
+	testTables := []packageIndexRuleFunctionTestTable{
+		{"Missing", "missing", ruleresult.NotRun, ""},
+		{"Valid 3rd party", "3rd-party-filename", ruleresult.Pass, ""},
+		{"Valid official", "official-filename", ruleresult.Pass, ""},
+		{"Invalid", "invalid-filename", ruleresult.Fail, "^invalid-filename.json$"},
+	}
+
+	checkPackageIndexRuleFunction(PackageIndexOfficialFilenameInvalid, testTables, t)
+}
+
 func TestPackageIndexJSONFormat(t *testing.T) {
 	testTables := []packageIndexRuleFunctionTestTable{
 		{"Invalid JSON", "invalid-JSON", ruleresult.Fail, ""},
diff --git a/internal/rule/rulefunction/testdata/packageindexes/3rd-party-filename/package_3rd-party_index.json b/internal/rule/rulefunction/testdata/packageindexes/3rd-party-filename/package_3rd-party_index.json
new file mode 100644
index 00000000..7938a2aa
--- /dev/null
+++ b/internal/rule/rulefunction/testdata/packageindexes/3rd-party-filename/package_3rd-party_index.json
@@ -0,0 +1,51 @@
+{
+  "packages": [
+    {
+      "name": "notarduino",
+      "maintainer": "NotArduino",
+      "websiteURL": "http://www.arduino.cc/",
+      "email": "packages@arduino.cc",
+      "help": {
+        "online": "http://www.arduino.cc/en/Reference/HomePage"
+      },
+      "platforms": [
+        {
+          "name": "Arduino AVR Boards",
+          "architecture": "avr",
+          "version": "1.8.3",
+          "category": "Contributed",
+          "help": {
+            "online": "http://www.arduino.cc/en/Reference/HomePage"
+          },
+          "url": "http://downloads.arduino.cc/cores/avr-1.8.3.tar.bz2",
+          "archiveFileName": "avr-1.8.3.tar.bz2",
+          "checksum": "SHA-256:de8a9b982477762d3d3e52fc2b682cdd8ff194dc3f1d46f4debdea6a01b33c14",
+          "size": "4941548",
+          "boards": [{ "name": "Arduino Uno" }],
+          "toolsDependencies": [
+            {
+              "packager": "arduino",
+              "name": "avr-gcc",
+              "version": "7.3.0-atmel3.6.1-arduino7"
+            }
+          ]
+        }
+      ],
+      "tools": [
+        {
+          "name": "avr-gcc",
+          "version": "7.3.0-atmel3.6.1-arduino7",
+          "systems": [
+            {
+              "size": "34683056",
+              "checksum": "SHA-256:3903553d035da59e33cff9941b857c3cb379cb0638105dfdf69c97f0acc8e7b5",
+              "host": "arm-linux-gnueabihf",
+              "archiveFileName": "avr-gcc-7.3.0-atmel3.6.1-arduino7-arm-linux-gnueabihf.tar.bz2",
+              "url": "http://downloads.arduino.cc/tools/avr-gcc-7.3.0-atmel3.6.1-arduino7-arm-linux-gnueabihf.tar.bz2"
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/internal/rule/rulefunction/testdata/packageindexes/invalid-filename/invalid-filename.json b/internal/rule/rulefunction/testdata/packageindexes/invalid-filename/invalid-filename.json
new file mode 100644
index 00000000..7938a2aa
--- /dev/null
+++ b/internal/rule/rulefunction/testdata/packageindexes/invalid-filename/invalid-filename.json
@@ -0,0 +1,51 @@
+{
+  "packages": [
+    {
+      "name": "notarduino",
+      "maintainer": "NotArduino",
+      "websiteURL": "http://www.arduino.cc/",
+      "email": "packages@arduino.cc",
+      "help": {
+        "online": "http://www.arduino.cc/en/Reference/HomePage"
+      },
+      "platforms": [
+        {
+          "name": "Arduino AVR Boards",
+          "architecture": "avr",
+          "version": "1.8.3",
+          "category": "Contributed",
+          "help": {
+            "online": "http://www.arduino.cc/en/Reference/HomePage"
+          },
+          "url": "http://downloads.arduino.cc/cores/avr-1.8.3.tar.bz2",
+          "archiveFileName": "avr-1.8.3.tar.bz2",
+          "checksum": "SHA-256:de8a9b982477762d3d3e52fc2b682cdd8ff194dc3f1d46f4debdea6a01b33c14",
+          "size": "4941548",
+          "boards": [{ "name": "Arduino Uno" }],
+          "toolsDependencies": [
+            {
+              "packager": "arduino",
+              "name": "avr-gcc",
+              "version": "7.3.0-atmel3.6.1-arduino7"
+            }
+          ]
+        }
+      ],
+      "tools": [
+        {
+          "name": "avr-gcc",
+          "version": "7.3.0-atmel3.6.1-arduino7",
+          "systems": [
+            {
+              "size": "34683056",
+              "checksum": "SHA-256:3903553d035da59e33cff9941b857c3cb379cb0638105dfdf69c97f0acc8e7b5",
+              "host": "arm-linux-gnueabihf",
+              "archiveFileName": "avr-gcc-7.3.0-atmel3.6.1-arduino7-arm-linux-gnueabihf.tar.bz2",
+              "url": "http://downloads.arduino.cc/tools/avr-gcc-7.3.0-atmel3.6.1-arduino7-arm-linux-gnueabihf.tar.bz2"
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
diff --git a/internal/rule/rulefunction/testdata/packageindexes/official-filename/package_index.json b/internal/rule/rulefunction/testdata/packageindexes/official-filename/package_index.json
new file mode 100644
index 00000000..b8a62038
--- /dev/null
+++ b/internal/rule/rulefunction/testdata/packageindexes/official-filename/package_index.json
@@ -0,0 +1,51 @@
+{
+  "packages": [
+    {
+      "name": "arduino",
+      "maintainer": "Arduino",
+      "websiteURL": "http://www.arduino.cc/",
+      "email": "packages@arduino.cc",
+      "help": {
+        "online": "http://www.arduino.cc/en/Reference/HomePage"
+      },
+      "platforms": [
+        {
+          "name": "Arduino AVR Boards",
+          "architecture": "avr",
+          "version": "1.8.3",
+          "category": "Arduino",
+          "help": {
+            "online": "http://www.arduino.cc/en/Reference/HomePage"
+          },
+          "url": "http://downloads.arduino.cc/cores/avr-1.8.3.tar.bz2",
+          "archiveFileName": "avr-1.8.3.tar.bz2",
+          "checksum": "SHA-256:de8a9b982477762d3d3e52fc2b682cdd8ff194dc3f1d46f4debdea6a01b33c14",
+          "size": "4941548",
+          "boards": [{ "name": "Arduino Uno" }],
+          "toolsDependencies": [
+            {
+              "packager": "arduino",
+              "name": "avr-gcc",
+              "version": "7.3.0-atmel3.6.1-arduino7"
+            }
+          ]
+        }
+      ],
+      "tools": [
+        {
+          "name": "avr-gcc",
+          "version": "7.3.0-atmel3.6.1-arduino7",
+          "systems": [
+            {
+              "size": "34683056",
+              "checksum": "SHA-256:3903553d035da59e33cff9941b857c3cb379cb0638105dfdf69c97f0acc8e7b5",
+              "host": "arm-linux-gnueabihf",
+              "archiveFileName": "avr-gcc-7.3.0-atmel3.6.1-arduino7-arm-linux-gnueabihf.tar.bz2",
+              "url": "http://downloads.arduino.cc/tools/avr-gcc-7.3.0-atmel3.6.1-arduino7-arm-linux-gnueabihf.tar.bz2"
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}