Skip to main content

honeyfile

CI Python 3.10+ No dependencies MIT License

Plant decoy files and get alerted the moment ransomware or an intruder touches them.

honeyfile drops tempting-looking bait — Payroll_2026_Q4.csv, passwords.txt, .env, backup.sql — into a directory and records exactly what each one looks like. Then it watches. The instant something encrypts, modifies or deletes a decoy, you get an alert with the file and what happened. It's a tripwire: a normal user never touches these files, so any change is a signal.

honeyfile planting three office decoys, reporting them intact, then detecting two encrypted files, one deleted file and a dropped ransom note

Why

Ransomware encrypts files fast, and by the time you notice, it's done. But it has to touch files to encrypt them, and a decoy that no human ever opens is the perfect early warning: one honeyfile changing means something is walking through your directory encrypting everything. The same tripwire catches an intruder browsing a file share for passwords.txt.

This is a detection tool, the opposite of malware. It never encrypts anything; it watches for something else that does.

Try it in 30 seconds

pipx install git+https://github.com/winxtxrgit/honeyfile

mkdir demo
honeyfile plant demo --profile office
honeyfile status demo                 # OK: all 3 decoys are intact

echo "encrypted" > demo/passwords.txt # pretend to be ransomware
honeyfile watch demo --once           # [modified] passwords.txt — contents changed

Usage

honeyfile plant /srv/share --profile office   # plant decoys and record a baseline
honeyfile plant ./repo --profile dev          # .env, id_rsa, deploy_keys.json
honeyfile status /srv/share                   # one-shot check, exits 1 if anything changed

honeyfile watch /srv/share                    # keep watching, alert on every change
honeyfile watch /srv/share --json alerts.jsonl
honeyfile watch /srv/share --webhook https://hooks.example.com/honeyfile
honeyfile watch /srv/share --exec "/usr/local/bin/isolate-host.sh"
honeyfile watch /srv/share --once             # for cron; exits 1 if anything changed

honeyfile unplant /srv/share                  # remove the decoys and the baseline

# Keep the baseline out of the watched directory (recommended for shares an
# intruder can browse). Use the same --manifest path for plant, status and watch:
honeyfile plant  /srv/share --manifest /var/lib/honeyfile/share.json
honeyfile status /srv/share --manifest /var/lib/honeyfile/share.json

On Linux, watch uses inotify by default: it reacts the instant a decoy is touched and — unlike polling — catches a decoy merely being opened or read, before anything is changed. Elsewhere it falls back to polling. Force either with --backend poll or --backend inotify.

Profiles decide which decoys get planted: office (payroll, passwords, a confidential doc), dev (.env, id_rsa, deploy keys), db (SQL dumps, a customer export). Every decoy contains only inert placeholder data — the one AWS-shaped key is AWS's own documented example — plus a unique HONEYFILE-CANARY-… token you can also search for in logs, email or outbound traffic.

What it detects

Event Severity Means
modified high A decoy's contents changed — ransomware encrypting, or someone editing it
deleted high A decoy is gone — wiped or moved
manifest-error high The baseline itself was altered or deleted — someone covering their tracks
opened high A decoy was opened or read — someone browsing the bait (Linux inotify backend only)
new-file medium A file that wasn't planted appeared next to the decoys — a ransom note, a dropped tool
touched low A decoy's timestamp changed but its contents are intact — re-saved or restored

Each decoy is fingerprinted by sha256 + size, so a change that keeps the same byte count is still caught. The baseline lives in .honeyfile.json, which carries a checksum of its own contents: editing it to hide a change fails the check, and deleting it is reported too. Pass --manifest PATH to keep that baseline outside the watched directory, so an intruder among the decoys can't read it to learn which files are bait. Planted decoys also get varied, backdated timestamps so a directory of them doesn't betray itself by sharing one creation time.

Alerting

watch prints every alert to stderr (coloured by severity on a terminal) and fans each one out to whatever you configure:

  • --json FILE — one JSON object per line: {"time", "event", "severity", "path", "directory", "detail"}. Feed it to your log pipeline.
  • --webhook URL — POST that JSON to Slack, Discord, or your SOAR. A dead endpoint is logged and never stops the watch.
  • --exec CMD — run a command on each alert, with the event passed as HONEYFILE_EVENT, HONEYFILE_PATH, HONEYFILE_SEVERITY and so on. Use it to isolate a host, kill a session, or page someone. No shell is involved, so a filename from disk is never interpreted.

Good places to plant decoys

  • File shares people rarely open — the first thing ransomware and intruders sweep.
  • A user's Documents or Desktop — many ransomware strains start there.
  • Backup and database directories — high-value targets.
  • Web roots and repos — where a .env or id_rsa is what an attacker is hunting for.

Put decoys where a legitimate user has no reason to go, so every alert is real. honeyfile tells you something touched the bait; pair it with --exec or your EDR to respond.

Limits, honestly

  • Read detection is Linux-only. On Linux the inotify backend reports a decoy being opened or read (opened), the earliest possible signal. On macOS and Windows watch polls, which can only compare snapshots: a plain read changes nothing it can see, so there it detects tampering, not reads. For OS-level read-auditing everywhere, use auditd (Linux) or Windows file-access auditing; honeyfile is the lightweight, portable layer.
  • Polling is near-real-time, not instant. Where inotify isn't used, watch scans every few seconds, so fast ransomware may encrypt several files between scans — you'll still catch it, within one interval. The inotify backend reacts immediately.
  • Decoys protect themselves and signal an attack; they don't stop it. The response is yours, via --exec or your tooling.

Development

python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest
ruff check . && ruff format --check .

No dependencies outside the Python standard library. Tested on Python 3.10–3.13, Linux/macOS/Windows.

License

MIT © Thanut Jongteerathanachote

Metadata

Release files for honeyfile 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for honeyfile 0.3.0
File Size Uploaded Provenance Actions
honeyfile-0.3.0.tar.gz 20.3 kB With provenance Details for honeyfile-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for honeyfile 0.3.0
File Interpreter ABI Platform Actions
honeyfile-0.3.0-py3-none-any.whl Python 3 none any Details for honeyfile-0.3.0-py3-none-any.whl

Total release size: 40.0 kB

Release files / honeyfile-0.3.0.tar.gz

Download URL honeyfile-0.3.0.tar.gz
Size 20.3 kB
Tags Source
SHA-256 checksum
How to use checksums
8feacb8ab3067957d17ef79446db36daae75f47b07dbf1527052e9987f957456
BLAKE2b-256 checksum
How to use checksums
fffb7218dc04ec5fc7b4bd97c635a9b63e97d2205b278532dc21f14a01262d55
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

Release files / honeyfile-0.3.0-py3-none-any.whl

Download URL honeyfile-0.3.0-py3-none-any.whl
Size 19.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
842a95e3a3cb326915df7ebd8fa0ba0ec89ce4ab84edac1d10d9dfad51b80b2d
BLAKE2b-256 checksum
How to use checksums
984cdedfaa916fc484560c506235f4b047478e7e2d1b4cea68bb9c9fc2180d96
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

Security for honeyfile 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for honeyfile-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 30, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page