diff --git a/docs/platform-specification.md b/docs/platform-specification.md
index 11b21249bd1..8d01bb098dd 100644
--- a/docs/platform-specification.md
+++ b/docs/platform-specification.md
@@ -83,8 +83,9 @@ suffixes are `.linux`, `.windows` and `.macosx`.
 
 The following automatically generated properties can be used globally in all configuration files:
 
-- `{runtime.platform.path}`: the absolute path of the [board platform](#platform-terminology) folder (i.e. the folder
-  containing boards.txt)
+- `{runtime.platform.path}`: is the absolute path of the [board platform](#platform-terminology) folder (i.e. the folder
+  containing boards.txt) unless `{runtime.use_core_platform_path_for_runtime_platform_path}` is set to `true` in this
+  case, the value is the absolute path of the referenced core platform.
 - `{runtime.hardware.path}`: the absolute path of the hardware folder (i.e. the folder containing the
   [board platform](#platform-terminology) folder)
 - `{runtime.ide.path}`: the absolute path of the Arduino IDE or Arduino CLI folder
@@ -113,8 +114,11 @@ The following automatically generated properties can be used globally in all con
 - `{extra.time.zone}`: local timezone offset without the DST component
 - `{extra.time.dst}`: local daylight savings time offset
 
-Compatibility note: Versions before Arduino IDE 1.6.0 only used one digit per version number component in
-`{runtime.ide.version}` (so 1.5.9 was `159`, not `10509`).
+Compatibility notes:
+
+- Versions before Arduino IDE 1.6.0 only used one digit per version number component in `{runtime.ide.version}` (so
+  1.5.9 was `159`, not `10509`).
+- `{runtime.use_core_platform_path_for_runtime_platform_path}` support is available from Arduino CLI >=1.0.4.
 
 ## platform.txt
 
@@ -534,6 +538,9 @@ This explains the presence of **{build.mcu}** or **{build.board}** in the platfo
 overwritten respectively by **{uno.build.mcu}** and **{uno.build.board}** when the Uno board is selected! Moreover the
 following properties are automatically generated:
 
+- `{build.board.platform.path}`: The path to the selected board's platform. (available since Arduino CLI >=1.0.4)
+- `{build.core.platform.path}`: The path to the core's platform. It may differ from the board's platform path because
+  the latter may reference a core from another platform. (available since Arduino CLI >=1.0.4)
 - `{build.core.path}`: The path to the selected board's core folder (inside the [core platform](#platform-terminology),
   for example hardware/arduino/avr/core/arduino)
 - `{build.system.path}`: The path to the [core platform](#platform-terminology)'s system folder if available (for
diff --git a/go.mod b/go.mod
index e495b5a2e7a..7481a151b00 100644
--- a/go.mod
+++ b/go.mod
@@ -37,7 +37,7 @@ require (
 	go.bug.st/cleanup v1.0.0
 	go.bug.st/downloader/v2 v2.2.0
 	go.bug.st/relaxed-semver v0.12.0
-	go.bug.st/testifyjson v1.1.1
+	go.bug.st/testifyjson v1.2.0
 	golang.org/x/term v0.22.0
 	golang.org/x/text v0.16.0
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157
diff --git a/go.sum b/go.sum
index 7c8bc44a9e8..c3ff0cd2e62 100644
--- a/go.sum
+++ b/go.sum
@@ -219,8 +219,8 @@ go.bug.st/relaxed-semver v0.12.0 h1:se8v3lTdAAFp68+/RS/0Y/nFdnpdzkP5ICY04SPau4E=
 go.bug.st/relaxed-semver v0.12.0/go.mod h1:Cpcbiig6Omwlq6bS7i3MQWiqS7W7HDd8CAnZFC40Cl0=
 go.bug.st/serial v1.6.1 h1:VSSWmUxlj1T/YlRo2J104Zv3wJFrjHIl/T3NeruWAHY=
 go.bug.st/serial v1.6.1/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
-go.bug.st/testifyjson v1.1.1 h1:nHotIMK151LF3vYsU/b2RaoVaWCgrf2kvQeGNoZkGaA=
-go.bug.st/testifyjson v1.1.1/go.mod h1:nZyy2icFbv3OE3zW3mGVOnC/GhWgb93LRu+29n2tJlI=
+go.bug.st/testifyjson v1.2.0 h1:0pAfOUMVCOJ6bb9JcC4UmnACjxwxv2Ojb6Z9chaQBjg=
+go.bug.st/testifyjson v1.2.0/go.mod h1:nZyy2icFbv3OE3zW3mGVOnC/GhWgb93LRu+29n2tJlI=
 go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
 go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
diff --git a/internal/arduino/cores/packagemanager/package_manager.go b/internal/arduino/cores/packagemanager/package_manager.go
index 2821b23ddb4..aaaf675a410 100644
--- a/internal/arduino/cores/packagemanager/package_manager.go
+++ b/internal/arduino/cores/packagemanager/package_manager.go
@@ -372,12 +372,17 @@ func (pme *Explorer) ResolveFQBN(fqbn *cores.FQBN) (
 
 	// Add runtime build properties
 	buildProperties.Merge(boardPlatformRelease.RuntimeProperties())
+	buildProperties.SetPath("build.board.platform.path", boardPlatformRelease.InstallDir)
+	buildProperties.SetPath("build.core.platform.path", corePlatformRelease.InstallDir)
 	buildProperties.SetPath("build.core.path", corePlatformRelease.InstallDir.Join("cores", core))
 	buildProperties.SetPath("build.system.path", corePlatformRelease.InstallDir.Join("system"))
 	buildProperties.Set("build.variant.path", "")
 	if variant != "" {
 		buildProperties.SetPath("build.variant.path", variantPlatformRelease.InstallDir.Join("variants", variant))
 	}
+	if buildProperties.GetBoolean("runtime.use_core_platform_path_for_runtime_platform_path") {
+		buildProperties.Set("runtime.platform.path", buildProperties.Get("build.core.platform.path"))
+	}
 
 	for _, tool := range pme.GetAllInstalledToolsReleases() {
 		buildProperties.Merge(tool.RuntimeProperties())
diff --git a/internal/integrationtest/core/core_test.go b/internal/integrationtest/core/core_test.go
index fbda8da1c0c..1f8850f0856 100644
--- a/internal/integrationtest/core/core_test.go
+++ b/internal/integrationtest/core/core_test.go
@@ -18,6 +18,7 @@ package core_test
 import (
 	"crypto/md5"
 	"encoding/hex"
+	"encoding/json"
 	"fmt"
 	"os"
 	"path/filepath"
@@ -1303,3 +1304,50 @@ func TestCoreHavingIncompatibleDepTools(t *testing.T) {
 		require.Contains(t, lines, []string{"incompatible_vendor:avr", "n/a", "Incompatible", "Boards"})
 	}
 }
+
+func TestReferencedCoreBuildAndRuntimeProperties(t *testing.T) {
+	env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
+	defer env.CleanUp()
+
+	_, _, err := cli.Run("core", "install", "arduino:avr@1.8.6")
+	require.NoError(t, err)
+
+	testSketchbook, err := paths.New("testdata", "sketchbook_with_extended_platform").Abs()
+	require.NoError(t, err)
+
+	// Install custom platform
+	err = testSketchbook.Join("hardware").CopyDirTo(cli.SketchbookDir().Join("hardware"))
+	require.NoError(t, err)
+
+	// Determine some useful paths
+	boardPlatformPath := cli.SketchbookDir().Join("hardware", "test", "avr").String()
+	corePlatformPath := cli.DataDir().Join("packages", "arduino", "hardware", "avr", "1.8.6").String()
+	corePath := cli.DataDir().Join("packages", "arduino", "hardware", "avr", "1.8.6", "cores", "arduino").String()
+
+	jsonEncode := func(in string) string {
+		enc, err := json.Marshal(in)
+		require.NoError(t, err)
+		return string(enc)
+	}
+
+	// Check runtime variables are populated correctly
+	{
+		outJson, _, err := cli.Run("board", "details", "-b", "test:avr:test", "--show-properties", "--json")
+		require.NoError(t, err)
+		out := requirejson.Parse(t, outJson).Query(".build_properties")
+		out.ArrayMustContain(jsonEncode("build.board.platform.path=" + boardPlatformPath))
+		out.ArrayMustContain(jsonEncode("build.core.platform.path=" + corePlatformPath))
+		out.ArrayMustContain(jsonEncode("build.core.path=" + corePath))
+		out.ArrayMustContain(jsonEncode("runtime.platform.path=" + boardPlatformPath))
+	}
+	{
+		outJson, _, err := cli.Run("board", "details", "-b", "test:avr:test2", "--show-properties", "--json")
+		require.NoError(t, err)
+		out := requirejson.Parse(t, outJson).Query(".build_properties")
+		out.ArrayMustContain(jsonEncode("build.board.platform.path=" + boardPlatformPath))
+		out.ArrayMustContain(jsonEncode("build.core.platform.path=" + corePlatformPath))
+		out.ArrayMustContain(jsonEncode("build.core.path=" + corePath))
+		// https://github.com/arduino/arduino-cli/issues/2616
+		out.ArrayMustContain(jsonEncode("runtime.platform.path=" + corePlatformPath))
+	}
+}
diff --git a/internal/integrationtest/core/testdata/sketchbook_with_extended_platform/hardware/test/avr/boards.txt b/internal/integrationtest/core/testdata/sketchbook_with_extended_platform/hardware/test/avr/boards.txt
new file mode 100644
index 00000000000..24f046b561a
--- /dev/null
+++ b/internal/integrationtest/core/testdata/sketchbook_with_extended_platform/hardware/test/avr/boards.txt
@@ -0,0 +1,7 @@
+
+test.name=Test Board
+test.build.core=arduino:arduino
+
+test2.name=Test 2 Board
+test2.build.core=arduino:arduino
+test2.runtime.use_core_platform_path_for_runtime_platform_path=true