botgate 0.1.0__py3-none-win_amd64.whl
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.
|
Binary file
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: botgate
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Environment :: Console
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Programming Language :: Rust
|
|
8
|
+
Classifier: Topic :: Security
|
|
9
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
10
|
+
License-File: LICENSE-MIT
|
|
11
|
+
Summary: Evidence-first Web Bot Auth conformance and coverage analyzer
|
|
12
|
+
Keywords: web-bot-auth,http-signatures,rfc9421,security
|
|
13
|
+
Home-Page: https://github.com/kraftaa/botgate
|
|
14
|
+
License-Expression: MIT
|
|
15
|
+
Requires-Python: >=3.8
|
|
16
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
17
|
+
Project-URL: Homepage, https://github.com/kraftaa/botgate
|
|
18
|
+
Project-URL: Issues, https://github.com/kraftaa/botgate/issues
|
|
19
|
+
Project-URL: Repository, https://github.com/kraftaa/botgate
|
|
20
|
+
|
|
21
|
+
# Botgate
|
|
22
|
+
|
|
23
|
+
Botgate is an evidence-first conformance and coverage analyzer for Web Bot Auth and RFC 9421 HTTP Message Signatures.
|
|
24
|
+
|
|
25
|
+
It answers four separate questions:
|
|
26
|
+
|
|
27
|
+
1. Is the message shaped correctly for a selected protocol profile?
|
|
28
|
+
2. Does the signature verify with an explicitly supplied key?
|
|
29
|
+
3. Which request properties are cryptographically bound?
|
|
30
|
+
4. Does that coverage satisfy the application's declared policy?
|
|
31
|
+
|
|
32
|
+
Botgate deliberately does **not** infer authentication from an HTTP status code. A `200` response is not evidence that a server accepted a signature; the resource may simply be public.
|
|
33
|
+
|
|
34
|
+
## Status
|
|
35
|
+
|
|
36
|
+
This repository implements a focused v0.1:
|
|
37
|
+
|
|
38
|
+
- current `draft-ietf-webbotauth-httpsig-protocol-00` inspection;
|
|
39
|
+
- the current Cloudflare compatibility profile;
|
|
40
|
+
- current dictionary-form and legacy string-form `Signature-Agent` handling;
|
|
41
|
+
- RFC 9421 signature-base reconstruction for the common request components;
|
|
42
|
+
- RFC 8941 canonicalization for selected Structured Field dictionary members;
|
|
43
|
+
- Ed25519 signing and verification;
|
|
44
|
+
- JWK thumbprint/key selection;
|
|
45
|
+
- semantic coverage and configurable policy evaluation;
|
|
46
|
+
- `Content-Digest` SHA-256 validation;
|
|
47
|
+
- JSON output for CI;
|
|
48
|
+
- a safe offline mutation matrix.
|
|
49
|
+
|
|
50
|
+
It does not fetch untrusted key-directory URLs or send active mutations. Those operations require an SSRF-safe resolver and an explicit authentication oracle; pretending that response status alone is an oracle would produce misleading results.
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
You do not need Rust or Cargo to use Botgate.
|
|
55
|
+
|
|
56
|
+
On macOS or Linux, install with Homebrew:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
brew install kraftaa/tap/botgate
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If you already use Python tooling, install the same native Botgate binary on
|
|
63
|
+
macOS, Linux, or Windows with `pipx`:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
pipx install botgate
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Or with `uv`:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
uv tool install botgate
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Inside an existing Python virtual environment, ordinary pip works too:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
python -m pip install botgate
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
These package-manager installs use prebuilt native binaries; they do not
|
|
82
|
+
compile Botgate or install a Rust toolchain. Standalone archives, a Windows
|
|
83
|
+
installer, a shell installer, and SHA-256 checksums are also available on the
|
|
84
|
+
[Releases page](https://github.com/kraftaa/botgate/releases) as fallbacks.
|
|
85
|
+
|
|
86
|
+
The download links become active when the first public release is published.
|
|
87
|
+
Until then, authenticated repository collaborators can download private release
|
|
88
|
+
assets with the GitHub CLI.
|
|
89
|
+
|
|
90
|
+
Confirm the installation:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
botgate --version
|
|
94
|
+
botgate --help
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## End-to-end example
|
|
98
|
+
|
|
99
|
+
Generate a test key and policy:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
botgate init
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
This creates:
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
.botgate/
|
|
109
|
+
├── private.key # Ed25519 PKCS#8, mode 0600 on Unix
|
|
110
|
+
├── public.jwk
|
|
111
|
+
├── directory.json
|
|
112
|
+
└── botgate.toml
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The whole `.botgate/` directory is excluded by `.gitignore`. Botgate never prints the private key. A conformant remote key directory must be served over HTTPS.
|
|
116
|
+
|
|
117
|
+
Running `botgate init --force` regenerates `public.jwk` and `directory.json` from the existing private key. It never overwrites `private.key` or an existing `botgate.toml`.
|
|
118
|
+
|
|
119
|
+
On Unix, the private key is created atomically with mode `0600`. On Windows it is created with `create_new` but inherits the directory's ACL; restrict access to `.botgate/` yourself.
|
|
120
|
+
|
|
121
|
+
Sign the example request using the current IETF form:
|
|
122
|
+
|
|
123
|
+
```sh
|
|
124
|
+
botgate sign examples/request.http \
|
|
125
|
+
--agent https://agent.example \
|
|
126
|
+
--components @authority,@method,@path,@query \
|
|
127
|
+
--output signed-request.http
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Inspect declared coverage without loading a key:
|
|
131
|
+
|
|
132
|
+
```sh
|
|
133
|
+
botgate inspect signed-request.http \
|
|
134
|
+
--config examples/strict-policy.toml
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Verify cryptographically using a local JWKS:
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
botgate verify signed-request.http \
|
|
141
|
+
--jwks .botgate/directory.json \
|
|
142
|
+
--config examples/strict-policy.toml
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Show the offline mutation matrix:
|
|
146
|
+
|
|
147
|
+
```sh
|
|
148
|
+
botgate test signed-request.http \
|
|
149
|
+
--jwks .botgate/directory.json \
|
|
150
|
+
--config examples/strict-policy.toml
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Nothing is sent by `test`. In particular, Botgate never turns a `GET` into a live `POST` or `DELETE` request.
|
|
154
|
+
The matrix is generated independently for every signature in the request.
|
|
155
|
+
|
|
156
|
+
## Cloudflare interoperability
|
|
157
|
+
|
|
158
|
+
The September 2026 working-group draft requires new senders to emit dictionary-form `Signature-Agent`, keyed by the signature label:
|
|
159
|
+
|
|
160
|
+
```http
|
|
161
|
+
Signature-Agent: sig1="https://agent.example"
|
|
162
|
+
Signature-Input: sig1=("@authority" "signature-agent";key="sig1");...
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Cloudflare currently documents the older bare-string form. Generate and analyze that form explicitly:
|
|
166
|
+
|
|
167
|
+
```sh
|
|
168
|
+
botgate sign examples/request.http \
|
|
169
|
+
--agent https://agent.example \
|
|
170
|
+
--components @authority \
|
|
171
|
+
--legacy-agent \
|
|
172
|
+
--output cloudflare-request.http
|
|
173
|
+
|
|
174
|
+
botgate inspect cloudflare-request.http --profile cloudflare
|
|
175
|
+
botgate inspect cloudflare-request.http --profile ietf-draft-00
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The second command reports why the same request is legacy rather than conformant for a new IETF-draft sender.
|
|
179
|
+
|
|
180
|
+
## Policy
|
|
181
|
+
|
|
182
|
+
Policy requirements are application requirements, not claims that every conforming Web Bot Auth signature must cover the same fields.
|
|
183
|
+
Without `--config`, Botgate automatically loads `.botgate/botgate.toml` from the current directory when it exists; otherwise it uses the same built-in defaults produced by `init`. Every report names the policy it applied (`Policy:` in text, `policy_source` in JSON). In CI, pass `--config` explicitly so a change to `.botgate/` cannot silently alter the gate. Unknown keys and negative time limits are rejected.
|
|
184
|
+
|
|
185
|
+
```toml
|
|
186
|
+
[policy]
|
|
187
|
+
require_authority = true
|
|
188
|
+
require_method = true
|
|
189
|
+
require_path = true
|
|
190
|
+
query = "required"
|
|
191
|
+
body = "ignore"
|
|
192
|
+
max_age_seconds = 300
|
|
193
|
+
max_lifetime_seconds = 300
|
|
194
|
+
allowed_future_skew_seconds = 30
|
|
195
|
+
require_nonce = false
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Coverage is semantic rather than a flat string check. For example, `@target-uri` satisfies authority, path, and query coverage, while `@path` does not cover the query. Body integrity requires a covered `Content-Digest` (the whole field, or its `sha-256` member via `;key="sha-256"`) whose SHA-256 value matches the body bytes. Covering only another member, such as `sha-512`, does not count.
|
|
199
|
+
Individual `@query-param` components are reported as partial evidence and do not satisfy a policy requiring the entire query to be bound. `@request-target` covers path and query for the raw HTTP/1.1 requests accepted by v0.1.
|
|
200
|
+
|
|
201
|
+
## JSON and exit behavior
|
|
202
|
+
|
|
203
|
+
Use `--format json` with `inspect`, `verify`, or `test`.
|
|
204
|
+
|
|
205
|
+
```sh
|
|
206
|
+
botgate inspect request.http --format json
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Exit status is `0` when no error-level findings exist, `1` when conformance, compatibility, crypto, or policy findings fail, and `4` for input or configuration errors detected after argument parsing. Clap uses its conventional status `2` for command-line usage errors. JSON retains independent finding categories and cryptographic/identity states so CI does not need to infer meaning from prose.
|
|
210
|
+
|
|
211
|
+
## Trust model
|
|
212
|
+
|
|
213
|
+
Verification with `--jwks` establishes that the supplied key validates the signature. It intentionally reports identity as `key_only`: loading a local JWK does not prove that an HTTPS `Signature-Agent` URL published that key. URL attribution requires a safe HTTPS discovery operation and its cache state.
|
|
214
|
+
|
|
215
|
+
The signing command derives the thumbprint from the private key and refuses to proceed if `--jwk` names a different key pair.
|
|
216
|
+
|
|
217
|
+
Similarly, signing `Content-Digest` binds the digest header. Botgate separately recomputes the digest before reporting body integrity.
|
|
218
|
+
|
|
219
|
+
## Supported signature components
|
|
220
|
+
|
|
221
|
+
v0.1 reconstructs:
|
|
222
|
+
|
|
223
|
+
- `@method`
|
|
224
|
+
- `@authority`
|
|
225
|
+
- `@scheme`
|
|
226
|
+
- `@path`
|
|
227
|
+
- `@query`
|
|
228
|
+
- `@target-uri`
|
|
229
|
+
- `@request-target`
|
|
230
|
+
- `@query-param`;`name=...`
|
|
231
|
+
- ordinary HTTP fields
|
|
232
|
+
- dictionary field members selected with `;key=...`
|
|
233
|
+
|
|
234
|
+
Unsupported derived components cause verification to fail explicitly rather than being guessed.
|
|
235
|
+
Input files use a strict raw HTTP/1.0 or HTTP/1.1 request format; malformed control data, folded headers, and ambiguous authorities are rejected before analysis.
|
|
236
|
+
|
|
237
|
+
## Non-goals
|
|
238
|
+
|
|
239
|
+
Botgate does not impersonate commercial agents, bypass bot protection, solve CAPTCHAs, crawl sites, score “AI readiness,” or replace authorization and bot-management systems.
|
|
240
|
+
|
|
241
|
+
## Development
|
|
242
|
+
|
|
243
|
+
Rust and Cargo are required only when building Botgate from source or
|
|
244
|
+
contributing to the project:
|
|
245
|
+
|
|
246
|
+
```sh
|
|
247
|
+
cargo build --release
|
|
248
|
+
cargo fmt --check
|
|
249
|
+
cargo clippy --all-targets -- -D warnings
|
|
250
|
+
cargo test
|
|
251
|
+
cargo deny check
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
The minimum supported Rust version is 1.86. CI runs the test suite on Linux, macOS, and Windows.
|
|
255
|
+
|
|
256
|
+
`cargo test` includes property tests for the HTTP and Structured Fields parsers. Coverage-guided fuzz targets live in `fuzz/` and need a nightly toolchain and [`cargo-fuzz`](https://github.com/rust-fuzz/cargo-fuzz):
|
|
257
|
+
|
|
258
|
+
```sh
|
|
259
|
+
cargo install cargo-fuzz
|
|
260
|
+
cargo +nightly fuzz run parse_request
|
|
261
|
+
cargo +nightly fuzz run parse_signatures
|
|
262
|
+
cargo +nightly fuzz run signature_base
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
See [SECURITY.md](SECURITY.md) for the trust model and how to report vulnerabilities.
|
|
266
|
+
Maintainer release setup is documented in [RELEASING.md](RELEASING.md).
|
|
267
|
+
|
|
268
|
+
The protocol is still an Internet-Draft. Profile-specific behavior is kept separate in the report engine, and `botgate protocol` identifies the implemented draft.
|
|
269
|
+
|
|
270
|
+
## References
|
|
271
|
+
|
|
272
|
+
- [Web Bot Auth working-group draft 00](https://datatracker.ietf.org/doc/html/draft-ietf-webbotauth-httpsig-protocol-00)
|
|
273
|
+
- [RFC 9421: HTTP Message Signatures](https://www.rfc-editor.org/rfc/rfc9421.html)
|
|
274
|
+
- [Cloudflare Web Bot Auth documentation](https://developers.cloudflare.com/bots/reference/bot-verification/web-bot-auth/)
|
|
275
|
+
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
botgate-0.1.0.data\scripts\botgate.exe,sha256=QtfXmQY8RPk1US7FG_QQF-x8I8svcXQdfGnvxs5XSzY,2099712
|
|
2
|
+
botgate-0.1.0.dist-info\METADATA,sha256=g98PpOgiN_fKTkLtaFB_entH7yOq7MMc-WzQfN-Gitc,10570
|
|
3
|
+
botgate-0.1.0.dist-info\WHEEL,sha256=jsSEiVNsW1dJj5gDaReR40i7mhgBjWtms6nAD6EViXU,94
|
|
4
|
+
botgate-0.1.0.dist-info\licenses\LICENSE-MIT,sha256=94n4rBNhaAsDzk3LlfShpE9TJvQiSIdCO30ZdGPTmU8,1102
|
|
5
|
+
botgate-0.1.0.dist-info\RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 The botgate contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|