travis234-websec-mcp 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.
- travis234_websec_mcp-0.1.0/PKG-INFO +248 -0
- travis234_websec_mcp-0.1.0/README.md +233 -0
- travis234_websec_mcp-0.1.0/extensions/websec_mcp.py +11 -0
- travis234_websec_mcp-0.1.0/libexec/travis234-websec-mcp/server.py +10 -0
- travis234_websec_mcp-0.1.0/pyproject.toml +46 -0
- travis234_websec_mcp-0.1.0/setup.cfg +4 -0
- travis234_websec_mcp-0.1.0/tests/test_acceptance.py +42 -0
- travis234_websec_mcp-0.1.0/tests/test_application.py +222 -0
- travis234_websec_mcp-0.1.0/tests/test_comparison.py +179 -0
- travis234_websec_mcp-0.1.0/tests/test_config.py +97 -0
- travis234_websec_mcp-0.1.0/tests/test_container_qualification.py +69 -0
- travis234_websec_mcp-0.1.0/tests/test_exports.py +334 -0
- travis234_websec_mcp-0.1.0/tests/test_extension.py +181 -0
- travis234_websec_mcp-0.1.0/tests/test_http_executor.py +1020 -0
- travis234_websec_mcp-0.1.0/tests/test_http_fixture.py +47 -0
- travis234_websec_mcp-0.1.0/tests/test_installed_contract.py +61 -0
- travis234_websec_mcp-0.1.0/tests/test_installed_wheel.py +137 -0
- travis234_websec_mcp-0.1.0/tests/test_matching.py +221 -0
- travis234_websec_mcp-0.1.0/tests/test_mcp_output.py +86 -0
- travis234_websec_mcp-0.1.0/tests/test_mcp_protocol.py +324 -0
- travis234_websec_mcp-0.1.0/tests/test_presentation.py +78 -0
- travis234_websec_mcp-0.1.0/tests/test_prompt_compatibility.py +114 -0
- travis234_websec_mcp-0.1.0/tests/test_protocol_redaction.py +39 -0
- travis234_websec_mcp-0.1.0/tests/test_raw_request.py +53 -0
- travis234_websec_mcp-0.1.0/tests/test_redaction.py +574 -0
- travis234_websec_mcp-0.1.0/tests/test_rendering.py +41 -0
- travis234_websec_mcp-0.1.0/tests/test_requests.py +81 -0
- travis234_websec_mcp-0.1.0/tests/test_results.py +25 -0
- travis234_websec_mcp-0.1.0/tests/test_scope.py +43 -0
- travis234_websec_mcp-0.1.0/tests/test_sdk_rendering.py +31 -0
- travis234_websec_mcp-0.1.0/tests/test_skill_protocol.py +77 -0
- travis234_websec_mcp-0.1.0/tests/test_stdio_io.py +251 -0
- travis234_websec_mcp-0.1.0/tests/test_store.py +99 -0
- travis234_websec_mcp-0.1.0/tests/test_transforms.py +90 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/__init__.py +1 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/analysis_budget.py +35 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/application.py +145 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/cli.py +52 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/comparison.py +49 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/config.py +103 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/errors.py +7 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/exports.py +134 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/extension.py +10 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/host.py +93 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/http_executor.py +133 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/lifetime.py +22 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/limits.py +21 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/matching.py +184 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/mcp_output.py +73 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/mcp_server.py +131 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/presentation.py +69 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/raw_request.py +57 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/redaction.py +324 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/rendering.py +151 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/requests.py +101 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/SOURCES.json +525 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ai-security/LICENSE.txt +21 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ai-security/SKILL.md +602 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ai-security/TRAVIS234.md +50 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-api-security/LICENSE.txt +21 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-api-security/SKILL.md +511 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-api-security/TRAVIS234.md +50 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-idor/LICENSE.txt +21 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-idor/SKILL.md +618 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-idor/TRAVIS234.md +50 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-jwt/LICENSE.txt +21 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-jwt/SKILL.md +281 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-jwt/TRAVIS234.md +50 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-reporting/LICENSE.txt +21 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-reporting/SKILL.md +378 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-reporting/TRAVIS234.md +50 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssrf/LICENSE.txt +21 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssrf/SKILL.md +840 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssrf/TRAVIS234.md +50 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssti/LICENSE.txt +21 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssti/SKILL.md +626 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/offensive-ssti/TRAVIS234.md +50 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/LICENSE.txt +21 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/SKILL.md +43 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/TRAVIS234.md +50 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/INDEX.md +75 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/access-control-resources.md +133 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/business-logic-resources.md +130 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/information-disclosure-resources.md +166 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/race-conditions-resources.md +132 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/data-leakage-redirect.md +73 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/header-bypass.md +169 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/idor-action.md +65 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/idor-read.md +176 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/mass-assignment.md +118 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/method-bypass.md +102 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/multi-step-bypass.md +63 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/parameter-based-controls.md +114 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/referer-bypass.md +58 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/access-control/unprotected-functionality.md +86 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/burp-extension-scanner.md +146 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/coupon-stacking.md +243 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/csrf-and-session-bypass.md +117 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/email-domain-bypass.md +123 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/gift-card-loop.md +265 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/parameter-pollution.md +249 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/price-manipulation.md +183 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/quantity-manipulation.md +267 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/regex-input-validation-bypass.md +53 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/business-logic/workflow-bypass.md +150 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/deception-delimiter.md +119 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/deception-normalization.md +109 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/deception-path-mapping.md +123 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/deception-via-smuggling.md +60 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/poisoning-body-args.md +99 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/poisoning-setnx-race.md +132 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/poisoning-unkeyed-headers.md +239 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/cache/poisoning-unkeyed-params.md +222 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/backups-and-version-control.md +167 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/client-side-storage-audit.md +88 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/debug-pages-and-cms-apis.md +133 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/error-messages.md +106 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/http-method-disclosure.md +103 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/javascript-source-review.md +81 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/multi-port-and-storage-discovery.md +117 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/info-disclosure/security-headers-audit.md +134 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/advanced-techniques.md +205 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/container-startup-admin-registration.md +75 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/detection-and-baseline.md +273 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/file-upload-race.md +102 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/limit-overrun.md +90 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/multi-endpoint.md +102 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/partial-construction.md +87 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/rate-limit-bypass.md +107 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/single-endpoint-collision.md +78 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/timestamp-collision.md +81 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/scenarios/race-conditions/toctou-session.md +132 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/web-app-logic-principles.md +59 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/web-cache-deception-resources.md +135 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/resources/skills/web-app-logic/reference/web-cache-poisoning-resources.md +169 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/results.py +21 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/schemas.py +87 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/scope.py +54 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/skill_library.py +166 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/stdio_io.py +149 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/store.py +73 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/transforms.py +65 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/transport.py +94 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp/types.py +50 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/PKG-INFO +248 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/SOURCES.txt +148 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/dependency_links.txt +1 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/entry_points.txt +2 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/requires.txt +7 -0
- travis234_websec_mcp-0.1.0/travis234_websec_mcp.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: travis234-websec-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Independent bounded HTTP security workbench for MCP clients and Travis234.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: <3.14,>=3.13
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: mcp<3,>=2.2
|
|
9
|
+
Requires-Dist: pydantic<3,>=2.12
|
|
10
|
+
Requires-Dist: httpx<1,>=0.27
|
|
11
|
+
Requires-Dist: httpcore<2,>=1
|
|
12
|
+
Requires-Dist: anyio<5,>=4
|
|
13
|
+
Requires-Dist: ahocorasick-rs<2,>=1.0.3
|
|
14
|
+
Requires-Dist: travis234-mcp-adapter<0.5,>=0.4
|
|
15
|
+
|
|
16
|
+
# Travis234 Websec MCP
|
|
17
|
+
|
|
18
|
+
An optional external HTTP workbench for Travis234 and standard stdio MCP clients.
|
|
19
|
+
Python 3.13 and macOS or Linux are required. Travis core and its existing MCP
|
|
20
|
+
adapter supply the host integration; this package owns requests, HTTP execution,
|
|
21
|
+
sanitization and evidence. KHackBar is a workflow reference and is not a dependency.
|
|
22
|
+
|
|
23
|
+
This milestone supports individual request experiments. Payload catalogs,
|
|
24
|
+
generators, batch fuzzing, login/token extraction and browser capture remain
|
|
25
|
+
future work. The package also includes imported assessment skills, built into
|
|
26
|
+
Travis and exposed to other clients through MCP
|
|
27
|
+
resources and prompts. These guides do not install external scanners. See the repository's
|
|
28
|
+
[complete KHackBar feature mapping](../../docs/verification/2026-10-18-khackbar-feature-crosscheck.md).
|
|
29
|
+
|
|
30
|
+
## Build, install and activate
|
|
31
|
+
|
|
32
|
+
Run these commands from the Travis234 repository root:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
uv sync --project packages/travis234-websec-mcp --locked --group source-test
|
|
36
|
+
websec_dist_dir="$(mktemp -d "${TMPDIR:-/tmp}/websec-dist.XXXXXX")"
|
|
37
|
+
uv build --wheel --out-dir "$websec_dist_dir" packages/travis234-mcp-adapter
|
|
38
|
+
uv build --wheel --out-dir "$websec_dist_dir" packages/travis234-websec-mcp
|
|
39
|
+
export PIP_FIND_LINKS="$websec_dist_dir"
|
|
40
|
+
export UV_FIND_LINKS="$websec_dist_dir"
|
|
41
|
+
websec_wheel_uri="$(packages/travis234-websec-mcp/.venv/bin/python -c 'from pathlib import Path; import sys; print(next(Path(sys.argv[1]).glob("travis234_websec_mcp-*.whl")).resolve().as_uri())' "$websec_dist_dir")"
|
|
42
|
+
travis234 install "travis234-websec-mcp @ $websec_wheel_uri"
|
|
43
|
+
travis234 --tools read,bash,websec
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Installation registers the package-owned server and one `websec` facade through
|
|
47
|
+
the shared adapter. Discovery and `status` do not send a testing request. Tool
|
|
48
|
+
selection uses the existing `--tools` allowlist; there is no new Travis flag.
|
|
49
|
+
|
|
50
|
+
For another MCP client, install the wheel and its dependencies into that client's
|
|
51
|
+
Python 3.13 environment, then configure this stdio command:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
travis234-websec-mcp mcp --transport stdio
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The standalone server does not import the Travis extension. It uses the same
|
|
58
|
+
configuration, request bounds and evidence format.
|
|
59
|
+
|
|
60
|
+
## Imported assessment skills
|
|
61
|
+
|
|
62
|
+
The source index is
|
|
63
|
+
[htooayelwinict/awesome-ai-offensive-security](https://github.com/htooayelwinict/awesome-ai-offensive-security/tree/0e3180f4a0ffd5b6703943cf112d85017895a842).
|
|
64
|
+
That repository contains links; the actual skills are imported from these
|
|
65
|
+
linked MIT-licensed projects at fixed revisions:
|
|
66
|
+
|
|
67
|
+
| Source | Included skills |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| [SnailSploit/Claude-Red](https://github.com/SnailSploit/Claude-Red/tree/a8de813edc9f66f60d44cfe42d47750e89d9930b) | `offensive-api-security`, `offensive-jwt`, `offensive-idor`, `offensive-ssrf`, `offensive-ssti`, `offensive-ai-security`, `offensive-reporting` |
|
|
70
|
+
| [transilienceai/communitytools](https://github.com/transilienceai/communitytools/tree/95fdc128af4ca1ae16b3226f9430f1bad97b0656/skills/web-app-logic) | `web-app-logic`, including its reference and scenario files |
|
|
71
|
+
|
|
72
|
+
All eight skills ship as read-only built-ins in Travis's Python and npm
|
|
73
|
+
distributions, using its existing lazy loader, precedence and trust rules.
|
|
74
|
+
Installing this optional package adds the Websec tools. When the user asks to
|
|
75
|
+
use Websec MCP, its facade instructs the agent to try loading all eight
|
|
76
|
+
SKILL.md guides before its first Websec call, like Evidence MCP's research
|
|
77
|
+
skill. This guidance also accompanies authorized delegation. User overrides
|
|
78
|
+
and `--no-skills` remain effective; unavailable guides are reported. Additional
|
|
79
|
+
reference files load only as needed. The package does not register duplicate
|
|
80
|
+
skill directories. A standalone installation exposes the same documents
|
|
81
|
+
through MCP resources and prompts. No skill is copied into the user's Codex installation.
|
|
82
|
+
|
|
83
|
+
Each imported skill has a `TRAVIS234.md` guide describing the supported tools
|
|
84
|
+
and request workflow. Local changes add compatible YAML metadata and a link to
|
|
85
|
+
that guide. Upstream methodology and references are retained. Each skill keeps
|
|
86
|
+
its upstream license; [SOURCES.json](travis234_websec_mcp/resources/skills/SOURCES.json)
|
|
87
|
+
records repository revisions, source paths, original hashes and shipped hashes.
|
|
88
|
+
Imports are bundled: startup, discovery and reads do not fetch updates or run
|
|
89
|
+
upstream code.
|
|
90
|
+
|
|
91
|
+
For a standard MCP client:
|
|
92
|
+
|
|
93
|
+
- `resources/list` enumerates skill documents in pages of eight. Pass its
|
|
94
|
+
`nextCursor` back as `cursor` until it is absent.
|
|
95
|
+
- Read `websec://skills/index` for the skill index, then a skill's
|
|
96
|
+
`websec://skills/<name>/TRAVIS234.md` and `websec://skills/<name>/SKILL.md`.
|
|
97
|
+
- A document larger than 4 KiB returns an ordered part index. Read the listed
|
|
98
|
+
`?part=1`, `?part=2`, … URIs in order. All bytes are retained, with UTF-8
|
|
99
|
+
characters kept intact. Relative references resolve within the skill's URI
|
|
100
|
+
directory. Each part is at most 4 KiB before protocol encoding. When literal
|
|
101
|
+
code examples cannot pass the existing text classifier unchanged, the read
|
|
102
|
+
uses a standard MCP blob with the same MIME type: Base64-decode it as UTF-8
|
|
103
|
+
to recover the exact text.
|
|
104
|
+
- `prompts/list` exposes eight entry prompts, named `websec-<skill-name>`.
|
|
105
|
+
`prompts/get` takes that name and no arguments; it directs the client to the
|
|
106
|
+
integration guide and relevant upstream resources.
|
|
107
|
+
|
|
108
|
+
Resource reads accept only bundled catalog URIs. Unknown URIs, prompts and
|
|
109
|
+
cursors return fixed errors. The original document is checked before any part
|
|
110
|
+
is returned, and the existing final MCP frame checks still apply. When a known
|
|
111
|
+
credential overlaps a document, its read fails without returning that document.
|
|
112
|
+
|
|
113
|
+
The existing seven request operations retain their contracts. Browser sessions,
|
|
114
|
+
raw protocol experiments, parallel probes and external tools mentioned in a
|
|
115
|
+
guide require those capabilities separately. Imported methodology does not
|
|
116
|
+
enable them in the Websec executor.
|
|
117
|
+
|
|
118
|
+
## Try the actual acceptance fixture
|
|
119
|
+
|
|
120
|
+
In one terminal, start the bundled fixture. It prints its actual loopback origin:
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
packages/travis234-websec-mcp/.venv/bin/python packages/travis234-websec-mcp/tests/http_fixture.py
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Keep it running. In a second terminal, copy that origin into
|
|
127
|
+
`WEBSEC_FIXTURE_ORIGIN`, then create an isolated lab configuration:
|
|
128
|
+
|
|
129
|
+
```sh
|
|
130
|
+
export WEBSEC_FIXTURE_ORIGIN='http://127.0.0.1:<printed-port>'
|
|
131
|
+
export WEBSEC_LAB_TOKEN='synthetic-lab-token'
|
|
132
|
+
websec_lab_dir="$(mktemp -d "${TMPDIR:-/tmp}/websec-lab.XXXXXX")"
|
|
133
|
+
export TRAVIS234_CODING_AGENT_DIR="$websec_lab_dir/agent"
|
|
134
|
+
packages/travis234-websec-mcp/.venv/bin/python - <<'PY'
|
|
135
|
+
import json
|
|
136
|
+
import os
|
|
137
|
+
from pathlib import Path
|
|
138
|
+
from urllib.parse import urlsplit
|
|
139
|
+
|
|
140
|
+
origin = os.environ['WEBSEC_FIXTURE_ORIGIN']
|
|
141
|
+
assert urlsplit(origin).hostname == '127.0.0.1' and urlsplit(origin).port
|
|
142
|
+
path = Path(os.environ['TRAVIS234_CODING_AGENT_DIR']) / 'websec' / 'config.json'
|
|
143
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
144
|
+
path.write_text(json.dumps({'version': 1, 'profiles': {'lab': {
|
|
145
|
+
'origins': [origin],
|
|
146
|
+
'headers': {'Authorization': 'Bearer ${WEBSEC_LAB_TOKEN}'},
|
|
147
|
+
'deadline_seconds': 10,
|
|
148
|
+
}}}))
|
|
149
|
+
PY
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Run installation and activation in that same terminal so Travis inherits the
|
|
153
|
+
directory override and credential reference. Stop the fixture with Ctrl-C.
|
|
154
|
+
Normal operator configuration lives at `~/.travis234/agent/websec/config.json`;
|
|
155
|
+
the existing `TRAVIS234_CODING_AGENT_DIR` override changes the agent directory.
|
|
156
|
+
The package never loads `.env` files. Headers accept exact `$env:NAME` references
|
|
157
|
+
or `${NAME}` interpolation. Missing or empty references leave offline operations
|
|
158
|
+
available and make `send` return `authentication_unavailable` before connecting.
|
|
159
|
+
|
|
160
|
+
## Request workflow
|
|
161
|
+
|
|
162
|
+
Call `websec` with the following operation arguments. Replace the fixture origin
|
|
163
|
+
with its printed value and copy each returned ID exactly:
|
|
164
|
+
|
|
165
|
+
| Operation | Arguments and result |
|
|
166
|
+
| --- | --- |
|
|
167
|
+
| `status` | `{}` or `{"operation":"status"}` returns configuration, profiles and limits. |
|
|
168
|
+
| `prepare` | `{"operation":"prepare","profile":"lab","request":{"url":"<fixture-origin>/query-echo?q=original&q=untouched"}}` creates an immutable request ID. Optional request fields are `method`, header pairs and a UTF-8 `body`. |
|
|
169
|
+
| `mutate` | `{"operation":"mutate","request_id":"<original-id>","location":"query","index":0,"value":"changed"}` creates a new ID. Header mutation is also indexed; body mutation replaces the whole body. |
|
|
170
|
+
| `transform` | `{"operation":"transform","value":"a b","codec":"url","direction":"encode"}` returns `a%20b`. Codecs are `url`, `base64`, `hex`, `double_url`, `html`, `unicode` and `reverse`; both directions are supported. |
|
|
171
|
+
| `send` | `{"operation":"send","request_id":"<request-id>"}` executes that snapshot once. Send the original and changed IDs separately. |
|
|
172
|
+
| `compare` | `{"operation":"compare","left_response_id":"<original-response-id>","right_response_id":"<changed-response-id>"}` returns measured differences, completeness and an optional sanitized diff. |
|
|
173
|
+
| `export` | The same response pair with `"operation":"export"` writes a new evidence file and returns its basename, ID and byte count. |
|
|
174
|
+
|
|
175
|
+
The fixture receives `original`, then `changed`, with the second query entry
|
|
176
|
+
unchanged. Its UTF-8 response bodies have 8 and 7 bytes respectively. Reusing the
|
|
177
|
+
original ID sends the original value again. `prepare` also accepts strict raw
|
|
178
|
+
HTTP/1.1 text using `raw_request` and an explicit `origin`, instead of `request`.
|
|
179
|
+
Ambiguous framing, invalid fields and unavailable IDs return specific bounded
|
|
180
|
+
errors. Comparisons report observations rather than vulnerability verdicts.
|
|
181
|
+
|
|
182
|
+
### Additional text codecs
|
|
183
|
+
|
|
184
|
+
| Codec | Defined behavior |
|
|
185
|
+
| --- | --- |
|
|
186
|
+
| `double_url` | Apply the existing UTF-8 URL conversion exactly twice. Decoding rejects malformed percent escapes or invalid UTF-8 at either step. A literal `+` stays `+`. |
|
|
187
|
+
| `html` | Encode the five HTML special characters; the apostrophe becomes `'`. Decode named/numeric entities once using HTML5 rules. Markup stays text: decoding `<b>é</b>` returns `<b>é</b>`. |
|
|
188
|
+
| `unicode` | Encode each UTF-16 unit as a lowercase `\uXXXX` escape, including valid pairs for supplementary characters. Decode those escapes once, combine valid surrogate pairs and reject malformed or unpaired units. Other backslash sequences and percent escapes stay literal. |
|
|
189
|
+
| `reverse` | Reverse Unicode code points. Both directions perform the same operation; `A😀é` becomes `é😀A`. Combining marks reverse individually. |
|
|
190
|
+
|
|
191
|
+
These operations retain the 16 KiB input and 64 KiB output limits. The aggregate
|
|
192
|
+
MCP frame limit also applies, so a valid engine result can return `output_limit`
|
|
193
|
+
at the public boundary. Errors never return a successful partial transformation.
|
|
194
|
+
Known credentials are checked in both the source value and the derived result.
|
|
195
|
+
|
|
196
|
+
## Bounds, credentials and lifetime
|
|
197
|
+
|
|
198
|
+
Origins are exact normalized scheme/host/port allowlists. Every send checks its
|
|
199
|
+
final target. The client performs one exchange, follows no redirects, retries
|
|
200
|
+
nothing, carries no cookie jar, verifies TLS and ignores proxy environment
|
|
201
|
+
variables. Only one send runs at a time; an overlapping send returns `busy`.
|
|
202
|
+
Cancellation and shutdown close and join owned HTTP work.
|
|
203
|
+
|
|
204
|
+
| Resource | Limit |
|
|
205
|
+
| --- | --- |
|
|
206
|
+
| URL / request body / raw import | 8 / 64 / 128 KiB |
|
|
207
|
+
| Wire headers, including authentication and framing | 100 entries / 32 KiB |
|
|
208
|
+
| Transform input / output | 16 / 64 KiB |
|
|
209
|
+
| Deadline | Default 10 seconds; profile integer 1–30. A caller may only lower it with `timeout_seconds`. |
|
|
210
|
+
| Retained response / text preview | 1 MiB / 8 KiB |
|
|
211
|
+
| Requests / responses in memory | 32 / 16; unpinned oldest entries are evicted. |
|
|
212
|
+
| Complete outgoing MCP frame / exported JSON | 32 KiB / 4 MiB |
|
|
213
|
+
|
|
214
|
+
Compressed responses are reported as `unsupported_encoding` and are not decoded.
|
|
215
|
+
Binary and incomplete responses preserve honest byte measurements; comparison
|
|
216
|
+
does not infer complete text equality or an exact complete-body length from them.
|
|
217
|
+
Incomplete or oversized presentation values are withheld in full, with explicit
|
|
218
|
+
omission flags. Complete bounded JSON can retain unrelated public fields.
|
|
219
|
+
|
|
220
|
+
Keep credentials in the operator environment and profile references. Never paste
|
|
221
|
+
them into tool arguments: the host records those inputs before the plugin sees
|
|
222
|
+
them. Available referenced values and bounded URL/Base64/hex forms are sanitized
|
|
223
|
+
from returned results and exports. Authentication values go only to an allowed
|
|
224
|
+
origin's request.
|
|
225
|
+
|
|
226
|
+
Request and response IDs belong to one server process. Shutdown, reload or
|
|
227
|
+
eviction can invalidate them. Exports persist under
|
|
228
|
+
`<agent-directory>/websec/evidence/` as new atomic mode-0600 JSON files; the tool
|
|
229
|
+
does not accept arbitrary export paths or overwrite prior evidence.
|
|
230
|
+
|
|
231
|
+
Restart the entire Travis process after changing profile configuration,
|
|
232
|
+
credential references/environment or the installed package. Registrations are
|
|
233
|
+
process-local; an existing host does not replace a different descriptor in place.
|
|
234
|
+
Stop Travis before removing the package, then start a new process to confirm the
|
|
235
|
+
facade is absent. Removing the package preserves exported evidence.
|
|
236
|
+
|
|
237
|
+
## Qualification
|
|
238
|
+
|
|
239
|
+
```sh
|
|
240
|
+
PYTHONDONTWRITEBYTECODE=1 packages/travis234-websec-mcp/.venv/bin/python -m pytest -q -p no:cacheprovider packages/travis234-websec-mcp/tests
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
The acceptance test builds actual wheels, installs through Travis's package
|
|
244
|
+
manager in a fresh interpreter outside the checkout, binds a real session, uses
|
|
245
|
+
a deterministic model stream and real HTTP/MCP transports, scans persisted
|
|
246
|
+
session JSONL, and checks A1–A13. Container qualification uses the same driver
|
|
247
|
+
with offline wheels, a nonroot user and Docker networking disabled. A build or
|
|
248
|
+
unit-test pass alone does not establish installed acceptance or deployment.
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Travis234 Websec MCP
|
|
2
|
+
|
|
3
|
+
An optional external HTTP workbench for Travis234 and standard stdio MCP clients.
|
|
4
|
+
Python 3.13 and macOS or Linux are required. Travis core and its existing MCP
|
|
5
|
+
adapter supply the host integration; this package owns requests, HTTP execution,
|
|
6
|
+
sanitization and evidence. KHackBar is a workflow reference and is not a dependency.
|
|
7
|
+
|
|
8
|
+
This milestone supports individual request experiments. Payload catalogs,
|
|
9
|
+
generators, batch fuzzing, login/token extraction and browser capture remain
|
|
10
|
+
future work. The package also includes imported assessment skills, built into
|
|
11
|
+
Travis and exposed to other clients through MCP
|
|
12
|
+
resources and prompts. These guides do not install external scanners. See the repository's
|
|
13
|
+
[complete KHackBar feature mapping](../../docs/verification/2026-10-18-khackbar-feature-crosscheck.md).
|
|
14
|
+
|
|
15
|
+
## Build, install and activate
|
|
16
|
+
|
|
17
|
+
Run these commands from the Travis234 repository root:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
uv sync --project packages/travis234-websec-mcp --locked --group source-test
|
|
21
|
+
websec_dist_dir="$(mktemp -d "${TMPDIR:-/tmp}/websec-dist.XXXXXX")"
|
|
22
|
+
uv build --wheel --out-dir "$websec_dist_dir" packages/travis234-mcp-adapter
|
|
23
|
+
uv build --wheel --out-dir "$websec_dist_dir" packages/travis234-websec-mcp
|
|
24
|
+
export PIP_FIND_LINKS="$websec_dist_dir"
|
|
25
|
+
export UV_FIND_LINKS="$websec_dist_dir"
|
|
26
|
+
websec_wheel_uri="$(packages/travis234-websec-mcp/.venv/bin/python -c 'from pathlib import Path; import sys; print(next(Path(sys.argv[1]).glob("travis234_websec_mcp-*.whl")).resolve().as_uri())' "$websec_dist_dir")"
|
|
27
|
+
travis234 install "travis234-websec-mcp @ $websec_wheel_uri"
|
|
28
|
+
travis234 --tools read,bash,websec
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Installation registers the package-owned server and one `websec` facade through
|
|
32
|
+
the shared adapter. Discovery and `status` do not send a testing request. Tool
|
|
33
|
+
selection uses the existing `--tools` allowlist; there is no new Travis flag.
|
|
34
|
+
|
|
35
|
+
For another MCP client, install the wheel and its dependencies into that client's
|
|
36
|
+
Python 3.13 environment, then configure this stdio command:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
travis234-websec-mcp mcp --transport stdio
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The standalone server does not import the Travis extension. It uses the same
|
|
43
|
+
configuration, request bounds and evidence format.
|
|
44
|
+
|
|
45
|
+
## Imported assessment skills
|
|
46
|
+
|
|
47
|
+
The source index is
|
|
48
|
+
[htooayelwinict/awesome-ai-offensive-security](https://github.com/htooayelwinict/awesome-ai-offensive-security/tree/0e3180f4a0ffd5b6703943cf112d85017895a842).
|
|
49
|
+
That repository contains links; the actual skills are imported from these
|
|
50
|
+
linked MIT-licensed projects at fixed revisions:
|
|
51
|
+
|
|
52
|
+
| Source | Included skills |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| [SnailSploit/Claude-Red](https://github.com/SnailSploit/Claude-Red/tree/a8de813edc9f66f60d44cfe42d47750e89d9930b) | `offensive-api-security`, `offensive-jwt`, `offensive-idor`, `offensive-ssrf`, `offensive-ssti`, `offensive-ai-security`, `offensive-reporting` |
|
|
55
|
+
| [transilienceai/communitytools](https://github.com/transilienceai/communitytools/tree/95fdc128af4ca1ae16b3226f9430f1bad97b0656/skills/web-app-logic) | `web-app-logic`, including its reference and scenario files |
|
|
56
|
+
|
|
57
|
+
All eight skills ship as read-only built-ins in Travis's Python and npm
|
|
58
|
+
distributions, using its existing lazy loader, precedence and trust rules.
|
|
59
|
+
Installing this optional package adds the Websec tools. When the user asks to
|
|
60
|
+
use Websec MCP, its facade instructs the agent to try loading all eight
|
|
61
|
+
SKILL.md guides before its first Websec call, like Evidence MCP's research
|
|
62
|
+
skill. This guidance also accompanies authorized delegation. User overrides
|
|
63
|
+
and `--no-skills` remain effective; unavailable guides are reported. Additional
|
|
64
|
+
reference files load only as needed. The package does not register duplicate
|
|
65
|
+
skill directories. A standalone installation exposes the same documents
|
|
66
|
+
through MCP resources and prompts. No skill is copied into the user's Codex installation.
|
|
67
|
+
|
|
68
|
+
Each imported skill has a `TRAVIS234.md` guide describing the supported tools
|
|
69
|
+
and request workflow. Local changes add compatible YAML metadata and a link to
|
|
70
|
+
that guide. Upstream methodology and references are retained. Each skill keeps
|
|
71
|
+
its upstream license; [SOURCES.json](travis234_websec_mcp/resources/skills/SOURCES.json)
|
|
72
|
+
records repository revisions, source paths, original hashes and shipped hashes.
|
|
73
|
+
Imports are bundled: startup, discovery and reads do not fetch updates or run
|
|
74
|
+
upstream code.
|
|
75
|
+
|
|
76
|
+
For a standard MCP client:
|
|
77
|
+
|
|
78
|
+
- `resources/list` enumerates skill documents in pages of eight. Pass its
|
|
79
|
+
`nextCursor` back as `cursor` until it is absent.
|
|
80
|
+
- Read `websec://skills/index` for the skill index, then a skill's
|
|
81
|
+
`websec://skills/<name>/TRAVIS234.md` and `websec://skills/<name>/SKILL.md`.
|
|
82
|
+
- A document larger than 4 KiB returns an ordered part index. Read the listed
|
|
83
|
+
`?part=1`, `?part=2`, … URIs in order. All bytes are retained, with UTF-8
|
|
84
|
+
characters kept intact. Relative references resolve within the skill's URI
|
|
85
|
+
directory. Each part is at most 4 KiB before protocol encoding. When literal
|
|
86
|
+
code examples cannot pass the existing text classifier unchanged, the read
|
|
87
|
+
uses a standard MCP blob with the same MIME type: Base64-decode it as UTF-8
|
|
88
|
+
to recover the exact text.
|
|
89
|
+
- `prompts/list` exposes eight entry prompts, named `websec-<skill-name>`.
|
|
90
|
+
`prompts/get` takes that name and no arguments; it directs the client to the
|
|
91
|
+
integration guide and relevant upstream resources.
|
|
92
|
+
|
|
93
|
+
Resource reads accept only bundled catalog URIs. Unknown URIs, prompts and
|
|
94
|
+
cursors return fixed errors. The original document is checked before any part
|
|
95
|
+
is returned, and the existing final MCP frame checks still apply. When a known
|
|
96
|
+
credential overlaps a document, its read fails without returning that document.
|
|
97
|
+
|
|
98
|
+
The existing seven request operations retain their contracts. Browser sessions,
|
|
99
|
+
raw protocol experiments, parallel probes and external tools mentioned in a
|
|
100
|
+
guide require those capabilities separately. Imported methodology does not
|
|
101
|
+
enable them in the Websec executor.
|
|
102
|
+
|
|
103
|
+
## Try the actual acceptance fixture
|
|
104
|
+
|
|
105
|
+
In one terminal, start the bundled fixture. It prints its actual loopback origin:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
packages/travis234-websec-mcp/.venv/bin/python packages/travis234-websec-mcp/tests/http_fixture.py
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Keep it running. In a second terminal, copy that origin into
|
|
112
|
+
`WEBSEC_FIXTURE_ORIGIN`, then create an isolated lab configuration:
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
export WEBSEC_FIXTURE_ORIGIN='http://127.0.0.1:<printed-port>'
|
|
116
|
+
export WEBSEC_LAB_TOKEN='synthetic-lab-token'
|
|
117
|
+
websec_lab_dir="$(mktemp -d "${TMPDIR:-/tmp}/websec-lab.XXXXXX")"
|
|
118
|
+
export TRAVIS234_CODING_AGENT_DIR="$websec_lab_dir/agent"
|
|
119
|
+
packages/travis234-websec-mcp/.venv/bin/python - <<'PY'
|
|
120
|
+
import json
|
|
121
|
+
import os
|
|
122
|
+
from pathlib import Path
|
|
123
|
+
from urllib.parse import urlsplit
|
|
124
|
+
|
|
125
|
+
origin = os.environ['WEBSEC_FIXTURE_ORIGIN']
|
|
126
|
+
assert urlsplit(origin).hostname == '127.0.0.1' and urlsplit(origin).port
|
|
127
|
+
path = Path(os.environ['TRAVIS234_CODING_AGENT_DIR']) / 'websec' / 'config.json'
|
|
128
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
129
|
+
path.write_text(json.dumps({'version': 1, 'profiles': {'lab': {
|
|
130
|
+
'origins': [origin],
|
|
131
|
+
'headers': {'Authorization': 'Bearer ${WEBSEC_LAB_TOKEN}'},
|
|
132
|
+
'deadline_seconds': 10,
|
|
133
|
+
}}}))
|
|
134
|
+
PY
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Run installation and activation in that same terminal so Travis inherits the
|
|
138
|
+
directory override and credential reference. Stop the fixture with Ctrl-C.
|
|
139
|
+
Normal operator configuration lives at `~/.travis234/agent/websec/config.json`;
|
|
140
|
+
the existing `TRAVIS234_CODING_AGENT_DIR` override changes the agent directory.
|
|
141
|
+
The package never loads `.env` files. Headers accept exact `$env:NAME` references
|
|
142
|
+
or `${NAME}` interpolation. Missing or empty references leave offline operations
|
|
143
|
+
available and make `send` return `authentication_unavailable` before connecting.
|
|
144
|
+
|
|
145
|
+
## Request workflow
|
|
146
|
+
|
|
147
|
+
Call `websec` with the following operation arguments. Replace the fixture origin
|
|
148
|
+
with its printed value and copy each returned ID exactly:
|
|
149
|
+
|
|
150
|
+
| Operation | Arguments and result |
|
|
151
|
+
| --- | --- |
|
|
152
|
+
| `status` | `{}` or `{"operation":"status"}` returns configuration, profiles and limits. |
|
|
153
|
+
| `prepare` | `{"operation":"prepare","profile":"lab","request":{"url":"<fixture-origin>/query-echo?q=original&q=untouched"}}` creates an immutable request ID. Optional request fields are `method`, header pairs and a UTF-8 `body`. |
|
|
154
|
+
| `mutate` | `{"operation":"mutate","request_id":"<original-id>","location":"query","index":0,"value":"changed"}` creates a new ID. Header mutation is also indexed; body mutation replaces the whole body. |
|
|
155
|
+
| `transform` | `{"operation":"transform","value":"a b","codec":"url","direction":"encode"}` returns `a%20b`. Codecs are `url`, `base64`, `hex`, `double_url`, `html`, `unicode` and `reverse`; both directions are supported. |
|
|
156
|
+
| `send` | `{"operation":"send","request_id":"<request-id>"}` executes that snapshot once. Send the original and changed IDs separately. |
|
|
157
|
+
| `compare` | `{"operation":"compare","left_response_id":"<original-response-id>","right_response_id":"<changed-response-id>"}` returns measured differences, completeness and an optional sanitized diff. |
|
|
158
|
+
| `export` | The same response pair with `"operation":"export"` writes a new evidence file and returns its basename, ID and byte count. |
|
|
159
|
+
|
|
160
|
+
The fixture receives `original`, then `changed`, with the second query entry
|
|
161
|
+
unchanged. Its UTF-8 response bodies have 8 and 7 bytes respectively. Reusing the
|
|
162
|
+
original ID sends the original value again. `prepare` also accepts strict raw
|
|
163
|
+
HTTP/1.1 text using `raw_request` and an explicit `origin`, instead of `request`.
|
|
164
|
+
Ambiguous framing, invalid fields and unavailable IDs return specific bounded
|
|
165
|
+
errors. Comparisons report observations rather than vulnerability verdicts.
|
|
166
|
+
|
|
167
|
+
### Additional text codecs
|
|
168
|
+
|
|
169
|
+
| Codec | Defined behavior |
|
|
170
|
+
| --- | --- |
|
|
171
|
+
| `double_url` | Apply the existing UTF-8 URL conversion exactly twice. Decoding rejects malformed percent escapes or invalid UTF-8 at either step. A literal `+` stays `+`. |
|
|
172
|
+
| `html` | Encode the five HTML special characters; the apostrophe becomes `'`. Decode named/numeric entities once using HTML5 rules. Markup stays text: decoding `<b>é</b>` returns `<b>é</b>`. |
|
|
173
|
+
| `unicode` | Encode each UTF-16 unit as a lowercase `\uXXXX` escape, including valid pairs for supplementary characters. Decode those escapes once, combine valid surrogate pairs and reject malformed or unpaired units. Other backslash sequences and percent escapes stay literal. |
|
|
174
|
+
| `reverse` | Reverse Unicode code points. Both directions perform the same operation; `A😀é` becomes `é😀A`. Combining marks reverse individually. |
|
|
175
|
+
|
|
176
|
+
These operations retain the 16 KiB input and 64 KiB output limits. The aggregate
|
|
177
|
+
MCP frame limit also applies, so a valid engine result can return `output_limit`
|
|
178
|
+
at the public boundary. Errors never return a successful partial transformation.
|
|
179
|
+
Known credentials are checked in both the source value and the derived result.
|
|
180
|
+
|
|
181
|
+
## Bounds, credentials and lifetime
|
|
182
|
+
|
|
183
|
+
Origins are exact normalized scheme/host/port allowlists. Every send checks its
|
|
184
|
+
final target. The client performs one exchange, follows no redirects, retries
|
|
185
|
+
nothing, carries no cookie jar, verifies TLS and ignores proxy environment
|
|
186
|
+
variables. Only one send runs at a time; an overlapping send returns `busy`.
|
|
187
|
+
Cancellation and shutdown close and join owned HTTP work.
|
|
188
|
+
|
|
189
|
+
| Resource | Limit |
|
|
190
|
+
| --- | --- |
|
|
191
|
+
| URL / request body / raw import | 8 / 64 / 128 KiB |
|
|
192
|
+
| Wire headers, including authentication and framing | 100 entries / 32 KiB |
|
|
193
|
+
| Transform input / output | 16 / 64 KiB |
|
|
194
|
+
| Deadline | Default 10 seconds; profile integer 1–30. A caller may only lower it with `timeout_seconds`. |
|
|
195
|
+
| Retained response / text preview | 1 MiB / 8 KiB |
|
|
196
|
+
| Requests / responses in memory | 32 / 16; unpinned oldest entries are evicted. |
|
|
197
|
+
| Complete outgoing MCP frame / exported JSON | 32 KiB / 4 MiB |
|
|
198
|
+
|
|
199
|
+
Compressed responses are reported as `unsupported_encoding` and are not decoded.
|
|
200
|
+
Binary and incomplete responses preserve honest byte measurements; comparison
|
|
201
|
+
does not infer complete text equality or an exact complete-body length from them.
|
|
202
|
+
Incomplete or oversized presentation values are withheld in full, with explicit
|
|
203
|
+
omission flags. Complete bounded JSON can retain unrelated public fields.
|
|
204
|
+
|
|
205
|
+
Keep credentials in the operator environment and profile references. Never paste
|
|
206
|
+
them into tool arguments: the host records those inputs before the plugin sees
|
|
207
|
+
them. Available referenced values and bounded URL/Base64/hex forms are sanitized
|
|
208
|
+
from returned results and exports. Authentication values go only to an allowed
|
|
209
|
+
origin's request.
|
|
210
|
+
|
|
211
|
+
Request and response IDs belong to one server process. Shutdown, reload or
|
|
212
|
+
eviction can invalidate them. Exports persist under
|
|
213
|
+
`<agent-directory>/websec/evidence/` as new atomic mode-0600 JSON files; the tool
|
|
214
|
+
does not accept arbitrary export paths or overwrite prior evidence.
|
|
215
|
+
|
|
216
|
+
Restart the entire Travis process after changing profile configuration,
|
|
217
|
+
credential references/environment or the installed package. Registrations are
|
|
218
|
+
process-local; an existing host does not replace a different descriptor in place.
|
|
219
|
+
Stop Travis before removing the package, then start a new process to confirm the
|
|
220
|
+
facade is absent. Removing the package preserves exported evidence.
|
|
221
|
+
|
|
222
|
+
## Qualification
|
|
223
|
+
|
|
224
|
+
```sh
|
|
225
|
+
PYTHONDONTWRITEBYTECODE=1 packages/travis234-websec-mcp/.venv/bin/python -m pytest -q -p no:cacheprovider packages/travis234-websec-mcp/tests
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The acceptance test builds actual wheels, installs through Travis's package
|
|
229
|
+
manager in a fresh interpreter outside the checkout, binds a real session, uses
|
|
230
|
+
a deterministic model stream and real HTTP/MCP transports, scans persisted
|
|
231
|
+
session JSONL, and checks A1–A13. Container qualification uses the same driver
|
|
232
|
+
with offline wheels, a nonroot user and Docker networking disabled. A build or
|
|
233
|
+
unit-test pass alone does not establish installed acceptance or deployment.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from importlib import import_module
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
payload_root = Path(__file__).resolve().parents[1]
|
|
6
|
+
if str(payload_root) not in sys.path:
|
|
7
|
+
sys.path.insert(0, str(payload_root))
|
|
8
|
+
|
|
9
|
+
extension = import_module("travis234_websec_mcp.extension").extension
|
|
10
|
+
|
|
11
|
+
__all__ = ["extension"]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from importlib import import_module
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
payload_root = Path(__file__).resolve().parents[2]
|
|
6
|
+
if str(payload_root) not in sys.path:
|
|
7
|
+
sys.path.insert(0, str(payload_root))
|
|
8
|
+
|
|
9
|
+
module = import_module("travis234_websec_mcp.cli")
|
|
10
|
+
raise SystemExit(module.main())
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0.3", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "travis234-websec-mcp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Independent bounded HTTP security workbench for MCP clients and Travis234."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.13,<3.14"
|
|
12
|
+
dependencies = [
|
|
13
|
+
"mcp>=2.2,<3",
|
|
14
|
+
"pydantic>=2.12,<3",
|
|
15
|
+
"httpx>=0.27,<1",
|
|
16
|
+
"httpcore>=1,<2",
|
|
17
|
+
"anyio>=4,<5",
|
|
18
|
+
"ahocorasick-rs>=1.0.3,<2",
|
|
19
|
+
"travis234-mcp-adapter>=0.4,<0.5",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.scripts]
|
|
23
|
+
travis234-websec-mcp = "travis234_websec_mcp.cli:main"
|
|
24
|
+
|
|
25
|
+
[dependency-groups]
|
|
26
|
+
source-test = ["pytest>=8", "pytest-asyncio>=1", "travis234", "travis234-evidence-mcp"]
|
|
27
|
+
|
|
28
|
+
[tool.uv.sources]
|
|
29
|
+
travis234 = { path = "../..", editable = true }
|
|
30
|
+
travis234-evidence-mcp = { path = "../travis234-evidence-mcp", editable = true }
|
|
31
|
+
travis234-mcp-adapter = { path = "../travis234-mcp-adapter", editable = true }
|
|
32
|
+
|
|
33
|
+
[tool.setuptools.packages.find]
|
|
34
|
+
where = ["."]
|
|
35
|
+
include = ["travis234_websec_mcp*"]
|
|
36
|
+
namespaces = false
|
|
37
|
+
|
|
38
|
+
[tool.setuptools.package-data]
|
|
39
|
+
travis234_websec_mcp = ["resources/skills/**/*.md", "resources/skills/**/LICENSE.txt", "resources/skills/SOURCES.json"]
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.data-files]
|
|
42
|
+
"libexec/travis234-websec-mcp" = ["libexec/travis234-websec-mcp/server.py"]
|
|
43
|
+
"extensions" = ["extensions/websec_mcp.py"]
|
|
44
|
+
|
|
45
|
+
[tool.pytest.ini_options]
|
|
46
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Acceptance uses a fresh installed host, real session, MCP child and loopback."""
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import shutil
|
|
7
|
+
import subprocess
|
|
8
|
+
|
|
9
|
+
from installed_support import REPOSITORY, installed_environment, run
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_installed_artifact_satisfies_A1_through_A13(artifacts, tmp_path):
|
|
13
|
+
source = Path(__file__).with_name("acceptance_driver.py")
|
|
14
|
+
assert source.is_file(), "Missing planned installed-artifact acceptance driver."
|
|
15
|
+
built = artifacts()
|
|
16
|
+
python, environment = installed_environment(tmp_path / "installed", built)
|
|
17
|
+
project = tmp_path / "project"
|
|
18
|
+
project.mkdir()
|
|
19
|
+
for name in (source.name, "http_fixture.py", "skill_protocol_checks.py"):
|
|
20
|
+
shutil.copyfile(Path(__file__).with_name(name), project / name)
|
|
21
|
+
revision = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=REPOSITORY, text=True).strip()
|
|
22
|
+
report_path = tmp_path / "acceptance-report.json"
|
|
23
|
+
result = run([str(python), str(project / source.name), "--wheel", str(built.websec),
|
|
24
|
+
"--repository", str(REPOSITORY), "--source-revision", revision, "--report", str(report_path)],
|
|
25
|
+
cwd=project, environ=environment)
|
|
26
|
+
assert result.stderr == ""
|
|
27
|
+
report = json.loads(result.stdout)
|
|
28
|
+
assert json.loads(report_path.read_bytes()) == report
|
|
29
|
+
expected = {"A" + str(number) for number in range(1, 14)}
|
|
30
|
+
assert expected <= report.keys()
|
|
31
|
+
assert all(report[key]["passed"] is True and report[key]["observations"] for key in expected)
|
|
32
|
+
assert report["provenance"]["wheel_sha256"] == hashlib.sha256(built.websec.read_bytes()).hexdigest()
|
|
33
|
+
assert report["provenance"]["source_revision"] == revision
|
|
34
|
+
assert report["A3"]["observations"]["pair_values"] == ["original", "changed"]
|
|
35
|
+
assert report["A4"]["observations"]["body_bytes"] == [8, 7]
|
|
36
|
+
assert report["A8"]["observations"]["disconnect_seconds"] < 2
|
|
37
|
+
assert report["A10"]["observations"]["persisted_tool_results"] > 0
|
|
38
|
+
assert report["A12"]["observations"]["remaining_children"] == 0
|
|
39
|
+
assert report["A13"]["observations"]["skill_protocol"]["documents_reassembled"] == 80
|
|
40
|
+
assert report["A13"]["observations"]["skill_protocol"]["prompts_read"] == 8
|
|
41
|
+
assert "synthetic-websec-acceptance-private-token" not in result.stdout + result.stderr
|
|
42
|
+
print("Acceptance report:", report_path)
|