What happens when you build a security analysis tool in Python and deliberately remove every third-party runtime dependency?
Usually, I would reach for a few packages.
A parser here. A CLI framework there. A data-processing library. Maybe a logging package. Something for JSON. Something for configuration.
For the Zero Dependency 72-Hour Hackathon, I couldn't.
The rule was simple: standard library only.
So I built TraceLock — a lightweight security event correlation and attack analysis engine in Python, with zero third-party runtime dependencies.
The idea
TraceLock takes security event logs and tries to answer a question that raw logs often don't:
"What actually happened during this sequence of events?"
A single failed login isn't necessarily interesting.
A successful login isn't necessarily malicious.
A command being executed isn't necessarily suspicious.
But when the events occur in a sequence like:
Multiple authentication failures
↓
Successful authentication
↓
Command execution
↓
Privileged activity
the story becomes much more interesting.
TraceLock correlates those events and reconstructs them into an attack chain.
For example, one of my synthetic attack scenarios produces:
Credential Attack
→
Successful Access
→
Command Execution
→
Privileged Activity
The resulting assessment is:
Risk: CRITICAL
Score: 100/100
It also extracts evidence, produces behavioral analysis, identifies relevant MITRE ATT&CK-style behavioral mappings, generates recommendations, and can export the analysis as JSON.
Why build this with zero dependencies?
The Zero Dependency hackathon challenged participants to build useful software using only their language's standard library — no third-party runtime packages, frameworks, or external libraries.
For a security project, this constraint actually made sense.
Security tools are exactly the kind of software where the dependency chain deserves attention.
Every additional runtime package adds something that has to be trusted, maintained, updated, and potentially audited.
That doesn't mean third-party packages are bad.
It means that sometimes the right engineering question is:
"Do I actually need this dependency?"
TraceLock was my attempt to answer that question for a small security-analysis engine.
What TraceLock does
The project follows a pipeline:
Raw Security Logs
↓
Log Parser
↓
Event Correlation
↓
Attack Chain Reconstruction
↓
Evidence Extraction
↓
Behavior Analysis
↓
Anomaly Detection
↓
Risk Scoring
↓
MITRE Mapping
↓
Security Recommendations
↓
Terminal / JSON Report
The important part is that each stage is implemented directly in Python.
No external runtime framework is sitting underneath it.
The first challenge: parsing logs without a package
Parsing logs sounds easy until you actually start defining what a parser should do.
TraceLock's parser needs to extract things like:
- timestamps
- source IP addresses
- usernames
- event types
- commands
- privilege-related activity
Python's standard library already gives enough building blocks for this.
I used:
-
refor pattern matching -
datetimefor timestamp parsing -
dataclassesfor structured event objects -
typingfor type annotations
The parser converts raw log lines into structured LogEvent objects.
Conceptually:
Raw line
↓
Pattern matching
↓
Extract fields
↓
Classify event
↓
Create LogEvent
The interesting realization was that I didn't need a dedicated parsing framework.
The standard library already had the primitives.
The package I would normally reach for: a CLI framework
A command-line tool usually makes people reach for something like Click or Typer.
TraceLock doesn't use either.
Instead, the CLI is built with Python's built-in:
argparse
That gives TraceLock commands such as:
python -m tracelock.cli examples\sample_attack.log
and JSON output:
python -m tracelock.cli examples\sample_attack.log --json reports\sample_attack.json
The CLI handles the input file and optional JSON output without requiring another dependency.
This was probably one of the easiest substitutions.
argparse is surprisingly capable once you stop assuming that every CLI needs a framework.
The harder part: correlation
Parsing individual events is one thing.
Understanding the relationship between events is another.
TraceLock uses a correlation window and groups related events based on context such as source IP and user.
The correlation engine looks for meaningful sequences rather than treating every event independently.
For example:
10.10.10.50
↓
5 authentication failures
↓
successful authentication
↓
command execution
↓
privileged activity
The system reconstructs this as one attack chain instead of five unrelated observations.
This required thinking about:
- time windows
- event ordering
- source identity
- duplicate-chain prevention
- scoring
- explanations
This was one of the places where I felt the zero-dependency constraint most strongly.
There wasn't a library I could simply call to "understand this sequence."
I had to define the behavior myself.
Turning events into an attack story
A security analyst doesn't just want:
event_1
event_2
event_3
event_4
They want a story.
So TraceLock has a story-building stage that converts correlated events into a chronological narrative.
For a full attack chain, the title becomes:
Credential Attack → Successful Access → Command Execution → Privileged Activity
The report also contains a timeline, stages, evidence, and a conclusion.
This was an important design decision:
Detection is more useful when the result explains itself.
A score without context isn't very helpful.
Risk scoring without a machine-learning framework
Another thing I could have outsourced to a package is scoring.
I didn't.
TraceLock uses a custom risk-scoring system based on the observed event sequence and security factors.
For the full synthetic attack chain, the resulting score is:
100 / 100
CRITICAL
The point isn't that 100 is some universal measurement of real-world risk.
It is a deterministic assessment produced from the evidence TraceLock observed.
That distinction matters.
A security tool should not pretend that a simple heuristic is magically equivalent to a complete security investigation.
MITRE ATT&CK mapping
TraceLock also maps observed behaviors to relevant MITRE ATT&CK techniques.
The current mappings include:
T1110 → Brute Force
T1078 → Valid Accounts
T1059 → Command and Scripting Interpreter
T1068 → Exploitation for Privilege Escalation
These mappings are treated as behavioral mappings, not proof that a particular technique definitely occurred.
That distinction is important because log evidence alone often cannot establish an attacker's exact intent.
The goal is to provide useful security context rather than manufacture certainty.
Evidence extraction
One of the things I wanted TraceLock to do was show why it reached a conclusion.
For the sample attack, the report extracts evidence such as:
- authentication failures
- successful authentication
- command execution
- privileged activity
- multi-stage correlation
The result is closer to:
Finding
+
Evidence
+
Timeline
+
Risk
+
Explanation
instead of simply:
CRITICAL!!!
That makes the output much more useful to someone actually investigating an event.
Behavior and anomaly analysis
TraceLock also creates a behavior profile from the observed chain.
For the full attack scenario, it identifies a behavioral progression such as:
Credential Compromise
→
Privilege Escalation
with a confidence value of:
95%
The anomaly stage produces multiple findings from the same evidence and combines them into an overall anomaly assessment.
For the sample attack:
Anomaly Score: 100/100
Severity: CRITICAL
Again, these values are part of TraceLock's deterministic analysis model, not claims that the tool can replace a production SOC or SIEM.
Recommendations
Detection without action is only half the job.
TraceLock therefore generates security recommendations based on the detected behavior.
For the full attack chain, the report produces five recommendations.
The goal is to move from:
"This looks suspicious."
to:
"Here are the next security actions you should consider."
The standard-library replacements
This was the heart of the Zero Dependency challenge.
Instead of importing packages, I built the required functionality from Python's standard library.
My STDLIB.md documents the approach.
Some of the important substitutions were:
| Normally reached for | TraceLock approach |
|---|---|
| Pydantic | dataclasses |
| Click | argparse |
| python-dateutil | datetime |
| orjson / ujson | json |
| Rich | standard print() and formatting |
| pandas | lists and dictionaries |
| NumPy | built-in arithmetic and collections |
| scikit-learn | custom scoring logic |
| Loguru | standard output/file I/O |
| PyYAML | text parsing and standard data structures |
| requests |
urllib where needed |
Not every project needs all of these packages.
The point of the table is to document the kinds of third-party functionality that could normally be used for similar tasks and what standard-library primitives are available instead.
The part that surprised me
The biggest lesson wasn't:
"Python has a lot in its standard library."
I already knew that.
The bigger lesson was:
Packages hide engineering decisions.
When you install a library, you inherit decisions about:
- data structures
- error handling
- parsing behavior
- edge cases
- formatting
- APIs
- performance trade-offs
When you remove the package, those decisions become yours.
That's both the difficult part and the educational part.
What was harder than the documentation made it look
The standard library makes many things possible.
It doesn't necessarily make them effortless.
The hardest part wasn't importing the modules.
It was designing the behavior.
For example:
1. Correlation isn't just parsing
Finding events is easy.
Deciding which events belong to the same attack chain requires rules.
2. A report needs an explanation
Generating a score is easy.
Generating a score that a human can understand requires more thought.
3. Dependency removal changes the architecture
Without a framework doing work for you, every layer has to have a clear responsibility.
That pushed TraceLock toward a modular design:
parser
correlator
risk
story
evidence
behavior
anomaly
mitre
recommendation
report
cli
4. Zero dependency also means zero hiding
If something goes wrong, there's no package to blame.
The behavior is yours.
And that's actually a good thing for learning.
Testing it
I didn't want the zero-dependency claim to be just something written in the README.
TraceLock includes automated tests.
Running:
python -m pytest -v
produces four passing tests covering:
test_normal_login
test_brute_force
test_command_activity
test_full_attack_chain
The important distinction is that pytest is a development/testing dependency only.
It is not required to run TraceLock.
The runtime itself uses only Python's standard library.
Proving the dependency claim
I also included a deps-proof.txt file in the repository.
The proof records:
Python: 3.13.14
Runtime dependencies: STANDARD LIBRARY ONLY
Third-party runtime packages: 0
The repository also includes:
STDLIB.md
which documents the standard-library approach and the development-only testing dependency.
The goal was to make the claim verifiable rather than simply saying:
"Trust me, bro. No dependencies."
A real run
Using the included synthetic attack log:
python -m tracelock.cli examples\sample_attack.log --json reports\sample_attack.json
TraceLock detects:
Attack chains detected: 1
Title:
Credential Attack → Successful Access → Command Execution → Privileged Activity
Risk:
CRITICAL
Score:
100/100
Evidence:
5 items
Behavior:
Credential Compromise → Privilege Escalation
Behavior confidence:
95%
Anomaly:
100/100
Severity:
CRITICAL
It also generates the JSON report successfully.
The sample scenario contains five authentication failures followed by successful authentication, command execution, and privileged activity.
What I learned
This hackathon changed the way I look at dependencies.
Before this project, the mental model was often:
Need feature
↓
Search package
↓
Install package
↓
Use package
Zero Dependency forced me to think:
Need feature
↓
What does the feature actually require?
↓
What does the language already provide?
↓
Can I compose those primitives?
↓
What trade-offs am I accepting?
That second process takes more effort.
But it teaches you what's actually happening underneath the abstraction.
Does this mean third-party packages are bad?
No.
That isn't the lesson I took from the hackathon.
Libraries exist for good reasons.
A mature package can provide:
- better edge-case handling
- stronger performance
- broader compatibility
- years of maintenance
- extensive testing
- features that aren't worth rebuilding yourself
I wouldn't recommend replacing every dependency with handwritten code in a production system.
The lesson is different:
Know what you're depending on.
And know enough about the underlying problem that you can recognize when a dependency is genuinely valuable versus when you're importing an entire abstraction for a small piece of functionality.
Why TraceLock matters
TraceLock is not intended to replace a production SIEM, EDR, SOC, or professional incident-response platform.
It's a lightweight security-analysis engine and an exploration of how far you can go with Python's standard library.
The interesting part isn't just that it has zero runtime dependencies.
It's that a reasonably complete pipeline can still exist:
Logs
↓
Parsing
↓
Correlation
↓
Attack reconstruction
↓
Evidence
↓
Behavior
↓
Anomaly detection
↓
Risk scoring
↓
MITRE context
↓
Recommendations
↓
Reports
All without installing a runtime package.
Final thoughts
The most useful thing I got from Zero Dependency wasn't a dependency-free project.
It was a better question.
Instead of immediately asking:
"Which package should I install?"
I now ask:
"What is the package actually doing for me?"
Sometimes the answer is:
"A lot. Use the package."
Sometimes it's:
"I can build this from the standard library."
Knowing the difference is the real skill.
TraceLock was my attempt to put that idea into practice — by building a security event correlation and attack analysis engine from Python's standard library, documenting the substitutions, testing the implementation, and proving that the runtime dependency count is zero.
And honestly, writing the code was only half the challenge.
The other half was discovering what I had been letting packages hide from me.
Try TraceLock
The source code, example logs, tests, dependency proof, standard-library documentation, and usage instructions are available in the TraceLock GitHub repository.
If you're interested in security tooling, dependency reduction, or simply understanding what your language can do before reaching for another package, feel free to explore it.
Top comments (0)