LogonTracer: the example config ships neo4j/password, and every import puts the database password in argv
Investigate malicious Windows logon by visualizing and analyzing Windows event log
At a glance
- What is it?
- LogonTracer imports Windows event logs into Neo4j, scores hosts and accounts with PageRank, a hidden Markov model and ChangeFinder, and adds an LLM agent in version 2. Its documented commands pass the Neo4j password as a flag, its example config ships a default password for both the web login and the database, and its four compose variants are documented nowhere.
- Who is it for?
- LogonTracer fits an incident responder who already has a Neo4j instance and a Security.evtx export, and who wants logon activity as a graph instead of a list of rows. Before the first run, change both passwords in `config/config.yml`, not just the one the comment marks, because the same value appears twice with two meanings.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 64 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The example config gives the web login the database credentials
The configuration step shows this:
settings:
logontracer:
WEB_PORT: "8080"
default_user: "neo4j" # Neo4j username for the default LogonTracer account
default_password: "password" # Change this before first run
neo4j:
NEO4J_USER: "neo4j"
NEO4J_PASSWORD: "password" # Your Neo4j password
NEO4J_SERVER: "localhost"
WS_PORT: "7687"Two things are worth pausing on. The value `password` appears twice, once as the web application's default login and once as the Neo4j password, and the comment on `default_user` says it is the Neo4j username for the default LogonTracer account, so the two pairs are not independent. And only one of the two carries a change-it instruction. The app then serves plain HTTP on 8080 and the README tells you to open `http://localhost:8080`, so the credential you just set travels in the clear on a default install.
Every documented import passes the password as a flag
All four import invocations take the database credential on the command line, and the concrete example fills it in:
python3 logontracer.py -e <path/to/Security.evtx> -z 9 -s localhost -u neo4j -p password --sigmaThe EVTX form, the XML form and the Elasticsearch form all end in `-s <Neo4j server> -u <user> -p <password>`. A command-line password lands in your shell history and is visible in the process table to anything else running on the machine for as long as the import takes, and an import of a large Security.evtx is not quick. Nothing in the README mentions an environment variable, a prompt, or a config-file-only path for the import step, even though the web application itself stores the same settings in `config/config.yml`. The web upload path exists and does not have this problem, since it runs inside the application that already holds the credentials.
An import replaces the graph unless you ask it not to
The usage section documents four import routes, and the fourth exists because the first three destroy what was there. The base invocations import a log and clear the existing data, while the one titled Add additional logs runs with `--add` and does not delete existing data. The same choice is exposed in the web interface as the Add additional files checkbox, described as appending data without clearing the database, and as Run scan using Sigma rules to run detection automatically after import. So the safe mode is the one you have to notice: re-running an import to fix a timezone or add a second host's log will empty the graph unless you remember a flag whose name is simply add. For a tool whose output is a picture of an intrusion, that is the difference between two rounds of analysis and one.
Four compose variants ship, and the README explains none of them
The tree holds `docker-compose/`, `docker-compose-localllm/`, `docker-compose-with-elasticstack/` and `docker-compose-with-nginx/`, beside a `docker/` directory, and the README's badge row links a Docker Hub image. The Installation section then documents only the manual path: clone, `pip3 install -r requirements.txt`, start Neo4j yourself, edit the config, run `python3 logontracer.py --run`. Four deployment shapes ship and not one is described. Two of them tell you something about the intended deployment anyway. The nginx variant implies TLS termination in front of the app, which the manual path does not have, and the local-LLM variant exists because the AI features default to OpenAI, since the AI setup steps say to enable analysis and enter your OpenAI API key and pick a GPT model, with no mention of pointing it somewhere else.
The v2 agent writes Cypher against your investigation graph
Version 2.0 adds four things under the heading of AI-powered security analysis. Security pattern analysis interprets graph query results and generates risk assessments with MITRE ATT&CK tactic mapping. An autonomous LLM agent iteratively generates and executes Cypher queries against the Neo4j graph without manual intervention. Generated Sigma rules convert findings into deployable detection content. Responses can be produced in English, Japanese or French. The mechanics matter for an incident response tool: the model is not summarising a report, it is writing database queries against the store holding your investigation, and the key is entered in the browser under Settings, then stored by the application. The README describes none of the data that leaves the machine, no retention behaviour, and no way to see what a query did beyond the AI History panel. The local-model compose variant is the only hint that a non-OpenAI path is possible.
Fourteen event IDs and three scoring methods
The graph is built from a fixed table of event IDs: 4624 and 4625 for successful logon and failure, 4662 for an operation on an object, 4672 for assigning special privileges, 4719 for a system audit policy change, 4720 and 4726 for account creation and deletion, the paired 4728, 4732 and 4756 for additions to security-enabled groups with 4729, 4733 and 4757 for removals, 4768 and 4769 for Kerberos ticket requests, 4776 for NTLM authentication, and 5137 and 5141 for directory service object creation and deletion. Hosts or IP addresses and account names found in those events become the nodes, which is how the tool answers which account tried to log on and from where. Scoring is separate: PageRank, a hidden Markov model and ChangeFinder are named as the methods for detecting malicious hosts and accounts, and event logs can also be shown in chronological order.
Elasticsearch import drops the timezone flag the others require
The EVTX and XML forms both require `-z <UTC offset>`, and the Sigma example uses `-z 9`. The Elasticsearch form has no such flag: it takes `--es` plus `-s`, `-u`, `-p` and `--es-server <ES host:port>`. So a log pulled from an Elasticsearch index is ingested without the timezone adjustment the file-based routes insist on, which is the kind of difference that shifts every timestamp in the resulting timeline. The Elasticsearch client library is also the one dependency with an upper bound, `elasticsearch-dsl>=7.0.0,<8.0.0`, while everything else in `requirements.txt` is open-ended above a floor. The tree holds an `es-index/` directory for the index side, and the requirements include `elasticsearch-dsl`, so the feature is wired rather than aspirational.
A two and a half year gap, and a sample graph in the repository
The release history has a hole in it: v1.6.0 on 2022-12-21, v1.6.1 on 2023-11-15, then v2.0.0 on 2026-04-22, with the last commit on master dated 2026-08-02. So the version described throughout the README as v2 has been out for about half a year, with commits landing since the tag, and the step before it is two and a half years old. Requirements say Python 3.9 or later with 3.12 recommended, and Neo4j 5.x in either Community or Enterprise, while multiple independent investigation cases, each in its own Neo4j database, are stated as an Enterprise Edition feature. The `sample/` directory ships a `Security.evtx`, a `data.tar.gz` and a `graph.db.tar.gz`, so you can look at a prepared graph before importing anything of your own.
Editorial conclusion
LogonTracer fits an incident responder who already has a Neo4j instance and a Security.evtx export, and who wants logon activity as a graph instead of a list of rows. Before the first run, change both passwords in `config/config.yml`, not just the one the comment marks, because the same value appears twice with two meanings. Avoid passing the database password on the command line where the process list can see it, and remember that an import replaces the existing graph unless you pass `--add`. Think hard about the AI features before enabling them: an agent writes and executes Cypher against your investigation database, and the README says nothing about what leaves the machine, though a local-model compose variant exists in the tree. Multiple investigation cases need Neo4j Enterprise. And if you only want the graph and the scoring, leave the OpenAI key alone; it is optional and only the v2.0 analysis needs it.
Frequently asked questions
What does LogonTracer do with a Security.evtx file?
It imports the log into Neo4j, turning the host names, IP addresses and account names found in fourteen logon-related event IDs into a graph you can browse. Hosts and accounts are then scored with PageRank, a hidden Markov model and ChangeFinder, and the same log can be viewed in chronological order.
Can I run LogonTracer without an OpenAI API key?
Yes. The requirements call the key optional and required only for the AI analysis features, so the graph, the Sigma scanning, the PageRank, Markov model and ChangeFinder analysis and the web interface all run without one. The v2.0 agent, the risk assessments and the Sigma rule generation are the parts that need it.
Does LogonTracer need Neo4j Enterprise?
Not for a single investigation. The requirements ask for Neo4j 5.x in Community or Enterprise, and the Enterprise Edition is named as what supports multiple independent cases, each stored in a separate Neo4j database.
Why did my LogonTracer import clear the previous graph?
Because clearing is the default. The base import commands replace the existing data, and the one that preserves it runs with `--add`, described as adding additional logs without deleting existing data. The web upload has the same choice as the Add additional files checkbox.
Where does LogonTracer keep its web interface password?
In `config/config.yml`, as `default_user` and `default_password` under the logontracer settings, and the shipped example sets them to `neo4j` and `password`. The comment says the user is the Neo4j username for the default LogonTracer account, and the same password appears again under the neo4j section, so change both.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jpcertcc-logontracer)