DEV Community

Taksh Patadia
Taksh Patadia

Posted on

I Built a Network Security Diagnostic Tool With Python’s Standard Library Only

I Built a Network Security Diagnostic Tool With Python’s Standard Library Only

For 72 hours, I had a strange constraint:

Build something useful. Don’t install a single third-party runtime dependency.

That sounds simple until you try to build something that deals with networking.

For the Zero Dependency 72-hour hackathon, I built TRACE — a passive network and security diagnostic tool that takes a domain and analyzes what happens when it tries to communicate with that target.

The goal wasn’t to build another port scanner.

I wanted TRACE to answer a more useful question:

“Where does the connection actually succeed or fail, and what can I observe about the target’s security configuration?”

What TRACE does

A TRACE scan follows roughly this path:

Target

DNS

TCP

HTTP / HTTPS

Redirects

TLS

Certificate

Security Headers

Findings

Risk Summary

Given a target such as:

google.com

TRACE can resolve its address, check TCP connectivity on ports 80 and 443, inspect HTTP and HTTPS responses, follow redirect chains, inspect TLS information, examine the certificate, check security-related HTTP headers, classify observations by severity, and produce a final security summary.

The important word here is passive.

TRACE isn’t claiming that it can prove a website is vulnerable. It reports what it can observe from the network and HTTP/TLS behavior.

That’s why the final report explicitly describes its confidence as:

PASSIVE / OBSERVATIONAL

The obvious question: why not just install packages?

That’s exactly what I would normally do.

For a networking project, the obvious choices might include packages such as:

  • requests or httpx for HTTP
  • dnspython for DNS
  • cryptography for deeper certificate and cryptographic handling
  • click or typer for CLI interfaces
  • pytest for testing

But the hackathon’s constraint was the point:

No third-party runtime dependencies.

Python had to do the work.

And that changed how I approached the entire project.

What I used instead

The Python standard library turned out to contain much more networking functionality than I initially expected.

The basic substitutions looked like this:

What I needed What I might normally install What TRACE used
DNS resolution dnspython socket
TCP connections higher-level networking libraries socket
HTTP communication requests / httpx http.client
HTTPS/TLS requests / other TLS wrappers ssl
URL parsing third-party helpers urllib.parse
CLI handling click / typer argparse
Timing external utilities standard-library timing functions
JSON handling external serializers json
Testing pytest unittest

The important lesson was that zero dependency does not mean zero abstraction.

The abstractions are still there.

They’re just lower-level.

DNS was the easy part

One of the first things TRACE needs to know is:

“Where is this domain?”

Python’s socket module can handle basic DNS resolution without installing anything.

Conceptually:

google.com

socket

142.x.x.x

That gave TRACE the first piece of evidence.

If DNS fails, there isn’t much point continuing with TCP, TLS, or HTTP.

So TRACE stops and reports that it cannot continue.

That also became one of our first useful failure cases to test.

TCP made the abstraction disappear

The next question is:

“Can I actually reach the target?”

TRACE checks TCP connectivity on ports 80 and 443.

A normal high-level library can make networking feel like:

response = requests.get(url)

But when you’re working closer to the socket layer, you have to think about the actual connection:

DNS

IP address

TCP connection

port

success / failure

That was one of the more useful parts of the challenge because it forced me to understand what the higher-level libraries normally hide.

HTTP was where things got more interesting

TRACE doesn’t just want to know whether an HTTP request succeeds.

It wants to observe the response.

For example, Google produced a redirect:

HTTP 301

redirect

HTTP 200

TRACE records the redirect chain instead of simply following it and throwing away the intermediate information.

That matters because the path itself can contain useful information.

One edge case taught me an important lesson

During testing, TRACE reported this for Google’s HTTP behavior:

HTTP → HTTPS Upgrade: NOT OBSERVED

At first glance, that sounds like:

“Google doesn’t use HTTPS.”

But TRACE had independently established that:

Port 443 → OPEN
TLS → TLSv1.3
Certificate → HEALTHY

So that conclusion would obviously be wrong.

The actual observation was narrower:

An HTTPS destination was not observed in the particular HTTP redirect chain TRACE followed.

That distinction matters.

I changed the way I thought about security observations because of this.

A diagnostic tool has to be careful not to turn:

“I didn’t observe X”

into:

“X does not exist.”

TLS was where the standard library became surprisingly useful

TRACE uses Python’s ssl functionality to inspect the TLS connection.

For a working HTTPS target, TRACE can observe things such as:

TLS Version : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Certificate : *.google.com
Issuer : Google Trust Services

It also calculates certificate validity information and reports whether the certificate appears healthy based on its validity period.

Again, the goal isn’t to recreate a complete certificate-analysis ecosystem.

It’s to extract useful information from a real TLS connection using functionality Python already provides.

Then came the security headers

TRACE checks several response headers, including:

  • HSTS
  • X-Content-Type-Options
  • Content-Security-Policy
  • Referrer-Policy

The tool turns each observation into a finding with:

Name
Severity
Status
Evidence
Impact
Recommendation

For example:

Finding:
HSTS
Severity:
LOW
Status:
NOT DETECTED
Evidence:
Strict-Transport-Security header absent
Impact:
The response does not provide an HSTS policy to browsers
Recommendation:
Consider enabling HSTS after validating HTTPS configuration

This is deliberately conservative.

A missing header isn’t automatically treated as a confirmed vulnerability.

It’s an observation that may represent a security improvement opportunity.

The part that took more thought: turning observations into a conclusion

Collecting data is only half the problem.

TRACE needed to answer:

“So what?”

That’s why it has a finding model with:

Observation

Severity

Evidence

Impact

Recommendation

Then those findings are aggregated into an overall risk summary.

For example:

Risk Level : LOW
High Findings : 0
Medium Findings : 0
Low Findings : 1
Informational : 3

And the tool explains the primary observation rather than simply printing:

Risk: LOW

That makes the output much more useful to someone who isn’t interested in reading raw HTTP headers.

The standard library wasn’t a magic button

One of the biggest misconceptions I had going into this was that “zero dependency” meant the project would simply be smaller.

It isn’t.

A dependency often hides complexity.

When you remove the dependency, the complexity doesn’t disappear.

You inherit it.

Instead of:

requests.get(...)

you start thinking about:

  • sockets
  • connections
  • TLS contexts
  • redirects
  • response parsing
  • timeouts
  • certificates
  • error handling
  • URL normalization

The package didn’t make those concepts disappear.

It just made me less aware of them.

The hackathon forced those layers back into view.

What I learned about AI-assisted development

I also used AI coding assistance during development.

But this hackathon made one thing very clear:

Generating code is not the same as understanding the code.

An AI can produce a function using socket or ssl very quickly.

That doesn’t mean the resulting implementation is correct.

The actual work was:

Generate

Run

Observe

Question

Debug

Understand

Test again

The project had to work under the zero-dependency constraint, and I needed to be able to explain why the implementation worked.

That made AI much more useful as a development partner than as a replacement for understanding.

Why I didn’t build everything

There is always another feature you can add.

More ports.

More TLS checks.

More headers.

A dashboard.

A database.

An AI explanation engine.

But a 72-hour hackathon is also a lesson in scope.

A smaller tool that:

  • works reliably,
  • handles failures,
  • explains its findings,
  • has tests,
  • has clear documentation,
  • and genuinely respects the dependency constraint

is more valuable than a huge project that barely works.

So TRACE stayed focused on its core purpose:

Passive network and HTTP/TLS diagnostics with security-oriented observations.

What zero dependencies actually changed

The most interesting result of the challenge wasn’t that I managed to avoid pip install.

It was that I started looking at the standard library differently.

Before this project, a lot of functionality felt like something you simply imported.

After building TRACE, I started asking:

“What is the package actually doing underneath?”

Sometimes the answer is surprisingly close to:

socket
ssl
http.client
urllib
json
argparse

The dependency wasn’t magic.

It was an abstraction.

And sometimes the standard library already had enough building blocks to create the abstraction I actually needed.

What I’d improve next

TRACE is intentionally not a replacement for professional security scanners.

There are several directions I’d explore with more time:

  • more robust IPv6 handling
  • richer network timing information
  • broader TLS analysis
  • more sophisticated redirect analysis
  • larger automated test coverage
  • machine-readable JSON reports
  • more configurable CLI options

But those are extensions.

The core experiment was successful:

Could I build a useful network/security diagnostic tool using Python’s standard library only?

Yes.

And the interesting part wasn’t avoiding packages.

It was discovering how much engineering those packages were doing for me.

Final takeaway

Zero dependency doesn’t mean zero complexity.

It means you’re choosing where that complexity lives.

With TRACE, I chose to put more of it in my own code and rely on Python’s standard library as the foundation.

That forced me to understand networking at a level I probably wouldn’t have reached by simply installing another package.

And that’s probably the biggest thing I’ll take away from the hackathon:

Before installing a dependency, understand what you’re actually asking it to do.

Top comments (1)

Collapse
 
arpan_singh_121 profile image
Arpan Singh

I love how you leveraged only the Python standard library to build a full‑featured network security diagnostic tool—it's a great reminder of what's possible without external dependencies. If you want to get even more eyes on your work, consider syndicating it on ZyVOP (zyvop.com) so other devs can discover it.