contextwall 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- contextwall-0.1.0/.dockerignore +37 -0
- contextwall-0.1.0/.env.example +12 -0
- contextwall-0.1.0/.github/workflows/docker.yml +44 -0
- contextwall-0.1.0/.gitignore +29 -0
- contextwall-0.1.0/Dockerfile +36 -0
- contextwall-0.1.0/LICENSE +33 -0
- contextwall-0.1.0/PKG-INFO +431 -0
- contextwall-0.1.0/README.md +393 -0
- contextwall-0.1.0/ctxfw.oss.yaml +68 -0
- contextwall-0.1.0/ctxfw.yaml.example +93 -0
- contextwall-0.1.0/demo/.env.example +19 -0
- contextwall-0.1.0/demo/ATTACKS.md +75 -0
- contextwall-0.1.0/demo/Dockerfile.agent +12 -0
- contextwall-0.1.0/demo/Dockerfile.cre +20 -0
- contextwall-0.1.0/demo/Dockerfile.simulator +8 -0
- contextwall-0.1.0/demo/Makefile +26 -0
- contextwall-0.1.0/demo/README.md +94 -0
- contextwall-0.1.0/demo/TESTING.md +275 -0
- contextwall-0.1.0/demo/agent/brave_search.py +29 -0
- contextwall-0.1.0/demo/agent/cre_client.py +70 -0
- contextwall-0.1.0/demo/agent/main.py +204 -0
- contextwall-0.1.0/demo/agent/requirements.txt +5 -0
- contextwall-0.1.0/demo/agent/scenarios.py +84 -0
- contextwall-0.1.0/demo/ctxfw.demo.yaml +34 -0
- contextwall-0.1.0/demo/dashboard/index.html +277 -0
- contextwall-0.1.0/demo/docker-compose.yml +47 -0
- contextwall-0.1.0/demo/simulator/main.py +340 -0
- contextwall-0.1.0/demo/simulator/requirements.txt +1 -0
- contextwall-0.1.0/docker-compose.yml +75 -0
- contextwall-0.1.0/policy/packs/fedramp.yaml +63 -0
- contextwall-0.1.0/policy/packs/hipaa.yaml +55 -0
- contextwall-0.1.0/policy/packs/soc2.yaml +58 -0
- contextwall-0.1.0/publish-pypi.sh +134 -0
- contextwall-0.1.0/pyproject.toml +81 -0
- contextwall-0.1.0/sdk/python/pyproject.toml +39 -0
- contextwall-0.1.0/sdk/python/src/contextwall_sdk/__init__.py +59 -0
- contextwall-0.1.0/sdk/python/src/contextwall_sdk/_anthropic.py +269 -0
- contextwall-0.1.0/sdk/python/src/contextwall_sdk/_openai.py +268 -0
- contextwall-0.1.0/sdk/python/src/contextwall_sdk/client.py +475 -0
- contextwall-0.1.0/sdk/python/src/contextwall_sdk/exceptions.py +53 -0
- contextwall-0.1.0/sdk/python/tests/test_sdk.py +279 -0
- contextwall-0.1.0/src/context_firewall/__init__.py +3 -0
- contextwall-0.1.0/src/context_firewall/analytics/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/analytics/engine.py +234 -0
- contextwall-0.1.0/src/context_firewall/api/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/api/app.py +1020 -0
- contextwall-0.1.0/src/context_firewall/api/models.py +54 -0
- contextwall-0.1.0/src/context_firewall/classifier/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/classifier/classifier.py +165 -0
- contextwall-0.1.0/src/context_firewall/cli/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/cli/main.py +513 -0
- contextwall-0.1.0/src/context_firewall/compliance/__init__.py +1 -0
- contextwall-0.1.0/src/context_firewall/compliance/baa.py +57 -0
- contextwall-0.1.0/src/context_firewall/compliance/chain.py +84 -0
- contextwall-0.1.0/src/context_firewall/compliance/control_mappings.py +92 -0
- contextwall-0.1.0/src/context_firewall/compliance/export.py +280 -0
- contextwall-0.1.0/src/context_firewall/compliance/keys.py +94 -0
- contextwall-0.1.0/src/context_firewall/config.py +234 -0
- contextwall-0.1.0/src/context_firewall/control_plane/__init__.py +0 -0
- contextwall-0.1.0/src/context_firewall/control_plane/client.py +107 -0
- contextwall-0.1.0/src/context_firewall/control_plane/models.py +72 -0
- contextwall-0.1.0/src/context_firewall/control_plane/pusher.py +377 -0
- contextwall-0.1.0/src/context_firewall/daemon/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/daemon/main.py +461 -0
- contextwall-0.1.0/src/context_firewall/db/__init__.py +6 -0
- contextwall-0.1.0/src/context_firewall/db/connection.py +30 -0
- contextwall-0.1.0/src/context_firewall/db/migrations.py +408 -0
- contextwall-0.1.0/src/context_firewall/entropy/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/entropy/engine.py +271 -0
- contextwall-0.1.0/src/context_firewall/graph/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/graph/engine.py +162 -0
- contextwall-0.1.0/src/context_firewall/lint/__init__.py +0 -0
- contextwall-0.1.0/src/context_firewall/lint/engine.py +334 -0
- contextwall-0.1.0/src/context_firewall/mcp/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/mcp/server.py +237 -0
- contextwall-0.1.0/src/context_firewall/metrics.py +100 -0
- contextwall-0.1.0/src/context_firewall/models.py +130 -0
- contextwall-0.1.0/src/context_firewall/policy/__init__.py +10 -0
- contextwall-0.1.0/src/context_firewall/policy/detectors/__init__.py +0 -0
- contextwall-0.1.0/src/context_firewall/policy/detectors/injection.py +480 -0
- contextwall-0.1.0/src/context_firewall/policy/dsl/__init__.py +0 -0
- contextwall-0.1.0/src/context_firewall/policy/dsl/evaluator.py +208 -0
- contextwall-0.1.0/src/context_firewall/policy/dsl/loader.py +150 -0
- contextwall-0.1.0/src/context_firewall/policy/dsl/types.py +112 -0
- contextwall-0.1.0/src/context_firewall/policy/engine.py +532 -0
- contextwall-0.1.0/src/context_firewall/provenance/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/provenance/engine.py +658 -0
- contextwall-0.1.0/src/context_firewall/provenance/models.py +91 -0
- contextwall-0.1.0/src/context_firewall/proxy/__init__.py +1 -0
- contextwall-0.1.0/src/context_firewall/proxy/router.py +519 -0
- contextwall-0.1.0/src/context_firewall/proxy/scanner.py +214 -0
- contextwall-0.1.0/src/context_firewall/proxy/tokens.py +156 -0
- contextwall-0.1.0/src/context_firewall/runtime/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/runtime/engine.py +303 -0
- contextwall-0.1.0/src/context_firewall/source/__init__.py +1 -0
- contextwall-0.1.0/src/context_firewall/source/registry.py +299 -0
- contextwall-0.1.0/src/context_firewall/source/types.py +12 -0
- contextwall-0.1.0/src/context_firewall/synthesizer/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/synthesizer/synthesizer.py +255 -0
- contextwall-0.1.0/src/context_firewall/trust/__init__.py +5 -0
- contextwall-0.1.0/src/context_firewall/trust/engine.py +139 -0
- contextwall-0.1.0/src/context_firewall/trust/signals.py +184 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Git history — large, not needed in any image
|
|
2
|
+
.git
|
|
3
|
+
.gitignore
|
|
4
|
+
|
|
5
|
+
# Python dev artifacts
|
|
6
|
+
__pycache__
|
|
7
|
+
*.pyc
|
|
8
|
+
*.pyo
|
|
9
|
+
*.pyd
|
|
10
|
+
.pytest_cache
|
|
11
|
+
.ruff_cache
|
|
12
|
+
.mypy_cache
|
|
13
|
+
dist/
|
|
14
|
+
build/
|
|
15
|
+
*.egg-info/
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
|
|
19
|
+
# Node / webapp — only needed in the webapp stage
|
|
20
|
+
# (The Dockerfile.webapp copies from webapp/ explicitly)
|
|
21
|
+
webapp/node_modules
|
|
22
|
+
webapp/.next
|
|
23
|
+
|
|
24
|
+
# Spec and docs
|
|
25
|
+
*.md
|
|
26
|
+
openspec/
|
|
27
|
+
|
|
28
|
+
# Local secrets — explicit at every level
|
|
29
|
+
.env*
|
|
30
|
+
*.env
|
|
31
|
+
**/.env*
|
|
32
|
+
**/*.env
|
|
33
|
+
|
|
34
|
+
# Editor
|
|
35
|
+
.vscode/
|
|
36
|
+
.idea/
|
|
37
|
+
*.swp
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# ContextWall OSS — environment variables
|
|
2
|
+
# Copy to .env.oss and fill in your keys
|
|
3
|
+
|
|
4
|
+
# Required for the demo agent (attack scenario demonstrations)
|
|
5
|
+
ANTHROPIC_API_KEY=your-anthropic-api-key-here
|
|
6
|
+
BRAVE_API_KEY=your-brave-search-api-key-here
|
|
7
|
+
|
|
8
|
+
# Demo mode: set false to run the agent without ContextWall filtering (shows attack without defense)
|
|
9
|
+
WITH_CONTEXTWALL=true
|
|
10
|
+
|
|
11
|
+
# Number of web search results to fetch per query
|
|
12
|
+
SEARCH_RESULTS=5
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Publish to GHCR
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build-and-push:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
packages: write
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Log in to GHCR
|
|
21
|
+
uses: docker/login-action@v3
|
|
22
|
+
with:
|
|
23
|
+
registry: ghcr.io
|
|
24
|
+
username: ${{ github.actor }}
|
|
25
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
26
|
+
|
|
27
|
+
- name: Extract metadata
|
|
28
|
+
id: meta
|
|
29
|
+
uses: docker/metadata-action@v5
|
|
30
|
+
with:
|
|
31
|
+
images: ghcr.io/bytewise-ca/context-wall
|
|
32
|
+
tags: |
|
|
33
|
+
type=semver,pattern={{version}}
|
|
34
|
+
type=semver,pattern={{major}}.{{minor}}
|
|
35
|
+
type=sha,prefix=sha-,format=short
|
|
36
|
+
type=raw,value=latest,enable={{is_default_branch}}
|
|
37
|
+
|
|
38
|
+
- name: Build and push
|
|
39
|
+
uses: docker/build-push-action@v5
|
|
40
|
+
with:
|
|
41
|
+
context: .
|
|
42
|
+
push: true
|
|
43
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
44
|
+
labels: ${{ steps.meta.outputs.labels }}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Secrets — never commit these
|
|
2
|
+
.env
|
|
3
|
+
.env.*
|
|
4
|
+
!.env.example
|
|
5
|
+
|
|
6
|
+
# Python
|
|
7
|
+
__pycache__/
|
|
8
|
+
*.pyc
|
|
9
|
+
*.pyo
|
|
10
|
+
*.pyd
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
.ruff_cache/
|
|
13
|
+
.mypy_cache/
|
|
14
|
+
dist/
|
|
15
|
+
build/
|
|
16
|
+
*.egg-info/
|
|
17
|
+
.venv/
|
|
18
|
+
venv/
|
|
19
|
+
|
|
20
|
+
# Runtime data
|
|
21
|
+
.ctxfw/
|
|
22
|
+
*.db
|
|
23
|
+
*.pid
|
|
24
|
+
|
|
25
|
+
# Editor
|
|
26
|
+
.vscode/
|
|
27
|
+
.idea/
|
|
28
|
+
*.swp
|
|
29
|
+
.DS_Store
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
FROM python:3.11-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
RUN apt-get update \
|
|
6
|
+
&& apt-get install -y --no-install-recommends curl git \
|
|
7
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
8
|
+
|
|
9
|
+
# Copy source — deps installed explicitly so this layer is cached on code-only changes
|
|
10
|
+
COPY pyproject.toml .
|
|
11
|
+
COPY src/ src/
|
|
12
|
+
|
|
13
|
+
RUN pip install --no-cache-dir \
|
|
14
|
+
"fastapi>=0.110" "uvicorn[standard]>=0.27" \
|
|
15
|
+
"fastmcp>=2.0" \
|
|
16
|
+
"pydantic>=2.0" "pydantic-settings>=2.0" \
|
|
17
|
+
"aiosqlite>=0.19" "kuzu>=0.3" "duckdb>=0.10" \
|
|
18
|
+
"apscheduler>=3.10" "watchdog>=3.0" \
|
|
19
|
+
"pyyaml>=6.0" \
|
|
20
|
+
"click>=8.0" "rich>=13.0" "httpx>=0.27" \
|
|
21
|
+
"opentelemetry-sdk>=1.20" \
|
|
22
|
+
"opentelemetry-exporter-otlp-proto-grpc>=1.20" \
|
|
23
|
+
"grpcio>=1.60" \
|
|
24
|
+
"rapidfuzz>=3.0" \
|
|
25
|
+
"cryptography>=42.0" \
|
|
26
|
+
"prometheus-client>=0.20" \
|
|
27
|
+
"aiobotocore>=2.0"
|
|
28
|
+
|
|
29
|
+
# src/ is importable without a package install
|
|
30
|
+
ENV PYTHONPATH=/app/src
|
|
31
|
+
|
|
32
|
+
EXPOSE 8080
|
|
33
|
+
|
|
34
|
+
# Runtime config is expected at /app/ctxfw.yaml via volume mount.
|
|
35
|
+
# Falls back to built-in defaults if the file is absent.
|
|
36
|
+
CMD ["python", "-m", "context_firewall.daemon.main"]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
|
|
3
|
+
ContextWall
|
|
4
|
+
Copyright (C) 2025 Bytewise Software Services (contextwall.io)
|
|
5
|
+
|
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU Affero General Public License as published
|
|
8
|
+
by the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU Affero General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU Affero General Public License
|
|
17
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
The full license text is available at:
|
|
22
|
+
https://www.gnu.org/licenses/agpl-3.0.txt
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
COMMERCIAL LICENSE
|
|
27
|
+
|
|
28
|
+
If you wish to use ContextWall in a proprietary product, embed it in a
|
|
29
|
+
closed-source system, or offer it as a service without complying with
|
|
30
|
+
the AGPL terms, a commercial license is available.
|
|
31
|
+
|
|
32
|
+
Contact: info@bytewise.ca
|
|
33
|
+
Website: https://contextwall.io
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: contextwall
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: ContextWall - context firewall for AI agents and RAG pipelines
|
|
5
|
+
Author-email: ContextWall <info@bytewise.ca>
|
|
6
|
+
License: AGPL-3.0-or-later
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: ai-agents,claude,context,context-firewall,llm,mcp,prompt-injection,rag,trust-scoring
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Requires-Dist: aiobotocore>=2.0
|
|
11
|
+
Requires-Dist: aiosqlite>=0.19
|
|
12
|
+
Requires-Dist: apscheduler>=3.10
|
|
13
|
+
Requires-Dist: click>=8.0
|
|
14
|
+
Requires-Dist: context-compiler-mcp
|
|
15
|
+
Requires-Dist: cryptography>=42.0
|
|
16
|
+
Requires-Dist: duckdb>=0.10
|
|
17
|
+
Requires-Dist: fastapi>=0.110
|
|
18
|
+
Requires-Dist: fastmcp>=2.0
|
|
19
|
+
Requires-Dist: grpcio>=1.60
|
|
20
|
+
Requires-Dist: httpx>=0.27
|
|
21
|
+
Requires-Dist: kuzu>=0.3
|
|
22
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.20
|
|
23
|
+
Requires-Dist: opentelemetry-sdk>=1.20
|
|
24
|
+
Requires-Dist: prometheus-client>=0.20
|
|
25
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
26
|
+
Requires-Dist: pydantic>=2.0
|
|
27
|
+
Requires-Dist: pyyaml>=6.0
|
|
28
|
+
Requires-Dist: rapidfuzz>=3.0
|
|
29
|
+
Requires-Dist: rich>=13.0
|
|
30
|
+
Requires-Dist: uvicorn[standard]>=0.27
|
|
31
|
+
Requires-Dist: watchdog>=3.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: httpx>=0.27; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
|
|
39
|
+
# ContextWall
|
|
40
|
+
|
|
41
|
+
**A context firewall for AI agents and RAG pipelines.**
|
|
42
|
+
|
|
43
|
+
Your agents pull context from everywhere: web search, internal docs, partner APIs, user uploads. ContextWall sits in front of every source, enforces your security policy, and stops malicious content before it reaches the model. No code changes to your agents required.
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
web search ──┐
|
|
47
|
+
internal docs─┤ ┌─► Claude / GPT-4
|
|
48
|
+
partner APIs ─┼──► ContextWall ──► policy ─┤
|
|
49
|
+
user uploads ─┤ (your rules) └─► blocked + audit trail
|
|
50
|
+
FHIR / PHI ──┘
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Why this exists
|
|
56
|
+
|
|
57
|
+
**EchoLeak (CVE-2025-32711, CVSS 9.3):** a crafted email caused Microsoft 365 Copilot to silently access SharePoint files and exfiltrate them. Zero user interaction. The root cause: the model had no way to tell the difference between a trusted system instruction and untrusted email content.
|
|
58
|
+
|
|
59
|
+
**PoisonedRAG (USENIX Security 2025):** 5 adversarial documents in a corpus of millions achieved 90%+ control over LLM responses. The model treated retrieved content as ground truth.
|
|
60
|
+
|
|
61
|
+
These are not edge cases. They are the default behavior of every RAG pipeline and agentic system that doesn't enforce source trust at the context layer.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## How ContextWall fixes it
|
|
66
|
+
|
|
67
|
+
**Every context source gets a trust tier.** Internal wikis, public web, regulated PHI data. Each carries a different level of trust, and your policy rules apply differently per tier.
|
|
68
|
+
|
|
69
|
+
**Content is scanned before the model sees it.** Three detection layers (structural bidi/zero-width scanning, normalized regex, and heuristic scoring for semantic paraphrases) run in under a millisecond with no LLM inference.
|
|
70
|
+
|
|
71
|
+
**Every decision is logged.** Tamper-evident Merkle chain, exportable as SOC2 evidence, HIPAA audit trail, or FedRAMP control mappings.
|
|
72
|
+
|
|
73
|
+
| Source tier | Examples | Default enforcement |
|
|
74
|
+
|-------------|----------|---------------------|
|
|
75
|
+
| `internal` | Code repos, internal wikis | Injection blocked, PII audit-only |
|
|
76
|
+
| `external` | Vendor docs, partner APIs | Injection blocked, PII warned |
|
|
77
|
+
| `untrusted` | Public web, user uploads | Injection + PII blocked |
|
|
78
|
+
| `regulated` | FHIR, PHI data sources | Injection + PII blocked, full compliance audit |
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Get started
|
|
83
|
+
|
|
84
|
+
**OSS daemon** (runs in your infrastructure, free forever):
|
|
85
|
+
```bash
|
|
86
|
+
# Install and start
|
|
87
|
+
pip install contextwall
|
|
88
|
+
ctxfw start --config ctxfw.yaml
|
|
89
|
+
|
|
90
|
+
# Or run with Docker
|
|
91
|
+
docker run -p 8080:8080 \
|
|
92
|
+
-v $(pwd)/ctxfw.yaml:/app/ctxfw.yaml \
|
|
93
|
+
ghcr.io/bytewise-ca/context-wall:latest
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Cloud dashboard** (optional: fleet visibility, policy authoring, compliance reports):
|
|
97
|
+
> Sign up at [app.contextwall.io](https://app.contextwall.io), generate a registration token in Settings, then add it to `ctxfw.yaml`:
|
|
98
|
+
> ```yaml
|
|
99
|
+
> control_plane:
|
|
100
|
+
> url: https://app.contextwall.io
|
|
101
|
+
> registration_token: cwt_your-token-here
|
|
102
|
+
> daemon_name: prod-us-east-1
|
|
103
|
+
> ```
|
|
104
|
+
> The daemon pushes only aggregated metadata (counts, scores) to the cloud. **Prompts, documents, and file contents never leave your infrastructure.**
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Integration
|
|
109
|
+
|
|
110
|
+
### Option 1: Environment variable (zero code change)
|
|
111
|
+
|
|
112
|
+
Point your existing SDK at the local daemon. Your agents don't need to change at all.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Anthropic (daemon runs on localhost:8080)
|
|
116
|
+
export ANTHROPIC_BASE_URL=http://localhost:8080/proxy/anthropic
|
|
117
|
+
export ANTHROPIC_API_KEY=sk-ant-your-real-key # unchanged
|
|
118
|
+
|
|
119
|
+
# OpenAI
|
|
120
|
+
export OPENAI_BASE_URL=http://localhost:8080/proxy/openai/v1
|
|
121
|
+
export OPENAI_API_KEY=sk-your-real-key # unchanged
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Every `anthropic.Anthropic()` or `openai.OpenAI()` call in your codebase is now screened locally. Prompts never leave your machine.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### Option 2: Python SDK (drop-in replace)
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from contextwall import SafeAnthropic, CREBlockedError
|
|
132
|
+
|
|
133
|
+
# Drop-in replacement for anthropic.Anthropic()
|
|
134
|
+
client = SafeAnthropic(
|
|
135
|
+
cre_endpoint="http://localhost:8080", # local daemon
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
response = client.messages.create(
|
|
140
|
+
model="claude-opus-4-7",
|
|
141
|
+
max_tokens=1024,
|
|
142
|
+
messages=[{"role": "user", "content": task}],
|
|
143
|
+
)
|
|
144
|
+
except CREBlockedError as e:
|
|
145
|
+
print(f"Blocked: {e.blocked_reason}") # injection_heuristic:instruction_override
|
|
146
|
+
print(f"Violations: {e.violations}")
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
pip install contextwall # base
|
|
151
|
+
pip install "contextwall[anthropic]" # + Anthropic SDK
|
|
152
|
+
pip install "contextwall[openai]" # + OpenAI SDK
|
|
153
|
+
pip install "contextwall[all]" # everything
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### Option 3: Document filter API (for RAG pipelines)
|
|
159
|
+
|
|
160
|
+
If your pipeline retrieves documents before calling the LLM, filter them through ContextWall before constructing the prompt. This is the primary defence against corpus poisoning.
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
import httpx
|
|
164
|
+
|
|
165
|
+
async def safe_rag(query: str, source_id: str) -> list[dict]:
|
|
166
|
+
"""Retrieve documents and filter through ContextWall before passing to LLM."""
|
|
167
|
+
raw_docs = await your_vector_store.search(query)
|
|
168
|
+
|
|
169
|
+
response = await httpx.AsyncClient().post(
|
|
170
|
+
"http://localhost:8080/v1/filter", # local daemon, no cloud call
|
|
171
|
+
json={
|
|
172
|
+
"source_id": source_id,
|
|
173
|
+
"documents": raw_docs,
|
|
174
|
+
"session_id": session_id,
|
|
175
|
+
},
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
result = response.json()
|
|
179
|
+
# result["documents"] - allowed docs, safe to include in prompt
|
|
180
|
+
# result["blocked"] - count of blocked documents
|
|
181
|
+
# result["blocked_documents"] - what was blocked and why
|
|
182
|
+
return result["documents"]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
ContextWall applies the trust tier of `source_id` to every document. A `trust_tier: untrusted` source gets full injection detection and PII scanning. The blocked documents never reach your prompt.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Declare your sources in config
|
|
190
|
+
|
|
191
|
+
Sources are declared in `ctxfw.yaml`. No API calls, no imperative setup code. Commit it alongside your infrastructure.
|
|
192
|
+
|
|
193
|
+
```yaml
|
|
194
|
+
# ctxfw.yaml
|
|
195
|
+
|
|
196
|
+
sources:
|
|
197
|
+
- id: brave-web-search
|
|
198
|
+
type: web
|
|
199
|
+
trust_tier: untrusted
|
|
200
|
+
|
|
201
|
+
- id: internal-confluence
|
|
202
|
+
type: confluence
|
|
203
|
+
trust_tier: internal
|
|
204
|
+
data_classification: sensitive
|
|
205
|
+
|
|
206
|
+
- id: fhir-api
|
|
207
|
+
type: api
|
|
208
|
+
trust_tier: regulated
|
|
209
|
+
data_classification: phi
|
|
210
|
+
owner: clinical-data-team
|
|
211
|
+
region: us-east-1
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
ContextWall registers these on every startup: idempotent, version-controlled, reviewable in a PR.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Policy as code
|
|
219
|
+
|
|
220
|
+
Write security rules in YAML. Commit them. Review them like any other infrastructure change.
|
|
221
|
+
|
|
222
|
+
```yaml
|
|
223
|
+
# policies/fleet/no-phi-exfil.yaml
|
|
224
|
+
rules:
|
|
225
|
+
- name: block-phi-exfiltration
|
|
226
|
+
action: deny
|
|
227
|
+
reason: "PHI must not leave regulated sources"
|
|
228
|
+
applies_when:
|
|
229
|
+
source_tier: [regulated]
|
|
230
|
+
compliance_mapping:
|
|
231
|
+
framework: hipaa
|
|
232
|
+
control_id: "45 CFR 164.502(b)"
|
|
233
|
+
|
|
234
|
+
- name: block-web-injection
|
|
235
|
+
action: deny
|
|
236
|
+
reason: "Untrusted web content blocked from high-stakes tasks"
|
|
237
|
+
applies_when:
|
|
238
|
+
source_tier: [untrusted]
|
|
239
|
+
task_scope: [financial_decision, medical_query]
|
|
240
|
+
compliance_mapping:
|
|
241
|
+
framework: soc2
|
|
242
|
+
control_id: "CC6.1"
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Rules reload within 5 seconds of a file change. No restart. No redeploy.
|
|
246
|
+
|
|
247
|
+
**Pre-built policy packs** for HIPAA, SOC2, and FedRAMP ship out of the box.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Tune detection sensitivity
|
|
252
|
+
|
|
253
|
+
Override defaults in `ctxfw.yaml`, per deployment, per environment.
|
|
254
|
+
|
|
255
|
+
```yaml
|
|
256
|
+
detection:
|
|
257
|
+
injection_block_threshold: 0.55 # raise to reduce false positives
|
|
258
|
+
injection_warn_threshold: 0.35 # lower to catch more, audit instead of block
|
|
259
|
+
default_source_trust_tier: untrusted
|
|
260
|
+
|
|
261
|
+
enforcement:
|
|
262
|
+
penalty_increment: 0.15 # trust penalty per deny event
|
|
263
|
+
decay_half_life_days: 1.0 # penalty halves every N days (auto-recovery)
|
|
264
|
+
reward_factor: 0.90 # trust improves with clean outcomes
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## What gets detected
|
|
270
|
+
|
|
271
|
+
| Attack class | Detection layer | Example |
|
|
272
|
+
|---|---|---|
|
|
273
|
+
| Direct instruction override | L1 structural + L2 regex | `IGNORE ALL PREVIOUS INSTRUCTIONS` |
|
|
274
|
+
| Bidi / zero-width obfuscation | L1 structural | RTL override chars in retrieved text |
|
|
275
|
+
| Spaced-letter injection | L1 structural | `i g n o r e p r e v i o u s` |
|
|
276
|
+
| Semantic paraphrase injection | L3 heuristic | "Your previous assignment has been superseded by the administrator" |
|
|
277
|
+
| Secret leakage | L2 regex | AWS keys, GitHub PATs, bearer tokens, private keys |
|
|
278
|
+
| PII exfiltration | L2 regex | Emails, phone numbers, SSNs in untrusted context |
|
|
279
|
+
|
|
280
|
+
Sub-millisecond latency. No LLM in the hot path.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Compliance
|
|
285
|
+
|
|
286
|
+
Every enforcement decision writes to a Merkle-chained append-only log. Export on demand:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
# SOC2 Type II evidence package (JSON, cryptographically signed)
|
|
290
|
+
ctxfw compliance export --framework soc2 --days 90 --out soc2-evidence.json
|
|
291
|
+
|
|
292
|
+
# HIPAA audit trail
|
|
293
|
+
ctxfw compliance export --framework hipaa --days 365 --out hipaa-audit.json
|
|
294
|
+
|
|
295
|
+
# Or call the local API directly
|
|
296
|
+
curl http://localhost:8080/v1/compliance/export \
|
|
297
|
+
-H "Authorization: Bearer $CRE_API_TOKEN" \
|
|
298
|
+
-d '{"framework": "soc2", "days": 90}'
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Every export is cryptographically signed. The `/v1/compliance/verify` endpoint proves chain integrity independently of the exporter.
|
|
302
|
+
|
|
303
|
+
Supported: **SOC2 Type II**, **HIPAA** (45 CFR 164.312), **FedRAMP** (NIST 800-53), **GDPR** (Article 32).
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Observability
|
|
308
|
+
|
|
309
|
+
```
|
|
310
|
+
GET /health - subsystem health
|
|
311
|
+
GET /metrics - Prometheus metrics
|
|
312
|
+
WS /ws/events - live enforcement event stream
|
|
313
|
+
GET /v1/sources - registered sources + enforcement history
|
|
314
|
+
GET /v1/sources/{id}/trust - trust health per source
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Key metrics emitted:
|
|
318
|
+
|
|
319
|
+
| Metric | What it tells you |
|
|
320
|
+
|--------|-------------------|
|
|
321
|
+
| `cre_proxy_requests_total{result}` | Block rate by provider |
|
|
322
|
+
| `cre_proxy_violations_total{type}` | Breakdown by violation type |
|
|
323
|
+
| `cre_enforcement_penalty{source}` | Trust degradation per source |
|
|
324
|
+
| `cre_pipeline_duration_seconds` | End-to-end latency |
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Architecture
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
ctxfw.yaml (sources, policy, thresholds)
|
|
332
|
+
│
|
|
333
|
+
Your agent / RAG pipeline │
|
|
334
|
+
│ ▼
|
|
335
|
+
│ ContextWall
|
|
336
|
+
│ ┌─────────────────────────────────────────┐
|
|
337
|
+
│ │ Source Registry (O(1) tier lookup) │
|
|
338
|
+
└────────►│ │
|
|
339
|
+
│ L1 Structural scan (<0.1ms) │
|
|
340
|
+
│ L2 Normalized regex (<0.2ms) │
|
|
341
|
+
│ L3 Heuristic scoring (<0.5ms) │
|
|
342
|
+
│ │
|
|
343
|
+
│ Policy DSL (fleet→org→team→repo) │
|
|
344
|
+
└──────────────┬──────────────────────────┘
|
|
345
|
+
│
|
|
346
|
+
┌──────────────┴──────────────────────────┐
|
|
347
|
+
│ allowed blocked │
|
|
348
|
+
▼ ▼ │
|
|
349
|
+
LLM API 400 + violation │
|
|
350
|
+
(Anthropic / OpenAI) details │
|
|
351
|
+
│ │
|
|
352
|
+
▼ │
|
|
353
|
+
Provenance Engine │
|
|
354
|
+
(Merkle-chained log) │
|
|
355
|
+
│ │
|
|
356
|
+
┌───────────┼───────────┐ │
|
|
357
|
+
▼ ▼ ▼ │
|
|
358
|
+
SQLite WebSocket Compliance │
|
|
359
|
+
live feed export │
|
|
360
|
+
└────────────────────────────────────────── ┘
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Self-hosting
|
|
366
|
+
|
|
367
|
+
```yaml
|
|
368
|
+
# ctxfw.yaml: minimal production config
|
|
369
|
+
repository_root: /app
|
|
370
|
+
|
|
371
|
+
sources:
|
|
372
|
+
- id: my-web-search
|
|
373
|
+
type: web
|
|
374
|
+
trust_tier: untrusted
|
|
375
|
+
|
|
376
|
+
rest_api:
|
|
377
|
+
port: 8080
|
|
378
|
+
auth:
|
|
379
|
+
enabled: true
|
|
380
|
+
tokens:
|
|
381
|
+
- token: "${CRE_API_TOKEN}"
|
|
382
|
+
name: admin
|
|
383
|
+
scopes: [analyze, bundle, admin, compliance]
|
|
384
|
+
|
|
385
|
+
storage:
|
|
386
|
+
db_path: /data/cre.db
|
|
387
|
+
|
|
388
|
+
policy:
|
|
389
|
+
policy_dir: /data/policies
|
|
390
|
+
|
|
391
|
+
compliance_hmac_key: "${CRE_COMPLIANCE_HMAC_KEY}"
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
# Generate secrets
|
|
396
|
+
export CRE_API_TOKEN=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
|
|
397
|
+
export CRE_COMPLIANCE_HMAC_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
|
|
398
|
+
|
|
399
|
+
docker run -d -p 8080:8080 \
|
|
400
|
+
-e CRE_API_TOKEN \
|
|
401
|
+
-e CRE_COMPLIANCE_HMAC_KEY \
|
|
402
|
+
-v $(pwd)/ctxfw.yaml:/app/ctxfw.yaml \
|
|
403
|
+
-v $(pwd)/policies:/data/policies \
|
|
404
|
+
-v cre-data:/data \
|
|
405
|
+
ghcr.io/bytewise-ca/context-wall:latest
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
ContextWall refuses to start with known-weak tokens and prints a generation command. Compliance HMAC key absence is warned at startup.
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## What's in this repo
|
|
413
|
+
|
|
414
|
+
| Component | Path | Description |
|
|
415
|
+
|-----------|------|-------------|
|
|
416
|
+
| Core daemon | `src/context_firewall/` | Proxy, policy engine, provenance, trust scoring |
|
|
417
|
+
| Python SDK | `sdk/python/` | `SafeAnthropic`, `SafeOpenAI`, `CREClient` |
|
|
418
|
+
| Policy packs | `policy/packs/` | Pre-built HIPAA, SOC2, FedRAMP rule sets |
|
|
419
|
+
| Live demo | `demo/` | Attack scenarios + dashboard (requires API keys) |
|
|
420
|
+
|
|
421
|
+
The cloud control plane (fleet dashboard, policy authoring UI, compliance reports) is available at [app.contextwall.io](https://app.contextwall.io).
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## License
|
|
426
|
+
|
|
427
|
+
**AGPL v3:** core proxy, policy engine, provenance chain, Python SDK.
|
|
428
|
+
|
|
429
|
+
If you run ContextWall as a service (managed or embedded), AGPL requires you to release your modifications under the same terms. If your organisation cannot comply with AGPL (for example, you want to embed ContextWall in a proprietary product or offer it as a closed SaaS), a commercial license is available at [contextwall.io](https://contextwall.io).
|
|
430
|
+
|
|
431
|
+
Fleet policy management, multi-tenant control plane, and the cloud dashboard are available on the paid cloud plan only.
|