I merged two PRs to fix my dependency alerts on GitHub. Both had empty diffs.
GitHub kept showing 11 open Dependabot alerts (10 high, 1 moderate). It was right, and I was wrong.
When I dug into my terminal, I saw this:
text
- pypdf==6.21.4
- pypdf==6.21.1 My security patch was silently downgraded. Here is exactly why it happened and how to fix it.
Why did uv add downgrade my package?
I was working on CivicAI, an open-source PII redaction pipeline. I ran uv add presidio-analyzer presidio-anonymizer to add a new feature.
However, my local main branch was 5 commits behind origin/main.
pyproject.toml said "pypdf>=4.0".
My local uv.lock was stale and had pypdf 6.21.1 cached.
The resolver saw that 6.21.1 satisfied >=4.0, so it silently kept the vulnerable version.
I pushed the code. The tests passed. But the lockfile still had vulnerabilities.
The fix that actually sticks
You cannot just fix the lockfile; you have to fix the rules so it can't happen again.
Step 1: Sync your local repo
bash
git fetch origin
git rebase origin/main
Step 2: Force the upgrade
bash
uv lock --upgrade-package pypdf
Step 3: Raise the floor in pyproject.toml
Change "pypdf>=4.0" to "pypdf>=6.21.4".
This is the most important step. By raising the floor, even if a developer runs uv add on a stale lockfile, the resolver is forced to install 6.21.4 or higher.
Step 4: Declare your test dependencies
I also noticed my Presidio integration test was silently skipping on a fresh clone because presidio-analyzer wasn't in pyproject.toml.
toml
pyproject.toml
dependencies = [
"pypdf>=6.21.4",
"presidio-analyzer>=2.2.0",
"presidio-anonymizer>=2.2.0",
]
Result:
bash
$ gh api repos/sitara2007/CivicAI/dependabot/alerts --jq '[.[]|select(.state=="open")]|length'
0
Tests: 28 passed, 1 skipped (tested against real Postgres).
The Takeaway for Engineers
A merged PR isn’t a fix until the lockfile diff proves it. Always run git diff uv.lock before merging.
A skipped test is a signal, not a pass. If a test skips because a dependency isn't declared, your CI is lying to you.
Passing tests, dependency scanning, and code scanning answer different questions. You need all three.
I'm building CivicAI, an open-source PII redaction pipeline with a tamper-evident audit log. If your team sends sensitive text to LLMs, what's the hardest part of redaction today?


