A canary package is a harmless internal package with a known version marked as pretend bad. Publish it to a sandbox registry, install it in a test project, then run your incident steps: find it, block it, roll back, rebuild. It tests your process with real tooling and no malicious code.
Why a canary
Tabletops test decisions. A canary tests mechanics: can you search lockfiles, can the mirror block a version, does a rebuild really remove it? Using a real incident for practice is risky. Using a fake package that does nothing is safe and repeatable.
Safety rule: the canary must contain no code that collects data, makes network calls, or changes files. Its sole visible behavior is printing a short marker line when imported. Keep it inside a sandbox registry or local path that no real project can reach.
Step 1: create the package
Make a tiny package with a distinctive name and two versions.
| Version | Role in the drill |
|---|---|
| 1.0.0 | Known good |
| 1.0.1 | Pretend compromised |
For a JavaScript package, the entire file can be one line that prints a marker:
console.log("canary-dependency 1.0.1: drill marker");
Pick a name that cannot collide with real packages, such as a prefix tied to your company plus the word canary.
Step 2: publish somewhere safe
Use a local directory, a throwaway registry running on a test machine, or a private scope on a sandbox account. Check that your normal pipelines cannot see it. Document where it lives so nobody mistakes it for production software.
Step 3: wire it into a test project
Create a small sample project that depends on the canary, with a lockfile. Add a second sample project that reaches it as a transitive dependency of another harmless package, to practice finding indirect use. Commit both.
Step 4: run the drill
Announce a drill window and assign roles. Give the team this scenario: "Version 1.0.1 of the canary package is flagged. Find where it is used, block it, roll back and rebuild."
Time and record these steps.
- Search for the package across lockfiles or inventories.
- Identify which projects hold 1.0.1, including the transitive one.
- Block 1.0.1 in the mirror or policy, and confirm a build fails.
- Roll back to 1.0.0 with a clean lockfile. The guide on rolling back to a known good version shows the mechanics.
- Rebuild and verify the artifact does not contain 1.0.1.
- Purge caches and confirm the blocked version is not served.
What to measure
| Measure | Why |
|---|---|
| Time to find all projects | Tests inventory |
| Whether the transitive use was found | Tests depth of search |
| Time to a working block | Tests permissions and tooling |
| Whether a cache still served the bad version | Tests cleanup |
Do not set targets from other companies. Record your own times and improve them.
Try it yourself
Click through it at your own pace, or open it full screen. Look at how an inventory surfaces direct and indirect use, the thing step 2 of the drill checks.
Clean up
Delete the canary from the sandbox when you finish, or keep it as a standing drill asset with a README. Record the results and findings, then retire the drill project or reset it for the next round.
Quick check
Is a canary package safe to publish publicly?
Avoid it. A public listing can confuse others and may break registry rules. Keep it in a private sandbox.
Can the canary include fake malicious behavior?
Keep it to a printed marker. Anything that touches the network or files adds risk without improving the drill.
Safeguard can help with the inventory side of this work. SBOM and dependency scanning show where a package and version appear across your projects, and policies and gates can stop a flagged version at the pull request. You can try a free scan at gold.safeguard.sh/scan.
Last reviewed: 19 October 2026.