ENH: Add vulnerability scan workflow with grype#164
ENH: Add vulnerability scan workflow with grype#164matthewfeickert wants to merge 5 commits intoscientific-python:mainfrom
Conversation
| locked: true | ||
|
|
||
| - name: Scan with grype | ||
| run: pixi exec grype .pixi/envs/default |
There was a problem hiding this comment.
There is the flag
-f, --fail-on string set the return code to 2 if a vulnerability is found with a severity >= the given severity, options=[negligible low medium high critical]
but I decided to not have things fail at the moment as we have some critical ones that I don't think we can do much about yet.
$ pixi exec grype .pixi/envs/default --fail-on high | grep 'High\|Critical'
✔ Indexed file system .pixi/envs/default
✔ Cataloged contents 3913d5d0159f235532a38c6542273f76b141335ceeef368779ba833d9fbcb4ac
├── ✔ Packages [211 packages]
├── ✔ Executables [262 executables]
├── ✔ File metadata [11,099 locations]
└── ✔ File digests [11,099 files]
✘ Scan for vulnerabilities [58 vulnerability matches]
├── by severity: 2 critical, 22 high, 27 medium, 4 low, 1 negligible (2 unknown)
└── by status: 50 fixed, 8 not-fixed, 0 ignored
[0000] WARN no explicit name and version provided for directory source, deriving artifact ID from the given path (which is not ideal) from=syft
A newer version of grype is available for download: 0.111.1 (installed version is 0.111.0)
[0002] ERROR discovered vulnerabilities at or above the severity threshold
libtiff 4.7.1 conda CVE-2023-52356 High 0.8% (74th) 0.6
openssl 3.6.0 3.0.19, 3.3.6, 3.4.4, 3.5.5, *3.6.1 conda CVE-2025-15467 High 0.7% (72nd) 0.6
openssl 3.6.0 1.1.1ze, 3.0.19, 3.3.6, 3.4.4, 3.5.5, *3.6.1, ... conda CVE-2025-69420 High 0.3% (53rd) 0.2
python 3.14.2 conda CVE-2026-6100 Critical 0.2% (35th) 0.1
jaraco-context 5.3.0 6.1.0 python GHSA-58pv-8j8x-9vj2 High < 0.1% (25th) < 0.1
libpng 1.6.53 1.6.55 conda CVE-2026-25646 High < 0.1% (23rd) < 0.1
openssl 3.6.0 1.1.1ze, 3.0.19, 3.3.6, 3.4.4, 3.5.5, *3.6.1, ... conda CVE-2025-69419 High < 0.1% (19th) < 0.1
openssl 3.6.0 3.6.2 conda CVE-2026-28386 Critical < 0.1% (15th) < 0.1
openssl 3.6.0 1.0.2zp, 1.1.1zg, 3.0.20, 3.3.7, 3.4.5, *3.6.2, ... conda CVE-2026-28389 High < 0.1% (15th) < 0.1
openssl 3.6.0 1.0.2zp, 1.1.1zg, 3.0.20, 3.3.7, 3.4.5, *3.6.2, ... conda CVE-2026-28390 High < 0.1% (15th) < 0.1
libpng 1.6.53 1.6.56 conda CVE-2026-33636 High < 0.1% (15th) < 0.1
libpng 1.6.53 1.6.56 conda CVE-2026-33416 High < 0.1% (11th) < 0.1
openssl 3.6.0 1.0.2zn, 1.1.1ze, 3.0.19, 3.3.6, 3.4.4, *3.6.1, ... conda CVE-2025-69421 High < 0.1% (10th) < 0.1
libtiff 4.7.1 conda CVE-2026-4775 High < 0.1% (9th) < 0.1
urllib3 2.6.2 2.6.3 python GHSA-38jv-5279-wg99 High < 0.1% (8th) < 0.1
libpng 1.6.53 1.6.54 conda CVE-2026-22695 High < 0.1% (8th) < 0.1
openssl 3.6.0 1.0.2zp, 1.1.1zg, 3.0.20, 3.3.7, 3.4.5, *3.6.2, ... conda CVE-2026-28388 High < 0.1% (7th) < 0.1
pillow 12.0.0 12.1.1 python GHSA-cfh3-3jmp-rvhc High < 0.1% (5th) < 0.1
pillow 12.0.0 12.2.0 python GHSA-whj4-6x5x-4v2j High < 0.1% (4th) < 0.1
python 3.14.2 conda CVE-2026-4786 High < 0.1% (5th) < 0.1
libpng 1.6.53 1.6.54 conda CVE-2026-22801 High < 0.1% (4th) < 0.1
openssl 3.6.0 3.0.20, 3.3.7, 3.4.5, 3.5.6, *3.6.2 conda CVE-2026-31790 High < 0.1% (4th) < 0.1
openssl 3.6.0 3.5.6, *3.6.2 conda CVE-2026-2673 High < 0.1% (4th) < 0.1
wheel 0.45.1 0.46.2 python GHSA-8rrh-rw8j-w5fx High < 0.1% (1st) < 0.1Not sure what people think.
There was a problem hiding this comment.
When there is a safe version I would fail. Or you're saying we can't do it here??
If we don't fail I am not sure I understand what this action does. People won't really have a look then no?
There was a problem hiding this comment.
When there is a safe version I would fail.
@tupui so you're saying as there is the flag
--only-fixed ignore matches for vulnerabilities that are not fixed
to do
| run: pixi exec grype .pixi/envs/default | |
| run: pixi exec grype .pixi/envs/default --only-fixed --fail-on high |
?
There was a problem hiding this comment.
There's some information here that we don't want though / should filter out, as
$ pixi exec grype --only-fixed --fail-on high .pixi/envs/default | grep 'High\|Crit'
✔ Indexed file system .pixi/envs/default
✔ Cataloged contents 3913d5d0159f235532a38c6542273f76b141335ceeef368779ba833d9fbcb4ac
├── ✔ Packages [211 packages]
├── ✔ Executables [262 executables]
├── ✔ File metadata [11,099 locations]
└── ✔ File digests [11,099 files]
✘ Scan for vulnerabilities [50 vulnerability matches]
├── by severity: 2 critical, 23 high, 27 medium, 4 low, 1 negligible (2 unknown)
└── by status: 50 fixed, 9 not-fixed, 9 ignored
[0000] WARN no explicit name and version provided for directory source, deriving artifact ID from the given path (which is not ideal) from=syft
A newer version of grype is available for download: 0.111.1 (installed version is 0.111.0)
[0002] ERROR discovered vulnerabilities at or above the severity threshold
openssl 3.6.0 3.0.19, 3.3.6, 3.4.4, 3.5.5, *3.6.1 conda CVE-2025-15467 High 0.7% (72nd) 0.6
openssl 3.6.0 1.1.1ze, 3.0.19, 3.3.6, 3.4.4, 3.5.5, *3.6.1, ... conda CVE-2025-69420 High 0.3% (53rd) 0.2
jaraco-context 5.3.0 6.1.0 python GHSA-58pv-8j8x-9vj2 High < 0.1% (25th) < 0.1
libpng 1.6.53 1.6.55 conda CVE-2026-25646 High < 0.1% (23rd) < 0.1
openssl 3.6.0 1.1.1ze, 3.0.19, 3.3.6, 3.4.4, 3.5.5, *3.6.1, ... conda CVE-2025-69419 High < 0.1% (19th) < 0.1
openssl 3.6.0 3.6.2 conda CVE-2026-28386 Critical < 0.1% (15th) < 0.1
openssl 3.6.0 1.0.2zp, 1.1.1zg, 3.0.20, 3.3.7, 3.4.5, *3.6.2, ... conda CVE-2026-28389 High < 0.1% (15th) < 0.1
openssl 3.6.0 1.0.2zp, 1.1.1zg, 3.0.20, 3.3.7, 3.4.5, *3.6.2, ... conda CVE-2026-28390 High < 0.1% (15th) < 0.1
libpng 1.6.53 1.6.56 conda CVE-2026-33636 High < 0.1% (15th) < 0.1
libpng 1.6.53 1.6.56 conda CVE-2026-33416 High < 0.1% (11th) < 0.1
openssl 3.6.0 1.0.2zn, 1.1.1ze, 3.0.19, 3.3.6, 3.4.4, *3.6.1, ... conda CVE-2025-69421 High < 0.1% (10th) < 0.1
urllib3 2.6.2 2.6.3 python GHSA-38jv-5279-wg99 High < 0.1% (8th) < 0.1
libpng 1.6.53 1.6.54 conda CVE-2026-22695 High < 0.1% (8th) < 0.1
openssl 3.6.0 1.0.2zp, 1.1.1zg, 3.0.20, 3.3.7, 3.4.5, *3.6.2, ... conda CVE-2026-28388 High < 0.1% (7th) < 0.1
pillow 12.0.0 12.1.1 python GHSA-cfh3-3jmp-rvhc High < 0.1% (5th) < 0.1
pillow 12.0.0 12.2.0 python GHSA-whj4-6x5x-4v2j High < 0.1% (4th) < 0.1
libpng 1.6.53 1.6.54 conda CVE-2026-22801 High < 0.1% (4th) < 0.1
openssl 3.6.0 3.0.20, 3.3.7, 3.4.5, 3.5.6, *3.6.2 conda CVE-2026-31790 High < 0.1% (4th) < 0.1
openssl 3.6.0 3.5.6, *3.6.2 conda CVE-2026-2673 High < 0.1% (4th) < 0.1
wheel 0.45.1 0.46.2 python GHSA-8rrh-rw8j-w5fx High < 0.1% (1st) < 0.1has things like
NAME INSTALLED FIXED IN TYPE VULNERABILITY SEVERITY EPSS RISK
...
jaraco-context 5.3.0 6.1.0 python GHSA-58pv-8j8x-9vj2 High < 0.1% (25th) < 0.1
which is a CVE for Python and not for the conda-forge package. So we want to also be able to ask it only for conda-forge related vulnerabilities that have a release with a fix.
There was a problem hiding this comment.
--only-fixed --fail-on high
Ah yes I would try to do that, or at least on criticals?
--only-fixed
More of an open remark. In general if we get notified that something hit the fan really bad, we could consider having a way to stop the distribution completely.
There was a problem hiding this comment.
@tupui I now have two checks, where the second is checking for the fixed and unfixed but fails only for critical vulnerabilities.
- name: Scan with grype (for fixed vulnerabilities)
run: pixi exec grype .pixi/envs/default --only-fixed --fail-on high
- name: Scan with grype (for all vulnerabilities)
run: pixi exec grype .pixi/envs/default --fail-on criticalThere was a problem hiding this comment.
Ah, no, I had to flip them to
- name: Scan with grype (for all vulnerabilities)
run: pixi exec grype .pixi/envs/default --fail-on critical
- name: Scan with grype (for fixed vulnerabilities)
run: pixi exec grype .pixi/envs/default --only-fixed --fail-on highor else we would never pick up the unfixed critical vulnerabilities that you were mentioning checking for if there were known fixed vulnerabilities that were at high or critical.
So if we can pass on the most restrictive cut level (Critical) for everything, then we loosen the cut level to High and then check again for ones with fixes.
There was a problem hiding this comment.
I guess we can make some arguments for both 😅
There was a problem hiding this comment.
@tupui I think if we want to be able to test both and know if there are unfixed VeryBad ™️ vulnerabilities that still persist after the 30 dependency cooldown
upload-nightly-action/pixi.toml
Lines 9 to 10 in 7c719ad
then we need to use what is currently there:
--fail-on critical--only-fixed --fail-on high
|
@scientific-python/nightly-wheels-developers this is ready for review. |
tupui
left a comment
There was a problem hiding this comment.
Nice! Did not know this one and I see they even support SBOM directly.
81e579d to
4c827c2
Compare
4c827c2 to
6d52911
Compare
| - package: | ||
| # only show vulnerabilities from conda-forge conda packages | ||
| type: python |
There was a problem hiding this comment.
i don't think this is what you want.
grype doesn't map type conda vulnerabilities (like
jaraco.context 6.1.1 pyhcf101f3_0 15.01 KiB conda https://conda.anaconda.org/conda-forge
)
to CVEs (like
jaraco-context 5.3.0 6.1.0 python GHSA-58pv-8j8x-9vj2 High < 0.1% (25th) < 0.1
). right now, there is no mapping for this. grype finds the typical site packages structure and infers the corresponding pypi package through this. if you excluded type: python packages, you would miss all python CVEs
There was a problem hiding this comment.
see also https://pixi.prefix.dev/latest/security/#current-gaps-and-practical-recommendation
We are currently working on a PURL-related Conda Enhancement Proposal, conda/ceps#63, that will make it easier to match conda-installed software against CVEs that are tracked in other ecosystems like PyPI. Until that work is standardized and widely implemented, direct scans of the already-installed environment with tools like Syft and Grype remain the most practical workaround.
There was a problem hiding this comment.
Thanks for explaining this in detail, @pavelzw.
6d52911 to
69a1fb3
Compare
|
Note that there's a lot of vulnerabilities coming from but these won't be fixed anytime soon as conda-forge's global pinning are currently pinned to openssl:
- '3.5'given a desire to stay on the LTS release in conda-forge/conda-forge-pinning-feedstock#7862. edit: That being said, not sure how were getting |
69a1fb3 to
ee4ddf9
Compare
|
Is the overarching goal of this PR to prevent uploading nightlies built with known-vulnerable build dependencies? |
@stefanv No. This doesn't give us any information on the uploaded packages or their build process — we only get them once they're already wheels. This only checks to see if the tool doing the uploading, |
|
@tupui (I'm no longer in European timezones, so I'll be slower to reply this week, but) do you have any other thoughts on this PR? |
Good point. Let me add some docs. |
|
Failing because:
Details |
|
@stefanv Can I also get a review from you (no rush on this though)? |
bsipocz
left a comment
There was a problem hiding this comment.
Overall this looks good to me; but I think we should really aim to get this job in a green passing state otherwise it will be very difficult to spot any new issues.
Getting the job to pass can be done in a follow-up if you prefer, so I'm OK with merging this as is.
@bsipocz I fully agree, but I want to be honest that I think that this probably won't happen for a long time unless there's some discussion with conda-forge people. To avoid having a broken weekly CI test for a long time I could open up some discussion RE: the global pinning and see how this would also affect the conda-forge feedstocks for |
That's a bit outrageous they would take some sweet time to fix things considering all that is happening now in terms of supply chain hacks 😅 |
I'm not saying that they would be unhelpful. I'm saying that given the build system #164 (comment) I would probably need to ask on the conda-forge Zulip to have a member of edit: Actually, from
and from
So I'm not sure what is going on. |
efb664d to
c6fa3da
Compare
What was going on is me forgetting that if I run and the thing I'm upgrading upload-nightly-action/pixi.toml Line 15 in 7c719ad is already at its most recent release it isn't going to resolve the environment all the way down. If I resolve the lock file though after loosening the dependency cooldown (like @henryiii suggested) then we get $ pixi list openssl
Name Version Build Size Kind Source
openssl 3.6.2 h35e630c_0 3.02 MiB conda https://conda.anaconda.org/conda-forgeand the only remaining critical vulnerability is in Python $ pixi run grype
✨ Pixi task (grype): pixi exec grype .pixi/envs/default: (Scan environment for security vulnerabilities with grype)
✔ Indexed file system .pixi/envs/default
✔ Cataloged contents 3913d5d0159f235532a38c6542273f76b141335ceeef368779ba833d9fbcb4ac
├── ✔ Packages [217 packages]
├── ✔ Executables [279 executables]
├── ✔ File metadata [11,892 locations]
└── ✔ File digests [11,892 files]
✔ Scanned for vulnerabilities [22 vulnerability matches]
├── by severity: 2 critical, 6 high, 12 medium, 2 low, 0 negligible
└── by status: 4 fixed, 18 not-fixed, 0 ignored
[0000] WARN no explicit name and version provided for directory source, deriving artifact ID from the given path (which is not ideal) from=syft
NAME INSTALLED FIXED IN TYPE VULNERABILITY SEVERITY EPSS RISK
libtiff 4.7.1 conda CVE-2023-6277 Medium 3.8% (88th) 2.2
libtiff 4.7.1 conda CVE-2023-52356 High 0.7% (72nd) 0.6
python 3.14.4 binary CVE-2026-6100 Critical 0.2% (35th) 0.1
python 3.14.4 conda CVE-2026-6100 Critical 0.2% (35th) 0.1
python 3.14.4 binary CVE-2026-3298 High < 0.1% (20th) < 0.1
python 3.14.4 conda CVE-2026-3298 High < 0.1% (20th) < 0.1
python 3.14.4 3.15.0a6 binary CVE-2025-15366 Medium < 0.1% (23rd) < 0.1
python 3.14.4 3.15.0a6 binary CVE-2025-15367 Medium < 0.1% (23rd) < 0.1
python 3.14.4 3.15.0a6 conda CVE-2025-15366 Medium < 0.1% (23rd) < 0.1
python 3.14.4 3.15.0a6 conda CVE-2025-15367 Medium < 0.1% (23rd) < 0.1
python 3.14.4 binary CVE-2026-1502 Medium < 0.1% (18th) < 0.1
python 3.14.4 conda CVE-2026-1502 Medium < 0.1% (18th) < 0.1
libtiff 4.7.1 conda CVE-2026-4775 High < 0.1% (11th) < 0.1
python 3.14.4 binary CVE-2026-3087 Medium < 0.1% (14th) < 0.1
python 3.14.4 conda CVE-2026-3087 Medium < 0.1% (14th) < 0.1
python 3.14.4 binary CVE-2026-4786 High < 0.1% (5th) < 0.1
python 3.14.4 conda CVE-2026-4786 High < 0.1% (5th) < 0.1
python 3.14.4 binary CVE-2026-6019 Low < 0.1% (15th) < 0.1
python 3.14.4 conda CVE-2026-6019 Low < 0.1% (15th) < 0.1
python 3.14.4 binary CVE-2025-12781 Medium < 0.1% (4th) < 0.1
python 3.14.4 conda CVE-2025-12781 Medium < 0.1% (4th) < 0.1
libtiff 4.7.1 conda CVE-2023-6228 Medium < 0.1% (3rd) < 0.1and as CVE-2026-6100 doesn't have a fix, we can't do anything about that yet. |
c6fa3da to
0184cca
Compare
| If there are updates available try resolving the lock file fresh with | ||
|
|
||
| ``` | ||
| pixi reinstall | ||
| ``` | ||
|
|
||
| or by | ||
|
|
||
| ``` | ||
| rm pixi.lock && pixi lock | ||
| ``` |
There was a problem hiding this comment.
Gave instructions to avoid my mistake here now.
There was a problem hiding this comment.
Okay, now finalized. Sorry for the noise.
0184cca to
84bc621
Compare
* Add GitHub Actions workflow that runs a vulnerability scan with grype (https://github.com/anchore/grype) on the conda packages in the Pixi environment. Check for vulnerabilities across all installed packages, both those with and without fixes, and then check for vulnerabilities that do have known fixes as a more restrictive failure setting.
* Add a Pixi task that executes grype but with 'pixi exec' to make it transient and to avoid adding grype to the default environment.
84bc621 to
0961bc5
Compare
|
I am mostly thinking along the line of if it's failing all the time, then we diff it to known issues, like all the ones you highlight? (I just say this as I have a couple of places where failures are expected and are always around, I find it really really difficult to even looking at the logs carefully as I know they are expected to fail. And naturally new stuff if always burried in those logs. Anyway, I'm much better with the ones where it's just an occasional failure). |


HT to @wolfv and @pavelzw for the 2026-04-21 prefix.dev blog post Securing the Conda-Forge Supply Chain.