DEV Community

Charlie Hu
Charlie Hu

Posted on

Sanitize Before You Send: A Local Proxy for AI Coding Assistants

A free AI server is a trade. You trade a little privacy for zero infrastructure cost. Most developers accept that trade without thinking about what exactly leaves their machine. Code snippets, API keys, internal hostnames, and even file paths all end up in a prompt. A lightweight local proxy can strip the sensitive parts before they travel anywhere. This article shows how to build one in under fifty lines of Python, and why it should sit between your editor and MonkeyCode's free server.

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

The Problem: Your Code Leaves the Building

MonkeyCode is an open source project that offers a free server and a 10-million-token grant. That is a generous offer for experimentation and daily coding tasks. But the free server is remote, which means every prompt you send crosses a network boundary. Even if the provider is trustworthy, minimizing exposure is a basic hygiene practice.

The risk is not abstract. A developer pastes a config file into a chat window and forgets that it contains a database password. Another sends a stack trace with internal IP addresses. These small leaks accumulate. A proxy gives you a single choke point where sensitive patterns can be caught before they leave.

The Solution: A Local Filtering Proxy

The idea is simple. Run a small HTTP server on localhost. Point your AI coding tool at that server instead of the remote endpoint. The proxy inspects every request body, replaces sensitive patterns with placeholders, and forwards the sanitized payload to the real server. Responses pass back unchanged.

This approach works with any tool that lets you configure a custom base URL. It adds a few milliseconds of latency, which is negligible compared to network round-trip time.

Building the Proxy

The following Python script uses only the standard library. It listens on 127.0.0.1:8080, sanitizes the JSON body, and forwards the request to an endpoint stored in the MONKEYCODE_ENDPOINT environment variable.

#!/usr/bin/env python3
"""A minimal privacy proxy for AI coding assistants."""

import json
import os
import re
import urllib.request
from http.server import BaseHTTPRequestHandler, HTTPServer

TARGET = os.environ.get("MONKEYCODE_ENDPOINT", "https://api.monkeycode.example/v1/chat/completions")

# Patterns that match common secrets and internal identifiers.
SECRET_PATTERNS = [
    (re.compile(r"(?i)(api[_-]?key|password|secret|token)\s*[:=]\s*[\"']?[A-Za-z0-9_\-]{8,}"), r"\1=[REDACTED]"),
    (re.compile(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b"), "[IP_REDACTED]"),
    (re.compile(r"\b(?:AKIA|ASIA)[A-Z0-9]{16}\b"), "[AWS_KEY_REDACTED]"),
    (re.compile(r"(sk-[A-Za-z0-9]{20,})"), "[OPENAI_KEY_REDACTED]"),
]

def sanitize(text: str) -> str:
    for pattern, replacement in SECRET_PATTERNS:
        text = pattern.sub(replacement, text)
    return text

def sanitize_payload(payload: dict) -> dict:
    if "messages" not in payload:
        return payload
    for message in payload["messages"]:
        if isinstance(message.get("content"), str):
            message["content"] = sanitize(message["content"])
    return payload

class ProxyHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get("Content-Length", 0))
        body = self.rfile.read(length)
        try:
            payload = json.loads(body)
        except json.JSONDecodeError:
            self.send_response(400)
            self.end_headers()
            return

        clean_payload = sanitize_payload(payload)
        req = urllib.request.Request(
            TARGET,
            data=json.dumps(clean_payload).encode(),
            headers={"Content-Type": "application/json"},
            method="POST",
        )
        try:
            with urllib.request.urlopen(req) as resp:
                response_body = resp.read()
                self.send_response(resp.status)
                self.send_header("Content-Type", resp.headers.get("Content-Type", "application/json"))
                self.end_headers()
                self.wfile.write(response_body)
        except urllib.error.HTTPError as e:
            self.send_response(e.code)
            self.end_headers()
            self.wfile.write(e.read())

    def log_message(self, format, *args):
        # Silence default logging to keep the console clean.
        pass

if __name__ == "__main__":
    server = HTTPServer(("127.0.0.1", 8080), ProxyHandler)
    print(f"Proxy listening on 127.0.0.1:8080 -> {TARGET}")
    server.serve_forever()
Enter fullscreen mode Exit fullscreen mode

Save the script as proxy.py, set the environment variable, and run it:

export MONKEYCODE_ENDPOINT="https://your-monkeycode-endpoint.example/v1/chat/completions"
python3 proxy.py
Enter fullscreen mode Exit fullscreen mode

Then configure your AI coding tool to use http://127.0.0.1:8080 as the base URL. Every request now passes through the filter.

Testing the Proxy

Before pointing your editor at the proxy, verify it works with a simple curl command:

curl -s http://127.0.0.1:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "My password is hunter2 and my IP is 10.0.0.5"}]}'
Enter fullscreen mode Exit fullscreen mode

If the proxy is working, the remote server receives a sanitized message: My password is [REDACTED] and my IP is [IP_REDACTED]. The response should still come back normally.

You can also add a logging line inside sanitize_payload to see what was replaced. That helps you tune the regular expressions for your own codebase.

Limitations and Who Should Skip This

A regex-based proxy is not a security boundary. It catches obvious patterns, but it will miss secrets in custom formats, encoded strings, or binary data. It also does not protect against prompt injection or malicious model output. Treat it as a hygiene layer, not a firewall.

Teams working with regulated data or strict confidentiality agreements should not use a remote AI server at all. For them, self-hosting a model is the only defensible option. The proxy is for developers who want to use a free server responsibly without over-engineering their setup.

Another limitation is latency. The proxy adds a local hop, but that overhead is usually under a millisecond. The bigger cost is the regular expression scan on large prompts. If you send 10,000-token prompts, the scan takes a few extra milliseconds. Acceptable for interactive use, but not for high-frequency batch processing.

The Takeaway

Free tokens are only worth something if you can use them without leaking what matters. A local filtering proxy is a small piece of code that gives you control over what leaves your machine. MonkeyCode's free server and 10-million-token grant become more useful when you can send code through a clean pipe. Run the proxy, test it with your own patterns, and keep the sensitive parts where they belong.

MonkeyCode provides free models that can run this workflow.

Top comments (0)