Rules / GRN-T002
GRN-T002 publisher-changed
| Default severity | warn |
| Kind | diff rule: fires only when the trusted version had the property and the new version lost it, or the new version gained a risky property the trusted version lacked. |
| Status | Implemented in 0.1 |
What it checks
The source repository named in the new version's verified attestations differs from the one named in the trusted version's attestations.
Repository renames that GitHub redirects don't fire: the rule compares GitHub's repository id, which survives a rename.
Why it matters
An attestation names the repository whose CI built the release. A different repository means a different CI published this version. That can be a fork, a move to a new organization, or an attacker's repository that has been granted publishing rights.
Example finding
Illustrative; not from a real release.
examplelib 2.6.1 → 2.6.2: WARN
WARN GRN-T002 publisher-changed: 2.6.2 was published from github.com/someone-else/examplelib, not github.com/example/examplelib
- examplelib-2.6.2-py3-none-any.whl: github.com/someone-else/examplelib
How to resolve it
- Confirm the move from the old home: release notes, the README, or an announcement in the old repository. Don't rely on what the new repository says about itself.
- If the move is real, merge and add an ignore for this version. Later releases from the new repository compare against this one and stay quiet.
Allowlisting
Once you've reviewed a release, ignore this rule for that package and version range.
Every ignore needs a reason and an expiry date; after until it stops applying and the
report notes that it expired.
[[garnet.ignore]]
package = "examplelib"
versions = "==2.6.2"
rules = ["GRN-T002"]
reason = "project moved to the example-org organization (announced in example/examplelib#200)"
until = "2027-06-30"
To change the rule's severity for every package instead:
[garnet.rules]
"GRN-T002" = "block" # "off" | "info" | "warn" | "block"
Suppressed findings still appear in JSON and SARIF output, marked with the ignore that
matched. The policy format is in SPEC §7; 0.1's garnet diff
doesn't read policy files yet.