PermitProbe
Open-source defensive security CLI for testing API authorization, response-data boundaries, and AI handoff exposure.
Maintainer: @Chorolee
Security Maintainer: @Chorolee
Security maintenance: vulnerability triage, security releases, and coordinated disclosure.
License: Apache-2.0 · Current release: v0.1.1
PermitProbe helps service operators validate:
- cross-user authorization boundaries
- unexpected API response fields
- secrets included in AI handoff files
It is designed exclusively for systems the operator owns or is authorized to test.
PermitProbe was developed from recurring defensive security checks used while operating data-backed production services.
PermitProbe is an early open-source CLI for small teams running data-backed services. It turns an explicit policy into repeatable checks and a local, machine-readable report. It reuses Overstep for authorization planning and classification, JSON Schema for response contracts, and Gitleaks for secret detection.
Version 0.1.1 supports GET-only JSON REST APIs and explicit UTF-8 text-file handoffs on Linux/macOS. A passing result applies only to the declared cases and scanned bytes.
Try the working demo
PyPI publication is being configured. Until an upload is verified, install from this repository or its GitHub Release files. Maintainers can follow the Trusted Publishing setup.
The project was renamed from BoundaryGuard in v0.1.1 because the PyPI package
boundaryguard belongs to an unrelated project. The historical v0.1.0 release
remains unchanged.
Python 3.11+ is required. From this repository:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -c requirements.lock -e '.[dev]'
python scripts/install_gitleaks.py
permitprobe demo --scenario safe --gitleaks .tools/gitleaks
permitprobe demo --scenario leaky --gitleaks .tools/gitleaks
permitprobe demo --scenario expired --gitleaks .tools/gitleaks
The demos start an ephemeral server on literal loopback and use synthetic credentials and documents. They do not contact an application or a database.
| Scenario | Expected exit | What it demonstrates |
|---|---|---|
safe |
0 |
Both users can read their own document; cross-owner reads are denied; fields and handoff match policy |
leaky |
1 |
Cross-owner access, an extra private response field, and a synthetic token in a handoff are detected |
schema-leak |
1 |
Authorization can be correct while the response exposes an extra field |
expired |
2 |
One user's working credential cannot hide another user's failed positive control |
server-error |
2 |
A server error on a negative test is not evidence that authorization worked |
Exit 1 and 2 in the last examples are intentional. No response bodies, token values,
file contents, or raw scanner diagnostics are included in PermitProbe reports.
Check your own staging API
permitprobe init my-security-checks
Edit my-security-checks/permitprobe.json:
- Set the HTTPS origin of a target you operate. HTTP is accepted only for literal loopback.
- Name one anonymous identity and at least two authenticated identities with distinct objects.
- Point
token_envat environment variables containing the corresponding bearer tokens. PermitProbe does not read dotenv files, create users, or obtain credentials. - Declare each resource's allowed roles and
own/anyscope. - For object resources, name the URL parameter, identity attribute, and JSON pointer that proves a successful response actually returned the intended object.
- Set
response_schemaanddenial_schemafor successful and refused responses. Close objects withadditionalProperties: false, including nested objects, when all undeclared fields must be forbidden. The starter also constrains denial error values. - Select only the text files intended for an AI handoff. Paths are relative to
handoff.root, itself relative to the policy file. They are never inferred from the whole repository.
After supplying the token variables through your normal local credential mechanism:
permitprobe check my-security-checks/permitprobe.json \
--gitleaks .tools/gitleaks --report result.json
The starter origin is a non-working example.invalid placeholder. A missing token,
unreachable target, unsupported response, failed control, or missing scanner exits 2.
Reports and exports are created exclusively; existing files are not overwritten.
Use permitprobe schema to print the policy's JSON Schema. Unknown policy keys,
duplicate JSON keys, reused object IDs, and reused token references are rejected.
examples/permitprobe.json is a complete configuration with synthetic placeholders.
Check and package an AI handoff
permitprobe bundle my-security-checks/permitprobe.json \
--gitleaks .tools/gitleaks --output reviewed-handoff.zip
bundle checks the handoff surface only and makes no API requests. Its report states
that API/data surfaces were not checked. It captures each named file, checks the captured
bytes with Gitleaks, and only emits a ZIP when all handoff checks pass. The ZIP contains a
SHA256 manifest and those exact bytes, even if source files change afterward. Nothing is
uploaded or sent to an agent. Send the checked archive, not a re-read of the original tree.
The built-in boundary refuses dotenv files, private-key files, credential directories,
Git/private-memory directories, symlinks, hard links, non-regular files, binary content,
path traversal, and configured size overruns. User deny patterns win over allow patterns;
neither can override the built-in exclusions. Glob patterns match the whole POSIX path,
and * can cross directory separators. Include specific files rather than a broad *.
Scanner configuration and inline gitleaks:allow comments in a payload cannot suppress
the scan. Gitleaks runs with a small explicit environment, without inherited credentials
or configuration overrides. It receives neutral filenames and private temporary files.
These controls are a preflight check, not a sandbox for a malicious scanner executable.
What is reused, and what PermitProbe adds
| Component | Responsibility |
|---|---|
| Overstep 1.5.0 | Generate identity/resource cases and classify unexpected access, including cross-owner access |
JSON Schema / jsonschema |
Validate nested JSON response contracts |
| Gitleaks 8.30.1 | Detect known secret patterns in captured handoff text |
| PermitProbe | Strict configuration, bounded GET transport, per-identity positive controls, object identity checks, success and denial response contracts, explicit file boundaries, checked-byte bundles, and one privacy-conscious report |
The Gitleaks installer pins the release and archive hashes. requirements.lock records
the tested Python dependency versions. Engine updates must pass the regression fixtures.
No code from a source-available-only security product is embedded here.
An auth-only matrix can be exported for direct use with Overstep:
permitprobe export-overstep my-security-checks/permitprobe.json --output matrix.json
The output is JSON, also valid YAML for Overstep, and retains ${TOKEN_ENV} references.
It does not include PermitProbe's JSON Schema checks, strict control rules, or
handoff checks. Direct Overstep execution has its own behavior and scope.
Exit codes and evidence
| Exit | Meaning |
|---|---|
0 |
Every configured check completed and passed |
1 |
At least one policy violation; no incomplete checks |
2 |
Configuration error or incomplete evidence; failures may also be present |
--format json prints the versioned report. --report path.json additionally creates
a local report file. Unconfigured surfaces are named explicitly. An empty run cannot pass.
Responses are consumed only in memory and capped in size/time. Proxy environment variables,
redirects, automatic login, fixture mutations, and shared cross-identity cookie jars are not used.
Scope and limitations
- Only declared GET cases are tested. This is not a full application security audit.
- A forbidden
2xxresponse is an access-policy violation; content markers can strengthen evidence, but a status code alone does not prove a particular secret was disclosed. - The owner must supply the intended policy, real test identities, and existing test objects. A wrong policy or overly permissive JSON Schema can produce misleading conclusions.
- JSON Schemas are inline Draft 2020-12; reference resolution and format enforcement are not supported. Denial responses must also be valid JSON matching their declared schema.
- These are API observations, not a proof of database grants, RLS, storage, GraphQL, caching, or write-path correctness. The tool never connects to a database in v0.1.
- Handoff scanning covers selected UTF-8 text only. It is not complete PII classification, archive scanning, prompt-injection prevention, continuous DLP, or runtime egress enforcement.
- Policy files, schemas, the installed dependencies, and the chosen scanner executable are trusted. Reports retain configured labels and filenames; do not put secrets in those names.
- GET handlers must actually be safe to call. Choose a staging target with synthetic fixtures.
Development
python -m pytest -q
ruff check src tests scripts
python -m build
Tests use real loopback HTTP and the installed Gitleaks binary. Missing Gitleaks fails the
suite rather than silently skipping secret-detection tests. Set PERMITPROBE_GITLEAKS
to an absolute binary path when it is not at .tools/gitleaks.
What expanding verification means
This means adding security checks that users can apply to their services, separately from adding unit tests for PermitProbe itself. The present regression suite tests the tool against synthetic safe, vulnerable, and inconclusive cases; it does not audit a deployed application automatically.
| Planned capability | Concrete question it would test |
|---|---|
| Database adapter (Supabase/pgTAP) | Can one authenticated user directly read another user's private row, even if the HTTP API denies it? |
| Linked API/storage cases | Does a document denied by its API remain readable through a direct object URL or another declared route? |
| Write authorization cases | Can a user modify or delete another user's seeded test record? Run against disposable test data with explicit write-test scope. |
| MCP adapter | Can an agent identity invoke a tool or name a resource outside its declared permissions? |
| Finding history and retests | Is a previously reproduced defect still present after a change, with valid credentials and a working positive control? |
These are not implemented in v0.1. Each addition needs a known-vulnerable fixture, a fixed counterpart, and an incomplete-evidence case that must not pass.
Design reference: ARTEX
ARTEX is an AI-driven penetration-testing system. Reference review: revision b55ceb1. Its documented asset/exploration graphs distinguish targets from investigation progress; its finding retests retain prior evidence and separate reproduced, fixed, and inconclusive outcomes. See its architecture, retest model, and evidence store.
The proposed PermitProbe adaptation is a scoped workflow: inventory declared surfaces, identify a candidate, reproduce it with an executable check, retain safe evidence metadata, then rerun the same case after a fix. A future AI-assisted discovery layer would produce candidates; configured executable checks would decide the result. Any coverage view must keep untested surfaces visible. Response bodies and credentials would remain excluded from ordinary reports under this project's existing data-handling contract.
ARTEX's reviewed source is AGPL-3.0. It is a conceptual reference, not an installed dependency or an imported implementation. No ARTEX code, prompts, screenshots, or other assets are copied into PermitProbe. This reference review does not claim to have run or audited ARTEX.
Apache-2.0. See NOTICE, CONTRIBUTING.md, and SECURITY.md.
Metadata
Release files for permitprobe 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| permitprobe-0.1.1.tar.gz | 41.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| permitprobe-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 69.3 kB
Release files / permitprobe-0.1.1.tar.gz
| Download URL | permitprobe-0.1.1.tar.gz |
|---|---|
| Size | 41.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
752b62fe33837b30fa23d396298988a322352b99339dd7818c6c17a21c2aeec2
|
|
BLAKE2b-256 checksum How to use checksums |
f436d7397a651ba0f14b084d6f2275bc5ab7b7b5afcb4dc65291181d15a1959d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency logRelease files / permitprobe-0.1.1-py3-none-any.whl
| Download URL | permitprobe-0.1.1-py3-none-any.whl |
|---|---|
| Size | 27.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ca1b57ce05234c1dd1b55cd6f1004465114da6d5b3a66bf0963e60280e98f546
|
|
BLAKE2b-256 checksum How to use checksums |
8c6fadef182c8c09354acdf9ef973edc53bc679d7f439a76a46c1f14744965f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency log