Spec 8 updates
We only have some minor additions to the SPEC 8:
- separate job that builds the wheel from job that does the upload. Upload job should just download from GitHub artifact and upload to PyPi/conda/etc.
- zero permissions at top level, permissions in job
-
- hashes in GitHub Actions pinning: better to be consistent, updating actions at regular intervals doesn't lead to problems where container expected from actions doesn't match container from workflow
- remove adopt SLSA section, mention that it is included in the trusted publishers
- persisten credentials set to false, https://github.com/sigstore/model-transparency/blob/b4f83c1230fd3f3428bd6f24d84ed4c478c19491/.github/workflows/release.yml#L34
As an example: https://github.com/sigstore/model-transparency/blob/main/.github/workflows/release.yml
In addition to the above, @mihaimaruseac also showed me that there are API docs for PyPI security https://docs.pypi.org/api/integrity/
So for example, the command
curl -H "Accept: application/vnd.pypi.integrity.v1+json" https://pypi.org/integrity/awkward/2.8.2/awkward-2.8.2-py3-none-any.whl/provenance
returns
Return payload:
{"attestation_bundles":[{"attestations":[{"envelope":{"signature":"MEUCIH2R9UEUEqZzegibYLULU8RzuF2VtRnRzcDxwVY4MIXWAiEAzWXwqXrR8E0mrgv92fdxpfEL4CCi8h+FW/DTB86yTFA=","statement":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiYXdrd2FyZC0yLjguMi1weTMtbm9uZS1hbnkud2hsIiwiZGlnZXN0Ijp7InNoYTI1NiI6Ijk4ZWRlMjAwNjFhOWZhOWQyYmRiOWQ1OWQzZWI1MGM0YWFkN2NiYWQwZjlkZjllMTU3YmY2YTRlODhmOGVlOWMifX1dLCJwcmVkaWNhdGVUeXBlIjoiaHR0cHM6Ly9kb2NzLnB5cGkub3JnL2F0dGVzdGF0aW9ucy9wdWJsaXNoL3YxIiwicHJlZGljYXRlIjpudWxsfQ=="},"verification_material":{"certificate":"MIIGtDCCBjqgAwIBAgIUFyay9IAvYne1wnWIkCbMgyLnFa0wCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNTAzMTAzODA2WhcNMjUwNTAzMTA0ODA2WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESXiqgoCohqZcwW4jKwChnBaZe9GldsWeFZuTuAS0lmadWRLmVO7bnlay+A/JK0yalrOtMcOaKv6wvv8dkxo02aOCBVkwggVVMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUxTufY/ZpGpcTcToAZ4MIabVprCowHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wYQYDVR0RAQH/BFcwVYZTaHR0cHM6Ly9naXRodWIuY29tL3NjaWtpdC1oZXAvYXdrd2FyZC8uZ2l0aHViL3dvcmtmbG93cy9kZXBsb3kueW1sQHJlZnMvdGFncy92Mi44LjIwOQYKKwYBBAGDvzABAQQraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTAVBgorBgEEAYO/MAECBAdyZWxlYXNlMDYGCisGAQQBg78wAQMEKDZmOGZiOGNjMmUyODk0Yzk4NGNhOTI3YWRhNGJiYjk0ZmEwZWE5YWEwFAYKKwYBBAGDvzABBAQGRGVwbG95MCAGCisGAQQBg78wAQUEEnNjaWtpdC1oZXAvYXdrd2FyZDAeBgorBgEEAYO/MAEGBBByZWZzL3RhZ3MvdjIuOC4yMDsGCisGAQQBg78wAQgELQwraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTBjBgorBgEEAYO/MAEJBFUMU2h0dHBzOi8vZ2l0aHViLmNvbS9zY2lraXQtaGVwL2F3a3dhcmQvLmdpdGh1Yi93b3JrZmxvd3MvZGVwbG95LnltbEByZWZzL3RhZ3MvdjIuOC4yMDgGCisGAQQBg78wAQoEKgwoNmY4ZmI4Y2MyZTI4OTRjOTg0Y2E5MjdhZGE0YmJiOTRmYTBlYTlhYTAdBgorBgEEAYO/MAELBA8MDWdpdGh1Yi1ob3N0ZWQwNQYKKwYBBAGDvzABDAQnDCVodHRwczovL2dpdGh1Yi5jb20vc2Npa2l0LWhlcC9hd2t3YXJkMDgGCisGAQQBg78wAQ0EKgwoNmY4ZmI4Y2MyZTI4OTRjOTg0Y2E5MjdhZGE0YmJiOTRmYTBlYTlhYTAgBgorBgEEAYO/MAEOBBIMEHJlZnMvdGFncy92Mi44LjIwGQYKKwYBBAGDvzABDwQLDAkyMDI0MTM3NjIwLQYKKwYBBAGDvzABEAQfDB1odHRwczovL2dpdGh1Yi5jb20vc2Npa2l0LWhlcDAYBgorBgEEAYO/MAERBAoMCDIzNDU0NjI0MGMGCisGAQQBg78wARIEVQxTaHR0cHM6Ly9naXRodWIuY29tL3NjaWtpdC1oZXAvYXdrd2FyZC8uZ2l0aHViL3dvcmtmbG93cy9kZXBsb3kueW1sQHJlZnMvdGFncy92Mi44LjIwOAYKKwYBBAGDvzABEwQqDCg2ZjhmYjhjYzJlMjg5NGM5ODRjYTkyN2FkYTRiYmI5NGZhMGVhOWFhMBcGCisGAQQBg78wARQECQwHcmVsZWFzZTBZBgorBgEEAYO/MAEVBEsMSWh0dHBzOi8vZ2l0aHViLmNvbS9zY2lraXQtaGVwL2F3a3dhcmQvYWN0aW9ucy9ydW5zLzE0ODEwMDg4ODY5L2F0dGVtcHRzLzEwFgYKKwYBBAGDvzABFgQIDAZwdWJsaWMwgYsGCisGAQQB1nkCBAIEfQR7AHkAdwDdPTBqxscRMmMZHhyZZzcCokpeuN48rf+HinKALynujgAAAZaVuYqcAAAEAwBIMEYCIQCCbgMymWEVr81Odtn/7ujrbUWxa47lQ+vf2h2HT59d7wIhAKLgwbcp0uEh1QAOxB3fQdkz0vF6s93o7US8iBjC9J5HMAoGCCqGSM49BAMDA2gAMGUCME8IQKdjwV5rX658rgkzDDn1rWRi4TUvsMBxu6LZNM0Az+UsOefGhK1N5uJktoLn4gIxANWSdI2JBe/dk5c27+X2+3FPZtMDiWgHNl5ahP4t7CtGqG+qRlrc52N+k0xm4UQ36A==","transparency_entries":[{"canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiZHNzZSIsInNwZWMiOnsiZW52ZWxvcGVIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiYWM4YWYzYzRmMmQ0Zjc1ZjI0MmIyNWM5YzM4NmFkNDkwYzUyN2NkYmNmNGVjY2I1ZDM5NjgyMDA1ZWVhMTkzOCJ9LCJwYXlsb2FkSGFzaCI6eyJhbGdvcml0aG0iOiJzaGEyNTYiLCJ2YWx1ZSI6Ijk5MmVlYTJlZmYyYjkzMDFjMDM5OTEyNmJlNzFlNjkyZmQ2MGM0YjBkMGZjNjM5NDJiNDgwNzAyNjBiNjJjYWUifSwic2lnbmF0dXJlcyI6W3sic2lnbmF0dXJlIjoiTUVVQ0lIMlI5VUVVRXFaemVnaWJZTFVMVThSenVGMlZ0Um5SemNEeHdWWTRNSVhXQWlFQXpXWHdxWHJSOEUwbXJndjkyZmR4cGZFTDRDQ2k4aCtGVy9EVEI4NnlURkE9IiwidmVyaWZpZXIiOiJMUzB0TFMxQ1JVZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHRDazFKU1VkMFJFTkRRbXB4WjBGM1NVSkJaMGxWUm5saGVUbEpRWFpaYm1VeGQyNVhTV3REWWsxbmVVeHVSbUV3ZDBObldVbExiMXBKZW1vd1JVRjNUWGNLVG5wRlZrMUNUVWRCTVZWRlEyaE5UV015Ykc1ak0xSjJZMjFWZFZwSFZqSk5ValIzU0VGWlJGWlJVVVJGZUZaNllWZGtlbVJIT1hsYVV6RndZbTVTYkFwamJURnNXa2RzYUdSSFZYZElhR05PVFdwVmQwNVVRWHBOVkVGNlQwUkJNbGRvWTA1TmFsVjNUbFJCZWsxVVFUQlBSRUV5VjJwQlFVMUdhM2RGZDFsSUNrdHZXa2w2YWpCRFFWRlpTVXR2V2tsNmFqQkVRVkZqUkZGblFVVlRXR2x4WjI5RGIyaHhXbU4zVnpScVMzZERhRzVDWVZwbE9VZHNaSE5YWlVaYWRWUUtkVUZUTUd4dFlXUlhVa3h0Vms4M1ltNXNZWGtyUVM5S1N6QjVZV3h5VDNSTlkwOWhTM1kyZDNaMk9HUnJlRzh3TW1GUFEwSldhM2RuWjFaV1RVRTBSd3BCTVZWa1JIZEZRaTkzVVVWQmQwbElaMFJCVkVKblRsWklVMVZGUkVSQlMwSm5aM0pDWjBWR1FsRmpSRUY2UVdSQ1owNVdTRkUwUlVablVWVjRWSFZtQ2xrdlduQkhjR05VWTFSdlFWbzBUVWxoWWxad2NrTnZkMGgzV1VSV1VqQnFRa0puZDBadlFWVXpPVkJ3ZWpGWmEwVmFZalZ4VG1wd1MwWlhhWGhwTkZrS1drUTRkMWxSV1VSV1VqQlNRVkZJTDBKR1kzZFdXVnBVWVVoU01HTklUVFpNZVRsdVlWaFNiMlJYU1hWWk1qbDBURE5PYW1GWGRIQmtRekZ2V2xoQmRncFpXR1J5WkRKR2VWcERPSFZhTW13d1lVaFdhVXd6WkhaamJYUnRZa2M1TTJONU9XdGFXRUp6WWpOcmRXVlhNWE5SU0Vwc1dtNU5kbVJIUm01amVUa3lDazFwTkRSTWFrbDNUMUZaUzB0M1dVSkNRVWRFZG5wQlFrRlJVWEpoU0ZJd1kwaE5Oa3g1T1RCaU1uUnNZbWsxYUZrelVuQmlNalY2VEcxa2NHUkhhREVLV1c1V2VscFlTbXBpTWpVd1dsYzFNRXh0VG5aaVZFRldRbWR2Y2tKblJVVkJXVTh2VFVGRlEwSkJaSGxhVjNoc1dWaE9iRTFFV1VkRGFYTkhRVkZSUWdwbk56aDNRVkZOUlV0RVdtMVBSMXBwVDBkT2FrMXRWWGxQUkdzd1dYcHJORTVIVG1oUFZFa3pXVmRTYUU1SFNtbFphbXN3V20xRmQxcFhSVFZaVjBWM0NrWkJXVXRMZDFsQ1FrRkhSSFo2UVVKQ1FWRkhVa2RXZDJKSE9UVk5RMEZIUTJselIwRlJVVUpuTnpoM1FWRlZSVVZ1VG1waFYzUndaRU14YjFwWVFYWUtXVmhrY21ReVJubGFSRUZsUW1kdmNrSm5SVVZCV1U4dlRVRkZSMEpDUW5sYVYxcDZURE5TYUZvelRYWmtha2wxVDBNMGVVMUVjMGREYVhOSFFWRlJRZ3BuTnpoM1FWRm5SVXhSZDNKaFNGSXdZMGhOTmt4NU9UQmlNblJzWW1rMWFGa3pVbkJpTWpWNlRHMWtjR1JIYURGWmJsWjZXbGhLYW1JeU5UQmFWelV3Q2t4dFRuWmlWRUpxUW1kdmNrSm5SVVZCV1U4dlRVRkZTa0pHVlUxVk1tZ3daRWhDZWs5cE9IWmFNbXd3WVVoV2FVeHRUblppVXpsNldUSnNjbUZZVVhRS1lVZFdkMHd5UmpOaE0yUm9ZMjFSZGt4dFpIQmtSMmd4V1drNU0ySXpTbkphYlhoMlpETk5kbHBIVm5kaVJ6azFURzVzZEdKRlFubGFWMXA2VEROU2FBcGFNMDEyWkdwSmRVOUROSGxOUkdkSFEybHpSMEZSVVVKbk56aDNRVkZ2UlV0bmQyOU9iVmswV20xSk5Ga3lUWGxhVkVrMFQxUlNhazlVWnpCWk1rVTFDazFxWkdoYVIwVXdXVzFLYVU5VVVtMVpWRUpzV1ZSc2FGbFVRV1JDWjI5eVFtZEZSVUZaVHk5TlFVVk1Ra0U0VFVSWFpIQmtSMmd4V1dreGIySXpUakFLV2xkUmQwNVJXVXRMZDFsQ1FrRkhSSFo2UVVKRVFWRnVSRU5XYjJSSVVuZGplbTkyVERKa2NHUkhhREZaYVRWcVlqSXdkbU15VG5CaE1td3dURmRvYkFwalF6bG9aREowTTFsWVNtdE5SR2RIUTJselIwRlJVVUpuTnpoM1FWRXdSVXRuZDI5T2JWazBXbTFKTkZreVRYbGFWRWswVDFSU2FrOVVaekJaTWtVMUNrMXFaR2hhUjBVd1dXMUthVTlVVW0xWlZFSnNXVlJzYUZsVVFXZENaMjl5UW1kRlJVRlpUeTlOUVVWUFFrSkpUVVZJU214YWJrMTJaRWRHYm1ONU9USUtUV2swTkV4cVNYZEhVVmxMUzNkWlFrSkJSMFIyZWtGQ1JIZFJURVJCYTNsTlJFa3dUVlJOTTA1cVNYZE1VVmxMUzNkWlFrSkJSMFIyZWtGQ1JVRlJaZ3BFUWpGdlpFaFNkMk42YjNaTU1tUndaRWRvTVZscE5XcGlNakIyWXpKT2NHRXliREJNVjJoc1kwUkJXVUpuYjNKQ1owVkZRVmxQTDAxQlJWSkNRVzlOQ2tORVNYcE9SRlV3VG1wSk1FMUhUVWREYVhOSFFWRlJRbWMzT0hkQlVrbEZWbEY0VkdGSVVqQmpTRTAyVEhrNWJtRllVbTlrVjBsMVdUSTVkRXd6VG1vS1lWZDBjR1JETVc5YVdFRjJXVmhrY21ReVJubGFRemgxV2pKc01HRklWbWxNTTJSMlkyMTBiV0pIT1ROamVUbHJXbGhDYzJJemEzVmxWekZ6VVVoS2JBcGFiazEyWkVkR2JtTjVPVEpOYVRRMFRHcEpkMDlCV1V0TGQxbENRa0ZIUkhaNlFVSkZkMUZ4UkVObk1scHFhRzFaYW1ocVdYcEtiRTFxWnpWT1IwMDFDazlFVW1wWlZHdDVUakpHYTFsVVVtbFpiVWsxVGtkYWFFMUhWbWhQVjBab1RVSmpSME5wYzBkQlVWRkNaemM0ZDBGU1VVVkRVWGRJWTIxV2MxcFhSbm9LV2xSQ1drSm5iM0pDWjBWRlFWbFBMMDFCUlZaQ1JYTk5VMWRvTUdSSVFucFBhVGgyV2pKc01HRklWbWxNYlU1MllsTTVlbGt5YkhKaFdGRjBZVWRXZHdwTU1rWXpZVE5rYUdOdFVYWlpWMDR3WVZjNWRXTjVPWGxrVnpWNlRIcEZNRTlFUlhkTlJHYzBUMFJaTlV3eVJqQmtSMVowWTBoU2VreDZSWGRHWjFsTENrdDNXVUpDUVVkRWRucEJRa1puVVVsRVFWcDNaRmRLYzJGWFRYZG5XWE5IUTJselIwRlJVVUl4Ym10RFFrRkpSV1pSVWpkQlNHdEJaSGRFWkZCVVFuRUtlSE5qVWsxdFRWcElhSGxhV25walEyOXJjR1YxVGpRNGNtWXJTR2x1UzBGTWVXNTFhbWRCUVVGYVlWWjFXWEZqUVVGQlJVRjNRa2xOUlZsRFNWRkRRd3BpWjAxNWJWZEZWbkk0TVU5a2RHNHZOM1ZxY21KVlYzaGhORGRzVVN0MlpqSm9Na2hVTlRsa04zZEphRUZMVEdkM1ltTndNSFZGYURGUlFVOTRRak5tQ2xGa2Ezb3dka1kyY3premJ6ZFZVemhwUW1wRE9VbzFTRTFCYjBkRFEzRkhVMDAwT1VKQlRVUkJNbWRCVFVkVlEwMUZPRWxSUzJScWQxWTFjbGcyTlRnS2NtZHJla1JFYmpGeVYxSnBORlJWZG5OTlFuaDFOa3hhVGswd1FYb3JWWE5QWldaSGFFc3hUalYxU210MGIweHVOR2RKZUVGT1YxTmtTVEpLUW1VdlpBcHJOV015Tnl0WU1pc3pSbEJhZEUxRWFWZG5TRTVzTldGb1VEUjBOME4wUjNGSEszRlNiSEpqTlRKT0syc3dlRzAwVlZFek5rRTlQUW90TFMwdExVVk9SQ0JEUlZKVVNVWkpRMEZVUlMwdExTMHRDZz09In1dfX0=","inclusionPromise":{"signedEntryTimestamp":"MEUCIQDN1LrPzFnl5RHCqyuKTlGbbVbbDwNi47Dm4QsiwXwlwgIgNDYvH9jTlrQmBxKjmnmZ3whVV4GqJlb2vrYSTP8NVe8="},"inclusionProof":{"checkpoint":{"envelope":"rekor.sigstore.dev - 1193050959916656506\n84555402\n8yW8IimcYVpX+GPpBE4nrQfreUnSuzKi1IBXT6zqZyw=\n\nā rekor.sigstore.dev wNI9ajBGAiEAgp+FGPzBGpg/2aMs7YiIsLPY1GlvGtFEDOX2ukJBaRsCIQCDed9l4TyL5qOCtblSNJmmuVJNHqLziRgVuBHOzoDQPw==\n"},"hashes":["wH4erB8HXXOMsenNJ2h+xHBW+lBJZnEfVuEkwKLWnwo=","uyeeiFO+IqePFTN7NySRMbEVgbjtBWYtmvEnfvS2aVc=","HmzZP9LAV8OZjt8WkZ8qRj/oyDVLn7+cIXL/rmSU+Gs=","ojdh8w+N5cFp2ESrEaY9E7rzvZtNnmKK6STDxgMxicA=","NXGlUrgL3IUjUh2ufP461YzhCNADUusjnDqAz89uvOA=","usyVpEjtVA/8ibfDb6bThSas/0BBrHH+SA1DzylKfI8=","DDs+taVIYHCYzm9HaP0QDDHnPCDkF23LYaZZa9C4hGk=","Mn6/Qmt5gum64ecdArWC4PtO26krRkoRBTuGJyRsWD0=","pGiL2+SI4khym9ssv5m4fTr1cgV7vUeFofdyEm399Lk=","++1LMuz3tIdW1/pfEfhPfXC4ot1AwDAXDcPyfibzGyc=","7v8qPHNDLerpduaMx06eb/MwgoQwczTn/cYGKX/9wZ4="],"logIndex":"84555401","rootHash":"8yW8IimcYVpX+GPpBE4nrQfreUnSuzKi1IBXT6zqZyw=","treeSize":"84555402"},"integratedTime":"1746268687","kindVersion":{"kind":"dsse","version":"0.0.1"},"logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="},"logIndex":"206459663"}]},"version":1}],"publisher":{"environment":"pypi","kind":"GitHub","repository":"scikit-hep/awkward","workflow":"deploy.yml"}}],"version":1}
I don't know if there exists a CLI tool for verifying information quickly at the command line, like gh attestation does for attestations published to GitHub's registry (e.g. https://github.com/scikit-hep/awkward/attestations).
From the skimage perspective, you can consider our endorsement continual. We will work to update our project to match the SPEC on an ongoing basis.
Thanks for helping us figure out good practices here!
Great. Thanks, @stefanv! As we have a small number of projects that are endorsers at the moment I will make PRs to any projects that need updates as a result of this. š
Scikit-HEP hasn't endorsed SPEC 8 yet only given that we need to discuss what it means for a domain stack to endorse a SPEC (if the flagship metapackage just needs to do so or if all projects in the domain stack need to be compliant) but this can get discussed elsewhere or in a future SPEC meeting.
Since endorsement means agreement with the SPEC concept, and is not tied to implementation, I think it would be fine to endorse on the higher level and implement as the domain stack sees fit.
I don't know if there exists a CLI tool for verifying information quickly at the command line, like
gh attestationdoes for attestations published to GitHub's registry (e.g. https://github.com/scikit-hep/awkward/attestations).
I found https://github.com/trailofbits/pypi-attestations?tab=readme-ov-file#verifying-a-pep-740-attestation this morning while waiting for the plane, but I have not tried to test it on some released package. Will do so and then update.
Excellent! Thanks very much, @mihaimaruseac!
One other question RE:
remove adopt SLSA section, mention that it is included in the trusted publishers
for everyone in this Issue. We have some projects that currently build their wheels across multiple platforms (e.g., GitHub Actions, CircleCI) and then do a curation before uploading them to PyPI (e.g. NumPy) and so don't currently use Trusted Publishers. Should we keep in the SLSA recommendations under the condition that projects aren't able to use Trusted Publishers? Or should we keep the SPEC recommendations aimed at the best practices and not address fall backs?
I am of two minds here as I want SPECs to be simple and give clear recommendations to follow, but I also want them to be actionable for people to implement now.
(Also, as I'm not a NumPy developer and I'm on my phone someone should double check me, maybe @mattip, that I'm not spouting off nonsense RE: NumPy's release process in 2025.)
Aside: Seems that @stefanv's recommendation of zizmor (https://github.com/scientific-python/summit-2025/issues/39) would have caught the persistant-credentials: false recommendation from @mihaimaruseac given https://github.com/numpy/numpy/pull/27931 š
Coming back late to this, sorry for this.
I think we still need to maintain the SLSA fallback for the cases where trusted publishing is not supported. I'm thinking we can have 2 golden GitHub Actions workflows, one that uses trusted publishing and one that uses SLSA and link to them from the SPEC -- this should keep the SPEC simple, while providing recommendations for both scenarios.
I could try to do a PR to update the draft.
Hey all - I don't want to derail discussion here so feel free to move this to a separate issue, but I wanted to draw attention to numpy/numpy#29178 as well!
Thanks for adding that issue here, it looks relevant.