Project Github Repository
Learning Path: Harvard CS50's Introduction to Programming with Python (CS50P)
Project Type: Security Operations, Python Development, Log Analysis and Automation
Environment: Python 3, Visual Studio Code, Windows PowerShell, Git and GitHub
Tools and Libraries: Python Standard Library, JSON, CSV, Regular Expressions, collections.Counter, datetime, pathlib, argparse, pytest, mypy
Final Validation: 37 automated tests passed; mypy reported no issues
Dataset: 62 simulated login events, including 8 intentionally invalid records
Python SOC Login Analyzer: Project Overview
The Python SOC Login Analyzer is the outcome of my journey through Harvard's CS50P, where I set out to strengthen my programming fundamentals by applying each new concept to a practical cybersecurity problem.
My goal was not simply to learn Python syntax or complete programming exercises. I wanted to understand how programming could support the daily work of a Security Operations Center (SOC) analyst, particularly when dealing with authentication events, suspicious login patterns, malformed records, and investigation reporting.
Rather than build an entirely different project every week, I developed a small login analysis script and progressively improved it as my Python knowledge expanded.
What started as a simple program that classified a single login alert eventually became a structured application capable of validating event records, identifying suspicious activity, tracking sensitive accounts, summarizing repeated IP addresses, recording invalid events, and exporting investigation reports.
The final CS50P Python Project brought these capabilities together in a single application with automated testing, command-line arguments, type annotations, and a clearer separation between event processing and reporting.
This case study documents the development process, the challenges I encountered, the decisions I made, and how I approached the work through a SOC analyst's investigative mindset.
1. Defining the Problem: Why SOC Log Analysis?
Authentication logs are an important source of evidence during security investigations. They can reveal repeated failed login attempts, unusual account activity, and patterns that may warrant further investigation.
However, raw event records do not automatically tell an analyst what happened.
Before reaching a conclusion, an analyst must determine whether the data is valid, identify relevant activity, correlate related events, and distinguish observations from assumptions.
I wanted to build a tool that could support part of this workflow.
The initial problem statement was straightforward: given a set of login events containing usernames, source IP addresses, failed-login counts, and timestamps, could Python process those records and produce a useful security summary?
I established several objectives for the Python SOC Login Analyzer:
- Validate incoming login records before analyzing them.
- Classify events using clearly defined severity thresholds.
- Identify source IP addresses appearing across multiple events.
- Highlight activity involving sensitive usernames.
- Continue processing when individual records contain errors.
- Produce structured output suitable for review.
- Verify important functionality using automated tests.
The data would be simulated, allowing me to deliberately introduce suspicious patterns and malformed records without using real credentials or exposing sensitive organizational information.
This was a learning project, not a production SIEM. The goal was to understand the engineering decisions behind a reliable analysis workflow.
2. Establishing the Baseline: Python Fundamentals
I began CS50P with the fundamentals: variables, data types, functions, user input, string operations, and conditional statements.
These concepts formed the foundation of my first personal security script.
Week 1: Single-Alert SOC Triage
My first SOC-focused Python program collected basic information about a login event, including the username, source IP address, number of failed login attempts, and whether a successful login followed the failures.
Using functions and conditional statements, I assigned a severity level based on the supplied information.
The early program was simple, but it introduced an important principle: detection logic should follow explicit rules rather than arbitrary conclusions.
It also helped me understand how Python functions could separate individual responsibilities, such as collecting data, classifying activity, and presenting results.
Week 2: Moving from One Event to Multiple Events
A SOC analyst rarely investigates only one record.
I therefore extended the project to process multiple login events using lists, dictionaries, loops, and counters.
Instead of manually reviewing each event, the program could iterate through a collection, classify records, count severity levels, and identify repeated source IP addresses.
This was my first meaningful step toward SOC Log Analysis through automation.
It demonstrated how even basic Python data structures could reduce repetitive analysis work.
3. The First Reliability Challenge: Malformed Events
Week 3: Exception Handling
One of the first problems I deliberately introduced was invalid input.
What happens when a failed-login count contains text instead of an integer? What if an event is missing a required field?
Without appropriate error handling, one malformed record could interrupt the entire analysis.
I introduced try and except blocks to handle expected failures and allow processing to continue.
The analyzer began distinguishing between valid and invalid events instead of treating every record as trustworthy.
This changed how I thought about the project.
From an investigative perspective, an invalid event should not silently disappear, but it also should not prevent other records from being analyzed.
That principle became increasingly important as the project developed.
4. Building a More Realistic Analysis Workflow
Week 4: Libraries, JSON and Timestamps
The next improvement was moving event data outside the Python source code.
I began loading simulated login records from a JSON file, making the input easier to maintain and modify independently.
I also introduced standard-library tools, including collections.Counter, datetime, and pathlib.
Counter simplified severity and IP-address aggregation. Timestamp parsing allowed the program to validate whether records contained recognizable date-time values, while pathlib improved file-path handling.
The program could now process an external dataset, reject incomplete records, summarize valid events, and report repeated IP addresses.
One limitation remained: the early IP-address validation only checked whether the field contained a nonempty string. It did not yet verify that an address followed valid IPv4 rules.
I retained that limitation in my documentation rather than presenting the validator as more capable than it was.
Week 5: Testing the Detection Logic
As the analyzer grew, manually checking its output became less reliable.
I introduced pytest and refactored the program into smaller functions that could be tested independently.
The tests covered severity classification, invalid inputs, event totals, repeated IP addresses, and boundary conditions.
For example, my severity rules were based on failed-login counts:
| Failed Login Attempts | Classification |
|---|---|
| 0–4 | LOW |
| 5–9 | MEDIUM |
| 10 or more | HIGH |
Testing values around the boundaries helped verify that the classification logic behaved consistently.
The Week 5 version reached five passing automated tests.
This was an important change in my development process. Instead of assuming a function worked because one example produced the expected output, I began verifying its behavior across different conditions.
5. Turning Analysis into Investigation Evidence
Week 6: CSV and Report Generation
A terminal summary is useful during development, but analysts also need outputs they can review, preserve, and share.
I extended the analyzer to export validated records into a CSV file and generate a human-readable text report.
The CSV included event details and severity classifications, while the report summarized totals, severity distribution, and repeated source IP addresses.
I also introduced tests for generated files using pytest's temporary-directory functionality.
This presented another engineering consideration: the original JSON input should remain unchanged while the program produces separate output artifacts.
By the end of Week 6, the project had seven passing tests and could produce repeatable analysis reports.
The Python SOC Login Analyzer was beginning to resemble a small investigation utility rather than a classroom exercise.
6. Improving Detection Accuracy with Regular Expressions
Week 7: IPv4 Validation and Sensitive-Account Monitoring
The next challenge was improving the quality of accepted event data.
A nonempty IP-address field does not guarantee a valid IP address. I used regular expressions and additional checks to validate IPv4 structure, octet ranges, and leading-zero rules.
I also introduced a case-insensitive watchlist for three sensitive usernames:
admin, administrator, and root.
The analyzer could now identify events involving these accounts and count how many were classified as HIGH severity.
The results were included in the CSV and text report.
This introduced a useful distinction between detection and interpretation.
A login attempt involving an administrator account may deserve attention, particularly when accompanied by repeated failures. However, a watchlist match alone does not prove that an account has been compromised.
I designed the output to highlight investigation leads rather than declare confirmed incidents.
The Week 7 project reached 16 passing automated tests.
7. Refactoring the Application with Object-Oriented Programming
Week 8: Separating Event Validation, Analysis and Reporting
By Week 8, the application had accumulated several responsibilities.
Validation, detection, aggregation, reporting, and file handling were becoming increasingly interconnected.
I used object-oriented programming to reorganize the project into three main classes.
LoginEvent represents an individual authentication event. It validates the username, IPv4 address, failed-login count, and timestamp, and provides computed properties for severity and sensitive-account status.
SOCAnalyzer processes collections of events. It distinguishes valid and invalid records, counts severity levels, identifies repeated IP addresses, and summarizes sensitive-account activity.
SOCReport handles output generation, including CSV exports and readable investigation reports.
This separation made the code easier to reason about.
Instead of treating the application as one long sequence of instructions, I began thinking in terms of components with specific responsibilities.
I also preserved compatibility functions for earlier interfaces, allowing existing tests and workflows to continue working while the internal architecture changed.
The Week 8 version reached 30 passing tests.
For me, this was one of the clearest demonstrations of why software architecture matters. A working program can still be difficult to maintain, and refactoring is often necessary as requirements expand.
8. The Final CS50P Python Project: Bringing Everything Together
Week 9: From Learning Exercise to Complete Application
After studying the remaining CS50P concepts, I created a dedicated Final_Project directory to consolidate the analyzer into a more complete Python application.
This final stage introduced constants, sets, type annotations, docstrings, comprehensions, enumerate(), generators, and command-line argument parsing.
Rather than adding these concepts only to demonstrate that I had learned them, I looked for places where they improved the program.
Constants centralized the severity thresholds and sensitive-account watchlist.
List, dictionary, and set comprehensions helped construct useful summaries and identify unique sensitive usernames.
enumerate() allowed the analyzer to associate invalid records with their original event numbers.
A generator provided a way to iterate through HIGH-severity events without constructing another complete list.
Type annotations made function contracts clearer, while mypy provided an additional static check.
Finally, argparse allowed the application to accept configurable input and output locations.
The result was a more flexible Python SOC Login Analyzer that could be executed from the command line and tested as a cohesive application.
9. Final Application Architecture
The completed workflow follows a sequence similar to a basic SOC investigation pipeline.
Input collection: The application loads simulated login events from a JSON file.
Validation: Each record is checked for required fields, a nonempty username, a valid IPv4 address, a nonnegative integer failed-login count, and a parseable timestamp.
Classification: Valid records are assigned LOW, MEDIUM, or HIGH severity using the defined thresholds.
Detection and correlation: The analyzer identifies repeated source IP addresses, sensitive-account activity, HIGH-severity sensitive-account events, and unique sensitive usernames.
Error tracking: Invalid records are counted and documented with their event positions and validation errors.
Reporting: Validated events are exported to CSV, while a separate text report presents the analysis summary and invalid-event details.
The application also provides compatibility functions alongside its class-based implementation.
This architecture keeps event validation separate from aggregation and report generation, making the code easier to test and extend.
10. Investigation Dataset and Results
To validate the final workflow, I used a simulated dataset containing 62 login events.
Eight records were intentionally invalid, allowing me to test how the application responded to missing fields, invalid values, malformed IP addresses, and incorrect timestamps.
The remaining 54 records were valid.
Final SOC Log Analysis Summary
| Metric | Result |
|---|---|
| Total login events | 62 |
| Valid events | 54 |
| Invalid events | 8 |
| HIGH severity | 12 |
| MEDIUM severity | 12 |
| LOW severity | 30 |
| Sensitive-account events | 17 |
| HIGH-severity sensitive-account events | 12 |
| Automated tests | 37 passed |
| Static type checking | No issues reported |
The analyzer also records repeated IP occurrences and generates lists of sensitive usernames for review.
These results demonstrate that the application can distinguish valid data from malformed input, apply consistent classification rules, and preserve useful investigation details.
They do not establish that the simulated activity represents confirmed malicious behavior.
11. Challenges, Debugging and Lessons Learned
Building the final project was not simply a matter of writing the correct functions once.
Several challenges shaped the development process.
Challenge 1: Preventing Invalid Records from Interrupting Analysis
As the dataset expanded, validation became more important.
Missing failed-login counts, negative values, incorrect data types, invalid IPv4 addresses, and malformed timestamps needed to be handled consistently.
The solution was to validate each event independently, catch expected validation errors, and continue processing the remaining records.
I also improved the report so that invalid records were not merely counted. Their original event numbers and error messages were preserved.
This matters during an investigation because analysts need to understand what was excluded and why.
Challenge 2: Maintaining Existing Behavior During Refactoring
Moving from functions to classes introduced the risk of breaking earlier functionality.
I addressed this by separating responsibilities while retaining compatibility functions and expanding the automated test suite.
Regression testing became part of the development workflow.
A refactor was not considered successful simply because the new structure looked cleaner. The existing behavior still needed to pass its tests.
Challenge 3: Handling File Paths and Command-Line Inputs
As the application became more independent, hard-coded paths became less suitable.
I introduced pathlib and argparse so the program could use sensible defaults while also accepting custom input and output directories.
I added tests for custom output locations, missing input files, and invalid JSON.
This made the application more usable outside a single development session.
Challenge 4: Improving the Clarity of Reports
The report evolved alongside the analyzer.
Initially, the emphasis was on totals and severity counts. Later versions included sensitive-account findings, repeated IP addresses, detection summaries, and detailed invalid-event information.
I also improved the formatting to make sections easier to read.
This reinforced an important SOC reporting principle: the purpose of a report is not merely to display data, but to help another person understand the findings.
Challenge 5: Git Repository Hygiene on Windows
Preparing the completed project for GitHub introduced a different kind of problem.
My CS50P work was already inside an existing Git repository, and some Python cache files from earlier weeks had been tracked.
Adding entries to .gitignore would prevent new untracked cache files from being included, but it would not automatically remove files Git was already tracking.
I reviewed the repository root, identified tracked cache artifacts, and worked through the distinction between ignoring files and removing them from Git's index.
I also reviewed the existing .gitattributes configuration, which used * text=auto for text-file normalization.
This part of the process reminded me that finishing an application involves more than writing Python. Repository organization, generated files, documentation, and version control are also part of software delivery.
12. Testing and Verification
I used automated testing throughout the later stages of the project, rather than waiting until the final application was complete.
The final test suite contained 37 passing tests covering important aspects of the analyzer, including event validation, severity boundaries, sensitive-account detection, analysis summaries, invalid-record handling, generated reports, and command-line behavior.
I also used mypy to check the annotated Python source.
The final verification reported no type-checking issues.
The main commands were:

python -m pytest test_project.py -v

python -m mypy project.py
To execute the application using its default input and output locations:
python project.pyTo specify input and output paths:
python project.py --input login_events.json --output reportsThe generated outputs include:
cleaned_login_events.csv, containing validated login events.soc_report.txt, containing the investigation summary and invalid-event details.
These tests provide confidence in the behaviors they cover. They do not replace testing against real-world log formats, operational environments, or adversarial input.
13. Limitations and Future Improvements
The Python SOC Login Analyzer is an educational application built around simulated authentication events.
Its detection logic uses fixed failed-login thresholds and a small sensitive-account watchlist. It does not perform threat-intelligence lookups, IP reputation analysis, behavioral baselining, or comprehensive incident correlation.
The IPv4 validator does not support IPv6, and the current dataset does not represent the full complexity of enterprise authentication telemetry.
Possible future improvements include support for Windows Event Logs and Linux authentication logs, configurable detection rules, time-window correlation, additional output formats, and integration with security monitoring platforms.
A future version could also introduce a web dashboard, persistent database storage, and more advanced investigation workflows.
These are potential extensions rather than capabilities of the completed CS50P project.
14. What This Project Taught Me
The biggest lesson from this project was that programming is not just about getting a script to run.
I learned to approach software development as a process of understanding requirements, designing logic, handling unexpected conditions, validating results, and documenting decisions.
The same investigative habits I apply to cybersecurity were useful here.
When something failed, I needed to identify the affected component, reproduce the behavior, examine the input, isolate the cause, implement a correction, and test again.
Over the course of CS50P, I moved from writing small scripts with basic conditionals to organizing an application around classes, reusable functions, automated tests, structured data, and command-line workflows.
I also learned the importance of distinguishing between what a tool actually detects and what an analyst might infer from its output.
A HIGH-severity event is not automatically an attack. A repeated IP address is not automatically malicious. An administrator-account match is not proof of compromise.
The software can organize evidence and highlight patterns, but investigation and interpretation still matter.
15. Conclusion: From Python Fundamentals to Security Engineering
Completing my CS50P learning journey gave me a stronger foundation in Python, but the Python SOC Login Analyzer gave me an opportunity to apply that knowledge to a problem I understood from cybersecurity.
The project began with a single-alert triage script and evolved through multiple stages of validation, log analysis, error handling, testing, file processing, regular expressions, object-oriented programming, and reporting.
Its final outcome was a tested command-line application capable of analyzing 62 simulated login events, identifying suspicious patterns, recording invalid data, and generating structured investigation outputs.
More importantly, the experience strengthened how I approach technical problems.
I now have a better understanding of how to break an application into components, test assumptions, investigate failures, and improve a system incrementally.
This CS50P Python Project marks the completion of one learning stage and the beginning of another: building independent applications that combine Python with real-world engineering problems.
For me, that is the value of learning to program—not simply knowing the syntax, but being able to use it to investigate, build, test, and improve something useful.
All authentication records used in this project are simulated. The severity classifications and detection findings are educational indicators, not confirmed security incidents.
See my first incident post ever: Real WordPress Security Incident & Credential Compromise Case Study? It's a hectic day of work experience as a WordPress developer. Yeah, an attacker got in!

