snare

command module
v2.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2026 License: MIT Imports: 3 Imported by: 0

README

Snare

CI Go Reference License Release

Local HTTP/HTTPS proxy — capture, inspect, replay, and mock traffic.


Snare runs as a local proxy and records every HTTP and HTTPS request that passes through it. Each capture is a plain JSON file you can list, filter, search, diff, mock, intercept, and replay with a single command. Forward and reverse proxy in one binary.


Installation

go install github.com/muxover/snare/v2@latest

Build from source:

git clone https://github.com/muxover/snare.git
cd snare
go build -o snare .

Quick Start

snare serve

export HTTP_PROXY=http://127.0.0.1:8888
export HTTPS_PROXY=http://127.0.0.1:8888

curl https://httpbin.org/get

snare list
snare show <id>
snare replay <id>

HTTPS MITM

snare ca generate   # writes ~/.snare/ca.pem
snare ca install    # installs CA into system trust store
snare serve

snare ca install runs the right command per platform: certutil -addstore Root on Windows, security add-trusted-cert on macOS, update-ca-certificates on Linux.


Reverse Proxy

snare serve --mode reverse --target http://localhost:3000

No proxy env vars needed. All traffic to 127.0.0.1:8888 is forwarded to the target and captured.


Commands

Captures

Command Description
snare list List captures with filters and colorized output
snare watch Tail new captures as they arrive
snare show <id> Full request/response detail; WebSocket frames, SSE frames, GraphQL fields, and decoded gRPC when present
snare diff <a> <b> Diff two captures
snare grep <pattern> Regex search across all capture bodies
snare clear Delete captures (all, or filtered by method/status/url/host)
snare delete <id> Delete a single capture

Replay

Command Description
snare replay <id> Re-send a captured request through the snare proxy (captured by default)
snare replay --match <str> Re-send all captures whose URL contains this string
snare replay --edit Open capture in $EDITOR before sending

Mock

Command Description
snare mock add Add a stub rule
snare mock from <id> Generate a stub from a capture
snare mock list List all stubs
snare mock remove <id> Remove a stub
snare mock clear Remove all stubs

Intercept

Command Description
snare intercept list List requests paused by the proxy
snare intercept forward <id> Release a paused request
snare intercept edit <id> Edit then forward a paused request
snare intercept drop <id> Drop a paused request (client receives 502)

Import / Export

Command Description
snare import <file.har> Import a HAR file
snare save <id> Save a capture to a file
snare export Export captures to JSON, HAR, Postman collection, or OpenAPI spec
snare curl <id> Print a capture as a curl command

OpenAPI

Command Description
snare openapi Generate an OpenAPI 3.0 spec from captured traffic

Sessions

Command Description
snare session start <name> Mark the start of a named capture session
snare session end <name> Mark the end of a named capture session
snare session list List all recorded sessions
snare session delete <name> Delete a named session
snare session diff <a> <b> Compare two sessions' capture sequences

Record / Playback

Command Description
snare record Record traffic to a cassette file for offline playback
snare playback <cassette> Replay a cassette file as an HTTP server

Testing & CI

Command Description
snare test <suite.yaml> Run a YAML test suite; exits 1 on any failure
snare assert Assert conditions on captures; exits 1 on failure
snare fuzz <id> Send mutated variants of a captured request

Bundles

Command Description
snare bundle pack Pack captures, mocks, and sessions into a .snare bundle
snare bundle unpack <file.snare> Import captures, mocks, and sessions from a bundle

Security

Command Description
snare audit Scan captures for security misconfigurations

Storage

Command Description
snare stats Traffic statistics: method/status/protocol breakdown, latency p50/p95/p99, top hosts
snare migrate --to sqlite Migrate flat-file captures to a SQLite database at ~/.snare/snare.db

Automation

Command Description
snare pipe Stream captures as NDJSON; --follow to tail
snare tui Interactive terminal UI — 4 tabs: Captures, Mocks, Intercept, Sessions

CA

Command Description
snare ca generate Generate CA certificate
snare ca install Install CA into system trust store
snare ca install --device android Push CA to Android device via ADB
snare ca install --device ios Serve CA for Safari download on iOS

serve Flags

-p, --port              Port (default: 8888)
-b, --bind              Bind address (default: 127.0.0.1)
    --mode              forward (default) or reverse
    --target            Reverse proxy target URL
    --no-mitm           Tunnel CONNECT without MITM
    --max-captures      In-memory cap, oldest pruned (default: 1000)
    --no-store          Memory only, nothing written to disk
    --max-body-size     Truncate bodies at N bytes (0 = no limit)
    --store-dir         Override capture directory
    --upstream-proxy    Chain through another proxy
    --rewrite-host      Rewrite outbound host: from=to (repeatable)
    --add-header        Add or override outbound header: Key: Value (repeatable)
    --remove-header     Remove outbound header by name (repeatable)
    --ignore            Skip URLs containing this substring (repeatable)
    --map-remote        Redirect host: host=http://target (repeatable)
    --rewrite-body      Rewrite response bodies: regex=replacement (repeatable)
    --mock-file         Load mock rules from a file
    --intercept         Pause requests matching this URL pattern (* for all)
    --intercept-timeout Auto-drop paused requests after this duration (default: 5m)
    --on-capture        Shell command run per capture; full JSON piped to stdin
    --delay             Inject artificial latency before each response (e.g. 200ms)
    --chaos             Drop this percentage of requests randomly (e.g. 10)
    --browser           Auto-launch Chrome/Edge with proxy configured
    --shadow            Mirror traffic to a second URL silently (repeatable)
    --plugin            Run plugin command per capture; JSON on stdin (repeatable)
    --web               Start web dashboard
    --web-port          Port for web dashboard (default: 8080)
    --no-config         Ignore ~/.snare/config.yaml
    --proto             Protobuf definition file for gRPC decoding (repeatable)
    --no-h3             Disable HTTP/3 QUIC server in reverse proxy mode
    --hook              JS hook file; onRequest/onResponse/onCapture called per request; reloaded from disk on every request (repeatable)
    --db                Persist captures to SQLite database at ~/.snare/snare.db
    --auth              Require basic auth on proxy and dashboard: user:pass
    --allow             Allow only this source CIDR (repeatable; default: all)
    --tls-dashboard     Serve web dashboard over HTTPS (auto self-signed cert)
    --tls-cert          TLS certificate file for --tls-dashboard
    --tls-key           TLS key file for --tls-dashboard
    --socks5-port       Also listen as a SOCKS5 proxy on this port
-v, --verbose           Debug logging

list Flags

-n, --last          Show last N captures (default: 20)
    --method        Filter by HTTP method
    --status        Filter by status code
    --url           Filter by URL substring
    --host          Filter by host
    --since         Filter by timestamp (RFC3339 or 2006-01-02)
    --until         Filter by timestamp (RFC3339 or 2006-01-02)
    --body          Filter by substring in request or response body
    --operation     Filter by GraphQL operation name
    --slow          Show only captures slower than N milliseconds
    --tls-version   Filter by TLS version (e.g. 1.2, 1.3)
    --page          Page number (1-based); enables pagination mode
    --page-size     Results per page when using --page (default: 50)

JS Hooks

snare serve --hook hook.js loads a JavaScript file and calls its exported functions for every request that passes through the proxy. The file is reloaded from disk on every request — edit it and the next request picks up your changes without restarting.

Available functions:

// Called before the request is forwarded. Mutate r to change what goes out.
// Return an object to short-circuit — the origin is never contacted.
function onRequest(r) {
  r.method            // string — change the HTTP method
  r.url               // string — change the target URL
  r.headers["X-Foo"] = "bar"   // add/override a header
  delete r.headers["X-Remove"] // remove a header
  r.body              // string — change the request body

  // Short-circuit: answer without hitting the origin
  return { status: 200, headers: { "Content-Type": "application/json" }, body: '{"mocked":true}' }
}

// Called after the response is received. Mutate res to change what the client sees.
function onResponse(r, res) {
  res.status           // number — change the status code
  res.headers["X-Injected"] = "yes"
  res.body = res.body.replace("staging", "production")
}

// Called after the capture is saved. Read-only view of the full capture JSON.
function onCapture(c) {
  if (c.response && c.response.status_code >= 500) {
    console.log("5xx:", c.request.method, c.request.url)
  }
}

console.log() writes to snare's verbose log (-v). Hook errors are logged and skipped — a broken hook never crashes the proxy. Pass --hook multiple times to load multiple files; all run in order.


Config file

Snare reads ~/.snare/config.yaml on startup. All snare serve flags are supported:

port: "8888"
bind: "127.0.0.1"
web: true
web_port: "8080"
ignore:
  - /healthz
  - /metrics
shadow:
  - http://staging.internal
plugins:
  - "jq . >> ~/snare-log.ndjson"

list / watch Flags

--method      HTTP method
--status      Response status code
--url         URL substring
--host        Host
--body        Substring in request or response body
--operation   GraphQL operation name
--since       Start timestamp (RFC3339)
--until       End timestamp (RFC3339)
--slow         Show only captures slower than N milliseconds
--tls-version  Filter by TLS version (e.g. 1.2, 1.3)
-n, --last     Max results (list only)
--interval     Poll interval (watch only, default: 500ms)

replay Flags

-n, --repeat  Send N times
-u, --url     Override URL
-H, --header  Add or override header (repeatable)
    --match   Replay all captures matching this URL substring
    --edit    Open capture in $EDITOR before sending
    --proxy   Proxy URL to route replay through (default: http://127.0.0.1:8888; set to empty to bypass)

clear Flags

--method  Delete only captures with this method
--status  Delete only captures with this status code
--url     Delete only captures whose URL contains this substring
--host    Delete only captures for this host

test Flags

    --proxy   Route requests through this proxy URL (captures test traffic in snare)
    --format  Output format: text (default), junit, tap
    --parallel Run tests concurrently

fuzz Flags

    --count           Maximum number of variants to send (default: 20)
    --proxy           Route fuzz requests through a proxy URL
    --mutate-body     Mutate JSON request body fields (default: true)
    --mutate-headers  Mutate request headers (default: true)
    --mutate-path     Mutate URL path segments (default: true)
    --mutate-method   Cycle through HTTP methods (default: true)

grep Flags

<pattern>    Regular expression matched against request and response bodies
-v, --invert Print captures that do NOT match
--method     Limit to this HTTP method
--host       Limit to this host

assert Flags

    --method  Filter by HTTP method
    --status  Filter by response status code
    --url     Filter by URL substring
    --body    Filter by substring in request or response body
    --slow    Filter to captures slower than N milliseconds
    --min     Minimum matching captures (default: 1)
    --max     Maximum matching captures (-1 = no limit)
    --format  Output format: text (default) or junit

bundle Flags

pack:
  -o, --out string       Output file (default "bundle.snare")
      --session string   Pack only captures from this named session
      --ids string       Comma-separated capture IDs (or prefixes) to pack

diff Flags

    --golden <name>        Record current session as a named golden baseline
    --check  <name>        Compare current session against a golden; exits 1 on regression
    --session <name>       Session to use for --golden/--check (default: most recent)
    --strict               Also compare response bodies when using --check
    --ignore-fields <k,k>  Comma-separated response body JSON keys to ignore in --strict

export Flags

-f, --format  Output format: json (default), har, postman
-n, --last    Number of captures to export (default: 50)

openapi Flags

-o, --out     Output file (default: openapi.json)
    --title   API title (default: "snare captured API")
    --server  Override server URL (default: inferred from captures)

record Flags

-o, --out     Cassette output file (default: cassette.json)
-p, --port    Port to listen on (default: 8888)
-b, --bind    Bind address (default: 127.0.0.1)
    --mode    forward (default) or reverse
    --target  Reverse proxy target URL (required for --mode reverse)
    --no-mitm Disable HTTPS MITM
-v, --verbose Debug logging

playback Flags

-p, --port  Port to listen on (default: 8888)
-b, --bind  Bind address (default: 127.0.0.1)

Environment

Variable Default Description
SNARE_STORE ~/.snare/captures Capture directory
SNARE_CA ~/.snare CA certificate directory
SNARE_MOCKS ~/.snare/mocks.json Mock rules file
SNARE_INTERCEPT ~/.snare/intercept Intercept queue directory

Examples

# Filter captures
snare list --method POST --status 500

# Search bodies
snare grep '"error"'
snare grep --invert '"success"'

# Watch live traffic for one host
snare watch --host api.example.com

# Mock an endpoint
snare mock add --url /api/payment --status 200 --body '{"ok":true}'

# Intercept and edit a request before it goes out
snare serve --intercept '*'
snare intercept list
snare intercept edit <id>
snare intercept forward <id>

# Stream to jq
snare pipe --follow | jq '.request.url'

# CI smoke test
snare assert --url /api/health --status 200 --min 1

# Ignore health checks
snare serve --ignore /healthz --ignore /metrics

# Redirect a host to a local server
snare serve --map-remote api.example.com=http://localhost:4000

# Reverse proxy with body rewrite
snare serve --mode reverse --target http://localhost:3000 \
  --rewrite-body 'staging.internal=production.example.com'

# Simulate latency and random failures
snare serve --delay 200ms --chaos 15

# Launch browser with proxy pre-configured
snare serve --browser

# Print a capture as curl
snare curl <id>

# Export as Postman collection
snare export --format postman

# Generate OpenAPI spec from captured traffic
snare openapi --out api.json

# Record then replay offline
snare record --out cassette.json
snare playback cassette.json

# Install CA on mobile
snare ca install --device android
snare ca install --device ios

# Shadow traffic to a staging server
snare serve --shadow http://staging.internal

# Plugin: log all captures as NDJSON
snare serve --plugin "jq -c . >> ~/captures.ndjson"

# Web dashboard
snare serve --web

# Decode gRPC traffic with a .proto file
snare serve --proto path/to/service.proto

# Filter captures by GraphQL operation name
snare list --operation GetUser
snare watch --operation CreateOrder

# Reverse proxy with HTTP/3 disabled
snare serve --mode reverse --target http://localhost:3000 --no-h3

# JS hook: inject a header and log all 5xx
snare serve --hook hook.js

# Run a YAML test suite (capture all traffic in snare)
snare test suite.yaml --proxy http://127.0.0.1:8888

# JUnit output for CI
snare test suite.yaml --format junit > results.xml
snare assert --url /api/health --status 200 --format junit > assert.xml

# Record a golden baseline, then check regressions
snare session start baseline
# ... run tests ...
snare session end baseline
snare diff --golden baseline
# ... deploy, run tests again ...
snare diff --check baseline --strict --ignore-fields timestamp,request_id

# Fuzz a captured request
snare fuzz <id>
snare fuzz <id> --proxy http://127.0.0.1:8888 --count 50

# Find slow requests
snare list --slow 500
snare watch --slow 1000
snare assert --slow 200 --max 0   # fail CI if any request exceeded 200ms

# Share a debugging context with a teammate
snare bundle pack --session my-session --out debug.snare
snare bundle unpack debug.snare

# Scope: capture only traffic matching a pattern
snare serve --scope api.example.com --scope auth.example.com

# Show TLS details for a captured HTTPS request
snare show <id>
snare show <id> --hex

# Scan captures for security issues
snare audit
snare audit --format json | jq '.[] | select(.issue | test("cookie"))'
snare audit --session my-session --fail

# Lock down snare when exposed on a shared network
snare serve --bind 0.0.0.0 --auth admin:secret --allow 192.168.1.0/24
snare serve --bind 0.0.0.0 --web --tls-dashboard --auth admin:secret

# SOCKS5 for tools that don't speak HTTP proxy
snare serve --socks5-port 1080

# Persistent SQLite storage
snare serve --db
snare stats
snare stats --format json
snare list --page 2 --page-size 25

# Migrate flat-file captures to SQLite (one-time)
snare migrate --to sqlite

# Export as bundle
snare export --format bundle

# Diff two test runs
snare session start baseline
# ... run tests ...
snare session end baseline
snare session start after-deploy
# ... run tests ...
snare session end after-deploy
snare session diff baseline after-deploy

Contributing

See CONTRIBUTING.md.


License

Licensed under the MIT license.



Made with ❤️ by Jax (@muxover)

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL