Your dependencies will break. Your CI will leak. Probably not today.
Your dependencies will break. Your CI will leak. Probably not today. The day the platform removes the API you depend on, or the tag you pinned to gets moved, is the day you find out. I wanted to find out earlier — so I built breakcheck, a zero-dependency Node.js CLI that scans a project for things that will break or leak before they do. Why now? Three things happened in the same week: Chrome and Edge are removing XSLT. Python removed imp and distutils in 3.12. Platforms remove things with short notice, and a vendor can halve a shutdown notice and break your migration plan. A workflow pinned to @v4 trusts that the tag still points where it did yesterday. Tags move. Commit SHAs don't. A recent wave hijacked ~1,900 GitHub accounts and reached ~30,000 repos — most of the damage ran through over-privileged automation, not zero-days. breakcheck doesn't fix any of this for you. It tells you exactly where it is, with a fix for each finding, so the next breakage is a planned mig
Your dependencies will break. Your CI will leak. Probably not today.
The day the platform removes the API you depend on, or the tag you
pinned to gets moved, is the day you find out. I wanted to find out
earlier — so I built breakcheck, a zero-dependency Node.js CLI that
scans a project for things that will break or leak before they do.
Why now? Three things happened in the same week:
- Chrome and Edge are removing XSLT. Python removed
impanddistutilsin 3.12. Platforms remove things with short notice, and a vendor can halve a shutdown notice and break your migration plan. - A workflow pinned to
@v4trusts that the tag still points where it did yesterday. Tags move. Commit SHAs don't. - A recent wave hijacked ~1,900 GitHub accounts and reached ~30,000 repos — most of the damage ran through over-privileged automation, not zero-days.
breakcheck doesn't fix any of this for you. It tells you exactly
where it is, with a fix for each finding, so the next breakage is a
planned migration instead of a fire drill.
What it checks
Plain Node.js, no network, no telemetry. It scans locally:
| File | Rules |
|---|---|
package.json |
Deprecated deps (request, node-sass, tslint, …), moment maintenance-mode warning, floating versions (*, latest, >=), engines.node on an EOL Node |
requirements.txt |
Deprecated Python packages (pycrypto, nose), unpinned requirements |
pyproject.toml |
requires-python allowing EOL Python |
.github/workflows/*.yml |
Actions pinned to a mutable tag instead of a full commit SHA, permissions: write-all, broad contents: write, pull_request_target, hardcoded token-shaped secrets |
Dockerfile |
Base image with no tag, :latest, or a major-only tag |
Code (.js/.ts/.py) |
Removed APIs: browser XSLTProcessor, Python imp, collections.Mapping-style aliases, distutils
|
Demo
The bundled examples/broken/ project is broken on purpose — one of
almost everything:
$ node bin/breakcheck.js check --path examples/broken
[ERROR] broad-permissions: 'permissions: write-all' grants every permission to the workflow
fix: Grant only the permissions each job needs, e.g. 'permissions: { contents: read }'
[ERROR] unpinned-action: Action 'actions/checkout@v4' is pinned to mutable ref 'v4'
fix: Pin the action to a full commit SHA
[ERROR] unpinned-base: Docker base image 'node:latest' uses the mutable ':latest' tag
fix: Pin the base image, e.g. 'node:22-alpine'
[ERROR] removed-api: XSLT in the browser is being removed from Chrome and Edge
fix: Move the transform to the server, or pre-render at build time
[ERROR] deprecated-dep: 'request' is deprecated since 2020 and unmaintained
fix: Replace with node:http / undici, axios, or node-fetch
[ERROR] eol-runtime: engines.node '14' targets Node 14, which is end-of-life
fix: Move engines.node to '>=18' (20 LTS recommended)
Summary: 10 error(s), 3 warning(s), 7 file(s) scanned.
examples/clean/ passes with Summary: 0 error(s), 0 warning(s), 6 file(s) scanned.
Use it in CI
# Scan a project (exit 1 if any error-level finding)
breakcheck check --path ./my-project
# JSON output for CI / scripts
breakcheck check --path ./my-project --format json
# Also fail on warnings (strict mode)
breakcheck check --path ./my-project --fail-on warn
Warnings don't fail the run by default, so you can adopt it without
breaking existing builds. Turn on --fail-on warn once the warnings
are down to zero.
What it deliberately does not do
The deprecation list is small on purpose: every entry is a removal or
deprecation that is public and settled, not a popularity contest. And
the tool never phones home, so it can't check live advisories — pair it
with your package manager's audit for CVEs.
One more deliberate choice: there is no --fix yet, and pinning
:latest to an explicit tag will intentionally never be auto-fixed —
picking the version is a decision, not a chore.
Repo: https://github.com/techdevfun/breakcheck — MIT, zero dependencies,
Node.js 18+.