Back to Articles

Hetty: Building a Modern HTTP Security Proxy with Go and GraphQL

[ View on GitHub ]

Hetty: Building a Modern HTTP Security Proxy with Go and GraphQL

Hook

The most popular tool in application security, Burp Suite, runs on Java and costs $449/year. Hetty achieves 80% of its functionality in a 15MB binary that starts in under a second.

Context

For nearly two decades, security researchers and bug bounty hunters have relied on a handful of HTTP proxies to intercept, inspect, and manipulate web traffic. Burp Suite dominated the commercial space while OWASP ZAP served the open-source community. Both tools share a common heritage: they're built on the JVM, require significant system resources, and carry the complexity of supporting every possible use case.

The penetration testing workflow hasn't fundamentally changed, but developer expectations have. Modern tooling emphasizes fast startup times, minimal dependencies, and API-first architectures. Hetty emerged from this gap—a recognition that 90% of security research involves straightforward HTTP interception, request modification, and traffic analysis. By focusing on these core workflows and leveraging Go's performance characteristics, Hetty delivers a toolkit that feels native to contemporary development practices. It's not trying to be Burp Suite; it's reimagining what an HTTP security proxy should look like in 2024.

Technical Insight

Hetty's architecture reveals thoughtful design decisions that prioritize developer ergonomics without sacrificing functionality. At its core, the application is structured as three loosely coupled layers: an HTTP proxy engine, a GraphQL API, and a React-based admin interface, all compiled into a single static binary.

The proxy implementation leverages Go's net/http package with custom certificate authority management. When you launch Hetty, it generates a CA certificate on first run and stores it in your project directory. The proxy intercepts HTTPS traffic by dynamically generating certificates for each domain, signed by this local CA. Here's how Hetty handles the certificate generation for a target domain:

// Simplified from Hetty's proxy/ca package
func (ca *CA) GenerateCert(host string) (*tls.Certificate, error) {
    serialNumber, _ := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
    
    template := x509.Certificate{
        SerialNumber: serialNumber,
        Subject: pkix.Name{
            Organization: []string{"Hetty"},
            CommonName:   host,
        },
        NotBefore:             time.Now(),
        NotAfter:              time.Now().Add(365 * 24 * time.Hour),
        KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
        ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
        BasicConstraintsValid: true,
        DNSNames:              []string{host},
    }
    
    certDER, err := x509.CreateCertificate(rand.Reader, &template, ca.cert, &ca.privateKey.PublicKey, ca.privateKey)
    // Certificate caching and TLS config returned
}

This approach is more elegant than Java-based alternatives because Go's standard library provides robust cryptographic primitives without external dependencies. The entire CA management system, including certificate caching and renewal, fits in under 500 lines of code.

The storage layer uses SQLite with a project-based model that's brilliantly simple. Each project is a single .db file containing intercepted requests, responses, scope rules, and sender history. This design choice means you can zip up a project file and share it with colleagues, archive research work, or version control your testing sessions. The schema is straightforward:

CREATE TABLE http_requests (
    id INTEGER PRIMARY KEY,
    proto TEXT NOT NULL,
    url TEXT NOT NULL,
    method TEXT NOT NULL,
    body BLOB,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE http_responses (
    id INTEGER PRIMARY KEY,
    request_id INTEGER NOT NULL,
    proto TEXT NOT NULL,
    status_code INTEGER NOT NULL,
    body BLOB,
    FOREIGN KEY (request_id) REFERENCES http_requests(id)
);

What makes Hetty architecturally interesting is the GraphQL API layer sitting between storage and UI. Traditional security proxies expose REST endpoints or custom protocols, but GraphQL provides precise data fetching that's critical for performance when dealing with thousands of captured requests. The admin interface can query exactly the fields it needs:

query GetProjectRequests($projectId: ID!, $scope: String) {
  httpRequestLog(projectId: $projectId, scope: $scope) {
    edges {
      node {
        id
        url
        method
        response {
          statusCode
          contentLength
        }
      }
    }
  }
}

This means the UI can load request metadata quickly, then fetch full bodies only when a user clicks on a specific request. Compare this to tools that load entire request/response pairs into memory—Hetty's approach scales gracefully to projects with 100,000+ intercepted requests.

The Chrome launcher integration demonstrates Hetty's focus on reducing friction. Instead of manually configuring proxy settings and trusting certificates, you run hetty --chrome, and it launches Chrome with the proxy preconfigured and the CA certificate trusted for that session. The implementation uses Chrome's command-line flags to achieve this zero-configuration experience, eliminating the most tedious part of setting up an HTTP proxy for testing.

Gotcha

Hetty's youth shows in its feature gaps compared to mature alternatives. The most glaring omission is automated vulnerability scanning—Burp Suite Pro's active scanner and OWASP ZAP's spider are absent. If your workflow depends on automatic injection testing, fuzzing, or crawling, Hetty requires manual effort or external tools. The sender/repeater functionality exists but lacks templates, variable substitution, and request chaining that power users expect.

The extension system is practically nonexistent. Burp Suite's ecosystem includes hundreds of community extensions for specialized tasks like JWT manipulation, AWS signature calculation, or custom authentication flows. Hetty doesn't yet provide hooks for programmatic extension, which means custom workflows require forking the codebase. For teams with specific integration needs—like importing findings into Jira, correlating with WAF logs, or custom request signing—this limitation is significant. The SQLite backend, while convenient for portability, can become a bottleneck with multi-gigabyte projects or when multiple team members need concurrent access to the same dataset.

Verdict

Use Hetty if you perform manual security testing, bug bounty hunting, or API research where you spend most of your time intercepting traffic, replaying requests, and analyzing responses. It's ideal when you value fast startup, simple deployment, and want to avoid Java runtime overhead or commercial licensing costs. Perfect for individual researchers, small teams, or anyone who wants transparent, auditable tooling without vendor lock-in. Skip it if you need automated vulnerability scanning, require a mature plugin ecosystem, depend on advanced Burp Suite features like session handling rules or macro recording, or work in enterprise environments requiring collaborative features and centralized management. Also skip if your testing involves complex authentication flows that require custom extension development—you'll be fighting the tool rather than leveraging it.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/cybersecurity/dstotijn-hetty.svg)](https://starlog.is/api/badge-click/cybersecurity/dstotijn-hetty)