DEV Community

jaryn
jaryn

Posted on

Free Model, Free Server, Not Free Secrets: A 3-Layer Data Quarantine

Friday, 4:47 PM. You wire the free model endpoint into your internal Q&A bot. The first test works. The second test works too. Then you scroll up and see the ticket summary you pasted — customer email, VPN client ID, a support note mentioning the prod database name. All of it just left your network. The invoice said $0. The cost wasn't.

Free tokens are a trade. Not a gift. Treat a third-party model like a local grep, and you are signing an invisible data-processing agreement.

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

MonkeyCode keeps showing up in my evaluation list because it pairs two tempting offers right now: a free model tier advertised with a 10M-token allowance, and a free server option for small teams. I like that combination. I distrust it exactly as much as I like it. The free server option means the orchestrator runs where you control it. The model it calls is still a remote API. That is the boundary you defend.

This walkthrough is a three-layer quarantine gate. Run it before you paste anything into MonkeyCode, or any other model proxy. The artifact is a small Python script plus a regression test you can steal.

Layer 1: Decide what may leave the building

Before you send anything, classify it. Not with a spreadsheet. With a rule.

Send Quarantine first Never send
Synthetic sample queries Email addresses Private keys (OpenSSH, PKCS#8, PGP)
Public API docs questions Full names and usernames Session tokens, OAuth grants, cookies
Redacted error messages Internal hostnames and IPs Production database dumps or backups
Algorithm design questions Cloud account/resource IDs Audit logs with user activity
Code snippets without comments Ticket text with sensitive fields Passwords, passphrases, OTP seeds

If a prompt contains a middle-column value, redact it. If it contains a never-send value, block it. Hard stop. Do not let sample counting override that.

Layer 2: Redact before you transmit

Here is the gate. It reads a JSON payload on stdin, scans the prompt, and exits non-zero when it finds something risky.

#!/usr/bin/env python3
'''quarantine.py - local preflight gate for remote model prompts.'''
import json
import re
import sys

DENY_PATTERNS = {
    'aws_access_key': r'AKIA[0-9A-Z]{16}',
    'github_token': r'gh[pousr]_[A-Za-z0-9]{36,255}',
    'private_key': r'-----BEGIN [A-Z ]*PRIVATE KEY-----',
    'email': r'[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}',
    'vpn_client_id': r'(?i)\bvpn.{0,20}(?:user|login|id)\s*[:=]\s*\S+',
    'connection_string': r'(?i)(?:postgres|mysql)://[^\s]+',
}

def scan(text):
    hits = {}
    for name, pattern in DENY_PATTERNS.items():
        count = len(re.findall(pattern, text))
        if count:
            hits[name] = count
    return hits

def main():
    payload = json.load(sys.stdin)
    text = payload.get('prompt', '')
    hits = scan(text)
    if hits:
        print('BLOCKED:', json.dumps(hits), file=sys.stderr)
        return 1
    print(json.dumps(payload))
    return 0

if __name__ == '__main__':
    sys.exit(main())
Enter fullscreen mode Exit fullscreen mode

Hook it into your request path:

python quarantine.py < prompt.json \
  && curl -s https://your-model-endpoint/v1/chat \
       -H "Authorization: Bearer $MONKEYCODE_TOKEN" \
       --data @prompt.json
Enter fullscreen mode Exit fullscreen mode

Keep the payload out of your shell history. Read the JSON from a file, not from the command line.

Layer 3: Keep your own logs clean

The model is not the only place data can leak. Your gateway logs are the second one. Log status and latency only:

curl -s -o /dev/null -w "%{http_code} %{time_total}\n" \
  --data @prompt.json https://your-model-endpoint/chat
Enter fullscreen mode Exit fullscreen mode

Never log the request body. Never log the full response. Never log the Authorization header. Check your reverse proxy for default access logs that echo JSON bodies — nginx logs paths, not bodies, but your orchestrator might.

Regression fixture: make the boundary testable

An ad hoc script is a prayer. A test is a boundary. Here is a minimal pytest suite.

import quarantine

def test_blocks_aws_key():
    hits = quarantine.scan('Set env to AKIAIOSFODNN7EXAMPLE before running.')
    assert hits['aws_access_key'] == 1

def test_blocks_email():
    hits = quarantine.scan('Contact alice@example.com')
    assert hits['email'] == 1

def test_allows_clean_query():
    assert quarantine.scan('How do I rotate a TLS certificate?') == {}

def test_blocks_connection_string():
    hits = quarantine.scan('USE postgres://admin:secret@db.internal:5432/prod')
    assert hits['connection_string'] == 1
Enter fullscreen mode Exit fullscreen mode

Run it in CI on every push that touches the proxy:

test-quarantine:
  image: python:3.12-slim
  script:
    - python -m pytest test_quarantine.py -q
Enter fullscreen mode Exit fullscreen mode

Pin the interpreter and pytest in your project manifest; the fixture only proves the gate on the version you actually tested.

Positive fixtures prove the gate fires. The negative fixture proves it does not block normal work. That asymmetry is the whole point: you want evidence of refusal, not a green pipeline that never exercises the alarm.

Limitations and who should say no

This gate is a regex fence, not a firewall. It catches accidental pastes, not clever exfiltration. If your data is genuinely sensitive, you need classification with real context, plus a data-processing agreement with the model provider. Neither comes free.

Skip this approach when:

  • your workloads touch PHI, student records, or regulated financial data;
  • your policy forbids third-party API prompts, even redacted;
  • you need audit-grade evidence, because a local script does not archive decisions.

And do not assume the 10M-token offer stays at 10M. Free tiers change. Pin the model endpoint, read the changelog, and re-run the gate each time the project updates.

The boundary question

You will eventually wire a free model into a real server. The question is not whether the model is smart — it is which prompt your CI gate would block before you could paste it, and who gets paged when it does not.

If you want to probe this boundary on a real free tier, MonkeyCode is a reasonable sandbox. Use a throwaway namespace, run the test suite first, and treat the free server as an untrusted remote you happen to pay $0 for.

Top comments (0)