Contents (4 sections)
Every security scan of your dependencies rests on the same assumption: the lock file tells the truth. It is the file that pins down, version by version and hash by hash, what your application actually ships. The scanner reads it and returns its verdict.
A few days ago, we discovered that this assumption could be false in our own build pipelines, without a single warning light coming on. Here is what was happening.
The restore that fixes instead of warning #
When a build starts, it restores the dependencies. If the lock file no longer matches the declared dependencies (because someone changed a version without regenerating the lock), the default behaviour of most tools is helpful: they update the lock file and carry on.
That is very convenient in development. In continuous integration, it is a silent disaster. The build goes green. The tests go green. And the lock file that goes to production no longer describes what the team reviewed.
The fix comes down to one flag: require a restore in locked mode. In this mode, an inconsistent lock file is no longer quietly repaired: it makes the build fail, with an explicit message. We added it to all the pipelines concerned.
With one precaution that matters: we first checked, repository by repository, that the main branch passed this check. Adding a strict flag to a project that already has inconsistent lock files turns its pipeline red overnight and pushes the team to switch it off. You do not put a guardrail in place without measuring what it is going to block.
Actually bringing versions up to date #
An accurate lock file is useless if it pins last year's versions. So, in parallel, we worked through the backlog of pending updates across all our repositories: twenty-six merge requests, built, tested and (the part nobody does) opened in a real browser page by page before merging, then checked on the production site after deployment.
That last step is not excessive zeal. A major version upgrade of a UI library compiles perfectly and renders a blank page. Unit tests do not see it. The build pipeline does not see it. Only a browser sees it.
The flaw nobody tests: the licence #
The most instructive moment of the week had nothing to do with a technical vulnerability.
A test library widely used in the .NET ecosystem changed its licence between two major versions: from a permissive open-source licence, it moved to a proprietary licence forbidding commercial use without a purchase. The automatic version upgrade proposed it like any other.
It compiled. All 1,159 tests passed. Absolutely nothing in the pipeline had the slightest reason to object, because no build pipeline tests licences. We spotted it by reading the package metadata, checked it in its licence file, then reverted it the same day, with a blocking rule so that the proposal would not come back.
A licence change is an invisible legal regression. It breaks no test, appears in no vulnerability scan, and is usually discovered at the worst possible moment: an audit, a funding round, a formal notice.
We tried to automate this detection. We failed, and that is a conclusion in itself: the licence scanners we tested read the licence files present in the source tree, not the metadata of downloaded packages. So they see neither this library nor the others. Rather than write yet another in-house tool, we made a decision: every dependency under a restrictive licence gets a replacement ticket, tracked like ordinary technical debt.
What changes for you #
- Your security scans read the real versions. A stale lock file gave a reassuring and false verdict; it now makes the build fail.
- Updates arrive as they come, in small, readable merge requests, rather than in a yearly batch that is impossible to review, and therefore never done.
- Your licences are checked. If a library you use moves to terms incompatible with commercial use, we see it and we tell you, before your lawyer is the one who finds out.
- Nothing is merged on the strength of a green build alone. Anything that touches the interface is opened in a browser, before and after release to production.
If you only run one check in your own environment this month, make it this one: take your lock file and check that your build pipeline fails when it is inconsistent. If it repairs it on its own, your security dashboard is measuring something other than your production.



