← Blog
ENGINEERING5 min read

Our dependency scan reported zero criticals. It had only looked at the repos we happened to have installed.

Aug 31, 2026DekimuAI-generated

We ran a dependency-advisory sweep across the whole Dekimu estate. The first pass walked every project folder, ran npm audit, and summed the results: 24 high, 25 moderate, zero critical. That number was wrong, and the way it was wrong is more interesting than the patches.

The scan measured presence, not the fleet

npm audit needs an installed dependency tree or a lockfile to read. Our sweep looped over directories and quietly skipped any repo that did not have node_modules sitting on disk. Those skips did not appear in the output as unknown or unmeasured. They simply were not in the total.

So the sweep covered the repos we had been actively working in, and silently ignored the ones nobody had opened in months. That is precisely backwards. A repo you touch weekly gets its dependencies pulled forward by ordinary work. A repo you have not built since spring is where advisories accumulate undisturbed.

When we went back and re-ran the scan against those repos’ lockfiles, three of them carried critical advisories. The clean bill of health had been a statement about our laptop, not about our software.

A check that skips what it cannot measure does not return an incomplete answer. It returns a confident wrong one.

The suggested fix that would have deleted a feature

On verify.dekimu.com, our public receipt renderer, three low advisories sit in a chain: opentimestamps depends on bitcore-lib, which depends on elliptic. The advisory covers every elliptic release up to and including 6.6.1, and 6.6.1 is the newest one published. There is no patched version to move to.

npm still offers a remedy. Running audit fix with --force resolves the chain by installing opentimestamps@0.0.0 — an empty placeholder package. The advisory count would drop to zero, the build would pass, and Bitcoin timestamp verification would silently disappear from the renderer.

We left those three advisories in place and wrote the reasoning into the source file next to the import, including the detail that this code path only ever verifies — it walks a Merkle path to a block header and never generates a key or signs anything, which is the surface the elliptic advisory actually concerns. An advisory you have understood and declined is a different object from one you have not noticed. The repo should be able to tell them apart without re-deriving the analysis.

A version bump that found copy nobody had read

Two of the moderate advisories in Dekimu Hub were only reachable through next-intl, and clearing them meant a 3 to 4 major upgrade. The migration itself was uneventful. What it surfaced was not.

Version 4 tightened the argument types on translation calls, and the type checker immediately flagged two places where a null was being passed into user-facing text. One of them was a late-payment calculator: when an invoice was not yet overdue, the code reported a rate source but no effective date, and rendered the sentence "ECB ref rate (effective ):" to the user. That string had been shipping. No test covered it, and no advisory would ever have mentioned it.

What we changed

Twenty-two codebases patched across twenty-one pull requests. The one genuinely runtime-reachable issue was in Hub: a PDF.js advisory allowing script execution from a malicious document, in the code path that parses user-uploaded files in the document vault. Everything else was build tooling, test runners, and transitive dependencies.

Every change was verified against each repository’s own CI gates rather than against the advisory count alone — type check, lint, build, and test suite where one exists. A lockfile edit that clears npm audit and breaks the build has not made anything safer.

We left one repo alone. Our Capacitor shell was parked earlier this year when the Telegram gateway replaced it, and its critical advisory sits in a CLI that nothing builds or deploys. Patching it would have meant an unverifiable major bump to a codebase we have already decided not to use. The honest fix there is to archive the repository, not to make its advisory count look better.

The durable change is not the patches, which will be stale again soon enough. It is that the sweep now reports what it could not measure, instead of leaving it out of the total.

ENGINEERING

This post was drafted by an AI system from Dekimu's public engineering record and published with automated checks, without per-post human editing.

← Back to blog