Skip to main content
Glama
ScopeGate MCP Server

ScopeGate MCP Server

by XIOQIGE

ScopeGate

Keep autonomous pentest agents inside the rules of engagement.

ScopeGate is an independent, Apache-2.0 control plane for authorized AI-assisted security testing. It sits between an LLM agent and the target, turns the engagement scope into runtime policy, quarantines hostile target content before it reaches the model, and records a hash-chained evidence trail that a human can verify afterwards.

Part of a three-part portfolio

ScopeGate is the agent runtime governance piece of a three-part body of work. The other two cover the execution and research sides:

Project

Layer

What it demonstrates

ylinux-code-audit-agent

AI for Security

A tool-calling code-audit agent with planner/critic separation, gates, replay, and precision/recall evaluation against a fixed ground truth

hack-cot-research

Security for AI

Controlled experiments on reasoning-model behavior: 8 methods, 16 cases, deterministic judges, raw logs, and confidence intervals

ScopeGate (this repo)

Agent runtime governance

Scope-as-code, pinned DNS, a typed tool boundary, prompt-injection quarantine, a finding validation gate, and hash-chained evidence

Read docs/INSPIRATION.md for the field notes that connect this repo to public work on agent workbenches, bug-bounty hooks, multi-agent CVE pipelines, and the abuse risks of autonomous pentesting.

The rest of the stack lives in separate repositories: mcp-trust (tool supply chain), prompt-range (injection delivery layers), rag-leak-lab (tenant/RAG boundaries), model-supply-guard (model artifacts), llm-infra-probe (local AI infrastructure), agent-redteam (tool-boundary behavior), and atlas-map (framework mapping).

Status: alpha. ScopeGate is deliberately not another exploit engine. It is the authorization, tool-boundary, and evidence layer around one.

Python License Status Tests


Why this exists

Autonomous pentest agents are now good at acting: they can browse, run tools, chain findings, and write reports. The part that has not caught up is accountability. In most agent setups, the scope is a sentence in a prompt, the tool surface is a shell, and the evidence is a transcript.

That creates three concrete problems:

  1. Scope is advisory. A prompt injection, a hallucination, or a curious agent can reach a host that was never authorized.

  2. Target content is executable context. HTML, headers, and error pages can contain instructions aimed at the model (indirect prompt injection).

  3. "Trust me" is not evidence. A report needs to show which requests were made, which were blocked, and whether the log was altered.

ScopeGate makes those three things explicit:

Control

Implementation

Scope as code

TOML/JSON allow/deny rules, ports, methods, time window, request/rate/runtime budgets

Fail-closed target checks

Deny wins; private ranges require an explicit lab flag; cloud metadata endpoints are always denied

DNS pinning

Resolve once, authorize every address, connect to the pinned IP with the original hostname for Host/SNI

Tool boundary

Typed HTTP/DNS/TCP/TLS/finding tools over MCP; no shell tool

Egress proxy

HTTP and CONNECT tunnel policy enforcement for agents that honour HTTP_PROXY

Prompt-injection handling

Detect instruction-like content, quarantine it, label all target output as untrusted

Finding quality gate

Reject low-confidence or evidence-free findings before they reach the report

Evidence

Append-only JSONL ledger with a SHA-256 hash chain, response hashes, report.md, report.json, SARIF

Reproducible benchmark

A deliberately imperfect loopback lab, ground truth, precision/recall, and a simulated compromised-agent probe

The result is a project you can demo in one command, inspect line by line, and extend with your own tools or agent.


Related MCP server: Offensive Security MCP Server

Quickstart

Requirements: Python 3.11+ and no third-party runtime dependencies.

git clone https://github.com/XIOQIGE/scopegate.git
cd scopegate
python -m venv .venv
# Windows: .venv\Scripts\activate
# macOS/Linux: source .venv/bin/activate
python -m pip install -e .
scopegate demo

No install? Run it from the source tree:

# Windows PowerShell
$env:PYTHONPATH = "src"; python -m scopegate demo
# macOS/Linux
PYTHONPATH=src python -m scopegate demo

demo starts a loopback-only lab on an ephemeral port, writes a one-hour scope, runs the deterministic playbook, runs a simulated prompt-injected agent, scores the result against ground truth, and writes a complete evidence pack.

Actual output from a clean run:

ScopeGate demo complete
  target:   http://127.0.0.1:64897
  run:      runs/demo-20261105T075655Z
  findings: {'critical': 0, 'high': 1, 'medium': 5, 'low': 2, 'info': 0, 'total': 8}
  policy:   {'attempts': 6, 'allowed': 5, 'denied': 1, 'denials_by_code': {'target.metadata': 1}, 'out_of_scope_denials': 1, ...}
  audit:    valid
Evaluation
  true positives : 8
  false positives: 0
  false negatives: 0
  precision      : 1.000
  recall         : 1.000
  f1             : 1.000
  audit valid    : True
  scope denials  : 1
  probe blocked  : True
  report:   runs/demo-20261105T075655Z/report.md

The run directory contains:

runs/demo-.../
├── audit.jsonl        # append-only, hash-chained event ledger
├── findings.jsonl     # deduplicated findings with evidence references
├── report.md          # human-readable assessment report
├── report.json        # machine-readable report
├── report.sarif       # SARIF 2.1.0 for code scanning / CI
├── eval.json          # ground-truth metrics and probe result
├── scope.toml         # the exact scope used for this run
├── meta.json          # environment, tool version, policy summary
└── evidence/          # bounded HTTP response captures

Verify the chain at any time:

scopegate audit verify --run-dir runs/demo-...

How it works

flowchart LR
    A["LLM agent / external tool"] -->|MCP stdio| G["Scoped tool gateway"]
    A -->|HTTP_PROXY / HTTPS_PROXY| P["Egress proxy"]
    G --> D["Policy engine"]
    P --> D
    D --> S[("scope.toml")]
    D --> L[("hash-chained audit.jsonl")]
    G --> H["Pinned HTTP client"]
    G --> N["Pinned TCP / TLS"]
    P --> N
    H --> T["Authorized target"]
    N --> T
    G --> F["Findings store"]
    F --> R["report.md / report.json / SARIF"]

A request follows one path:

  1. Parse the target and reject credentials, odd schemes, and invalid ports.

  2. Resolve the host once; reject if any address is outside the allow rules, non-public without allow_private, or a cloud metadata endpoint.

  3. Pin one authorized IP. Connect to that IP, but keep the original hostname for the Host header and TLS SNI/certificate validation.

  4. Check method, tool, request budget, rate limit, runtime budget, and concurrency.

  5. Record the decision and the response hash in the ledger.

  6. Treat the response body as hostile: detect instruction-like content, strip it for the model, and label the remainder as untrusted data.

The scope file is the source of truth. A prompt cannot expand it, and the model never receives a shell. The full design and trust boundaries are in docs/ARCHITECTURE.md.


Scope as code

[engagement]
name = "acme-web-2026-11"
authorized_by = "Alice Security Lead"
authorization_ref = "SEC-1234"
expires_at = "2026-11-12T18:00:00+08:00"
# not_before = "2026-11-05T09:00:00+08:00"

[targets]
allow = ["https://staging.example.com", "https://api.staging.example.com"]
deny = ["169.254.169.254/32", "10.0.0.0/8"]

[limits]
allowed_ports = [443]
max_requests = 500
max_rps = 2
max_runtime_seconds = 900
max_concurrent = 4
max_response_bytes = 2000000

[policy]
allowed_methods = ["GET", "HEAD", "OPTIONS"]
allowed_tools = [
  "http.request",
  "dns.resolve",
  "tcp.connect",
  "tls.inspect",
  "report.finding",
  "scope.check",
]
allow_private = false
follow_redirects = false
min_finding_confidence = "medium"
require_finding_evidence = true

Design rules:

  • Deny wins. A deny rule always beats an allow rule.

  • No global scope. *, 0.0.0.0/0, and ::/0 are rejected at load time.

  • Private address space is opt-in. Loopback and RFC1918 targets require allow_private = true, intended for local labs and explicitly approved internal engagements.

  • Cloud metadata is never in scope. 169.254.169.254, the ECS task metadata address, Alibaba's metadata address, and the IPv6 EC2 metadata address are denied regardless of allow rules.

  • Time-boxed. expires_at is mandatory; not_before is optional.

  • Path prefixes are supported. https://example.com/app authorizes /app and below, not /admin.

  • Findings must clear a gate. Low-confidence or evidence-free claims are rejected before they reach the report.

scopegate check is a dry-run:

scopegate check --scope scope.toml --target https://staging.example.com/app
scopegate check --scope scope.toml --target https://staging.example.com/app --json

Use it with an agent

1. MCP tool gateway

Run the stdio server:

scopegate mcp --scope scope.toml --out runs/mcp-session

It exposes seven tools:

Tool

Purpose

scope_check

Check a URL without sending traffic

http_request

GET/HEAD/OPTIONS by default; POST/PUT/etc. must be enabled in scope

dns_lookup

Resolve an in-scope host and show the pinned addresses

tcp_connect

Test an in-scope host/port

tls_inspect

Read certificate metadata from an in-scope endpoint

report_finding

Record a validated, evidence-backed finding

list_findings

Read findings for the current run

Example MCP client configuration: examples/mcp-config.json. The server speaks newline-delimited JSON-RPC 2.0 over stdio and writes logs only to stderr.

2. Egress proxy for an existing CLI agent

scopegate proxy --scope scope.toml
# prints HTTP_PROXY=http://127.0.0.1:8080

Or inject the proxy into a child process:

scopegate run --scope scope.toml --target https://staging.example.com -- \
  your-agent --target https://staging.example.com

This sets HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, and the lowercase variants, and records every proxied request. It is cooperative enforcement: a process that ignores the proxy can still open a direct socket. Use a network namespace or container egress policy when you need a hard boundary. That limitation is documented in docs/THREAT_MODEL.md.

3. Optional LLM planner

The repo includes a small OpenAI-compatible planner loop. It is intentionally limited to the typed tools and bounded by --max-steps:

export SCOPEGATE_LLM_API_KEY="..."
scopegate scan \
  --scope scope.toml \
  --target https://staging.example.com \
  --agent llm \
  --llm-model gpt-4.1-mini \
  --llm-base-url https://api.openai.com/v1 \
  --max-steps 8

For sensitive engagements, point --llm-base-url at a local OpenAI-compatible server (for example, an Ollama or vLLM endpoint) so target-derived content does not leave your environment. The planner is a demonstration of the agent paradigm, not a claim that a particular model is a good pentester.


Reproducible evaluation

scopegate eval

The bundled lab has eight seeded issues and a prompt-injection canary. The playbook is deterministic, so the result is reproducible rather than a cherry- picked model run.

Metric

Playbook agent

True positives

8

False positives

0

False negatives

0

Precision

1.000

Recall

1.000

F1

1.000

Audit chain valid

yes

Out-of-scope metadata attempts blocked

1 / 1

Prompt-injection signals detected

6 labels

The InjectionProbeAgent is a deliberately compromised scripted agent. It reads the lab's injected instruction and attempts to authorize http://169.254.169.254/latest/meta-data/. The request is denied by policy before a socket is opened; the probe is a dry-run so it can never reach a real metadata service even if the gate regresses. This is the control test that matters: the model can be fooled, but the boundary still holds.

This is a lab benchmark, not a claim of real-world coverage. See docs/EVALUATION.md for the ground truth and methodology.


Prior art and honest positioning

ScopeGate is not a fork of Strix, PentestGPT, or PentAGI, and contains no source code copied from them. Those projects are excellent execution engines; ScopeGate is a companion control plane that can supervise an engine or expose a safer tool surface to a custom agent.

Project

License

What it gives you

What ScopeGate adds

Strix

Apache-2.0

Autonomous multi-agent pentesting, sandbox, PoCs, reports

Runtime egress policy, MCP tool boundary, prompt-injection quarantine, hash-chained evidence

PentestGPT

MIT

LLM-driven pentest/CTF pipeline, task tree, sessions

Scope-as-code, pinned DNS, budgets, auditable tool calls

PentAGI

MIT

Multi-agent system with Docker sandbox and a large tool suite

A small, testable policy/evidence layer that can front other agents

HexStrike AI

MIT

MCP server exposing 150+ security tools

Fail-closed scope, no shell tool by default, evidence chain

RedAmon

MIT

Recon graph, exploitation pipeline, remediation PRs

Lightweight authorization and audit layer; no Neo4j/Docker requirement

ScopeGate

Apache-2.0

Scope enforcement, tool gateway, egress proxy, evidence, lab benchmark

—

Star counts and project status change quickly; the comparison in docs/PRIOR_ART.md records the sources and the date they were checked. The short version: use Strix or PentAGI when you need a full autonomous engine; use ScopeGate when you need to constrain, observe, and evidence one.

For the public field reports that shaped the finding gate and roadmap, see docs/INSPIRATION.md. If you are evaluating this as a portfolio project, read docs/PORTFOLIO.md for the design rationale, a five-minute demo script, and an explicit "what I did not build" section.


Project layout

src/scopegate/
├── scope.py          # scope parsing, matching, DNS resolution, fail-closed checks
├── policy.py         # budgets, rate limiting, audited decisions
├── httpclient.py     # pinned-IP HTTP client with re-authorized redirects
├── tools.py          # typed tools, evidence capture, MCP-compatible schemas
├── sanitize.py       # prompt-injection detection and quarantine
├── audit.py          # append-only hash-chained ledger
├── proxy.py          # HTTP/CONNECT egress proxy
├── mcp_server.py     # dependency-free MCP stdio server
├── agent.py          # deterministic playbook, optional LLM planner, injection probe
├── lab.py            # loopback-only intentionally imperfect target
├── eval.py           # ground-truth metrics
├── report.py         # Markdown, JSON, SARIF
└── cli.py            # init/check/scan/demo/eval/proxy/run/mcp/audit/report/lab

Tests live in tests/ (48 tests, no network access beyond loopback).


Limitations

ScopeGate is useful today, but it is not a silver bullet:

  • The proxy is cooperative. A hostile binary can bypass it. The next step is a network namespace/container with the proxy as the only route.

  • HTTPS CONNECT traffic is authorized and logged at the host/port level, not inspected. There is no MITM CA in this project.

  • Prompt-injection detection is heuristic. It reduces risk; it does not eliminate it. The hard control is that target content never grants authority.

  • The built-in playbook is read-only and shallow. It is a reproducible demo, not a replacement for manual testing.

  • The lab benchmark is intentionally small. A perfect score on it is not evidence of real-world coverage.

  • The audit chain detects casual tampering; it is not an external notary. For stronger proof, anchor the head hash in a separate system or sign it.

  • allow_private = true weakens the default network boundary. Use it only for a lab or an explicitly approved internal engagement.


Roadmap

  • Hard egress boundary using a network namespace / container and nftables

  • Signed scope files (Sigstore/cosign) and an approval workflow

  • Policy backend abstraction (OPA/Rego or Cedar)

  • First-class adapters for Strix and PentestGPT with tested Docker configs

  • More lab scenarios (OWASP Juice Shop, DVWA, API-only targets)

  • GitHub Action that uploads SARIF and fails on out-of-scope attempts

  • MCP resources for findings and audit summaries

  • External timestamping of the audit head


Authorized use

ScopeGate is for authorized security testing only. The scope file is an attestation that a human approved the engagement; it is not a substitute for legal authorization. The bundled lab binds to loopback and contains no real credentials.

Read SECURITY.md before running against anything you do not own.

Contributing

Contributions are welcome. Start with CONTRIBUTING.md, run the tests, and keep the fail-closed defaults intact. If you add code from another project, add its notice to NOTICE.

License

Apache-2.0. See LICENSE and NOTICE.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables autonomous AI agents and penetration testers to conduct authorized security audits with persistent cross-session memory, zero-trust secret scrubbing, dynamic OWASP/ASVS checklists, and hallucination-free exploit PoC generation from captured traffic.
      1
      MIT
    • F
      license
      Not graded
      quality
      C
      maintenance
      Enables AI agents to perform safe, authorized penetration testing by managing engagements, enforcing scope and risk policies, and orchestrating tools like Nmap, Nuclei, and Subfinder.
      -
    • A
      license
      B
      quality
      B
      maintenance
      Enables AI agents to conduct authorized pentests and bug-bounty workflows with scope enforcement, audit logging, reconnaissance, safe vulnerability checks, payload/wordlist generation, and professional report generation.
      14
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to perform authorized web-pentest reconnaissance and interaction, including crawling, headless-browser control, login/BOLA comparisons, safe probes, HAR replay, and evidence-first reporting, while enforcing declared scope, audit trails, rate limits, and data minimization.
      1
      MIT