diff --git a/cmake/fetch_kdeaddons.cmake b/cmake/fetch_kdeaddons.cmake index 76df0a3f4..561ed3550 100644 --- a/cmake/fetch_kdeaddons.cmake +++ b/cmake/fetch_kdeaddons.cmake @@ -23,8 +23,31 @@ if(BUILD_WITH_KF) if(BUILD_KF) - if(NOT DEFINED KF_GIT_TAG) - # this is a more or less random version, taken as an conservative approach + # v6.10.0 is a more or less random version, taken as an conservative + # approach. Pinned to the commits v6.10.0 points at, not to the tags + # themselves; see the note in fetch_pugixml.cmake. Each module lives in its + # own repository, so the same v6.10.0 release is a different commit in + # each. + # + # KDE uses annotated tags, so "git ls-remote 'refs/tags/v6.10.0*'" + # prints two hashes per module: refs/tags/v6.10.0 is the tag object (the + # tagger, the date and the tag message) and refs/tags/v6.10.0^{} is the + # commit that object points at. The hashes below are the "^{}" ones, i.e. + # the commits. Lightweight tags, such as pugixml's v1.15 and + # SingleApplication's v3.2.0, have no tag object and print only the + # commit line. + set(KF_ECM_GIT_COMMIT 7dd28cc56c339c3f8fb356f7c53c0e8f61433d81) # v6.10.0 + set(KF_KCOREADDONS_GIT_COMMIT c569f974dab24b4784ad186a3db4b76b2fa36612) # v6.10.0 + set(KF_KWIDGETSADDONS_GIT_COMMIT 1abbed8a280d6626c59fb197f2c4667d2b1e7445) # v6.10.0 + + if(DEFINED KF_GIT_TAG) + # Explicit override: -DKF_GIT_TAG= selects one ref for all three + # modules, unpinned, exactly as it did before. + set(KF_ECM_GIT_COMMIT ${KF_GIT_TAG}) + set(KF_KCOREADDONS_GIT_COMMIT ${KF_GIT_TAG}) + set(KF_KWIDGETSADDONS_GIT_COMMIT ${KF_GIT_TAG}) + else() + # Keep KF_GIT_TAG defined: define_definitions.cmake reports it. set(KF_GIT_TAG v6.10.0) endif() # using a function in order to limit the scope of the variables @@ -53,19 +76,19 @@ if(BUILD_WITH_KF) FetchContent_Declare( ecm GIT_REPOSITORY https://invent.kde.org/frameworks/extra-cmake-modules.git - GIT_TAG ${KF_GIT_TAG}) + GIT_TAG ${KF_ECM_GIT_COMMIT}) FetchContent_MakeAvailable(ecm) FetchContent_Declare( kcoreaddons GIT_REPOSITORY https://invent.kde.org/frameworks/kcoreaddons.git - GIT_TAG ${KF_GIT_TAG}) + GIT_TAG ${KF_KCOREADDONS_GIT_COMMIT}) FetchContent_MakeAvailable(kcoreaddons) FetchContent_Declare( kwidgetsaddons GIT_REPOSITORY https://invent.kde.org/frameworks/kwidgetsaddons.git - GIT_TAG ${KF_GIT_TAG}) + GIT_TAG ${KF_KWIDGETSADDONS_GIT_COMMIT}) FetchContent_MakeAvailable(kwidgetsaddons) endfunction() qet_make_kf_available() diff --git a/cmake/fetch_pugixml.cmake b/cmake/fetch_pugixml.cmake index 6aef219f7..25f235570 100644 --- a/cmake/fetch_pugixml.cmake +++ b/cmake/fetch_pugixml.cmake @@ -22,10 +22,51 @@ option(BUILD_PUGIXML "Build pugixml library, use system one otherwise" YES) if(BUILD_PUGIXML) + # Pinned to the commit v1.15 points at, not to the tag itself. + # + # A git tag is only a named pointer to a commit, and anyone with push access + # to the upstream repository can move it (git push --force) to any other + # commit. FetchContent fetches whatever the tag points at when the build + # runs, so if a maintainer account or CI token is compromised, the attacker + # can retarget a well-known release tag to malicious code: every fresh build + # of QElectroTech then compiles it, while nothing changes in this repository + # and the tag name still looks correct. A commit hash cannot be moved, because + # it is derived from the content: different code always has a different hash. + # + # This attack has been used in the wild: + # - March 2025, tj-actions/changed-files (CVE-2025-30066): tags v1 through + # v45.0.7 were retargeted to a commit that dumped CI secrets into build + # logs, affecting more than 23,000 repositories. + # - March 2026, aquasecurity/trivy-action (CVE-2026-33634): 76 of 77 + # version tags were force-pushed to a credential stealer and stayed + # malicious for about 12 hours. + # Both were GitHub Actions rather than CMake dependencies, but the mechanism + # is the same one FetchContent relies on here: resolving a git tag at build + # time. + # + # To upgrade, look up the commit the new tag points at with + # git ls-remote 'refs/tags/*', check that it is the release you + # expect, and update both the hash and the trailing tag comment. + # + # How many lines that prints depends on which of the two kinds of tag + # upstream created: + # - A lightweight tag is nothing but a ref pointing straight at the commit, + # so ls-remote prints a single line, "refs/tags/", and its hash is + # the commit to pin. pugixml tags this way, which is why the v1.15 hash + # below is what "git ls-remote ... refs/tags/v1.15" reports directly; + # SingleApplication (v3.2.0) does the same. + # - An annotated tag is a git object in its own right, carrying a tagger, + # a date, a message and optionally a GPG signature, and pointing at the + # commit. ls-remote then prints two lines: "refs/tags/" is the tag + # object and "refs/tags/^{}" is that object dereferenced, i.e. the + # commit. The KDE Frameworks modules tag this way, so for them it is the + # "^{}" hash that belongs in the pin; the other hash identifies the tag + # object itself, which is not the source revision and changes whenever + # upstream re-creates the tag, even over the very same commit. FetchContent_Declare( pugixml GIT_REPOSITORY https://github.com/zeux/pugixml.git - GIT_TAG v1.15) + GIT_TAG ee86beb30e4973f5feffe3ce63bfa4fbadf72f38) # v1.15 set(PUGIXML_INSTALL OFF CACHE INTERNAL "") FetchContent_MakeAvailable(pugixml) else() diff --git a/cmake/fetch_singleapplication.cmake b/cmake/fetch_singleapplication.cmake index c54de59ef..6983dfc2b 100644 --- a/cmake/fetch_singleapplication.cmake +++ b/cmake/fetch_singleapplication.cmake @@ -31,9 +31,15 @@ if(EXISTS "${CMAKE_SOURCE_DIR}/SingleApplication/CMakeLists.txt") set(FETCHCONTENT_SOURCE_DIR_SINGLEAPPLICATION "${CMAKE_SOURCE_DIR}/SingleApplication") endif() +# Pinned to the commit v3.2.0 points at, not to the tag itself; see the note in +# fetch_pugixml.cmake. v3.2.0 is a lightweight tag, a ref pointing straight at +# the commit, so "git ls-remote refs/tags/v3.2.0" prints that commit and +# nothing else. An annotated tag, as KDE uses in fetch_kdeaddons.cmake, would +# print the tag object under refs/tags/v3.2.0 as well, with the commit on the +# refs/tags/v3.2.0^{} line. FetchContent_Declare( SingleApplication GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication.git - GIT_TAG v3.2.0) + GIT_TAG aede311d28d20179216c5419b581087be2a8409f) # v3.2.0 set(QT_DEFAULT_MAJOR_VERSION 6) FetchContent_MakeAvailable(SingleApplication)