Skip to main content

jev-guard

ci license: MIT python

A static code scanner (SAST-style linter). It reads your Python source and flags insecure usage of Jev / TypeSafe "System One" models when they're used as a security guardrail.

jev-guard is not a guardrail and it does not run at runtime, call the model, or touch the network. It is a build-time analysis tool — think ruff/bandit, scoped to Jev guardrail patterns. It tells you where your guardrail code is misconfigured; it does not do any guarding itself.

Thesis: type-safe is not the same as correct. Jev can't emit a type error and it can't hallucinate a field — but "no hallucination" is a guarantee about shape, not about truth. A guardrail that returns a confidently wrong noul: 0.02 for a rm -rf / still lets the call through. If you gate bash on that number, the type safety bought you nothing.

jev-guard scans your code for the ways a Jev-based guardrail fails open. It runs entirely offline — it reads your source, not the model — so it needs no API key and costs nothing.

Why this exists

Two things shipped in September 2026:

  • TypeSafe released Jev, marketed for "score, judge, verify, guardrail, and detect jailbreaks."
  • LangChain shipped AutoModeMiddleware, which uses Jev to classify tool calls as dangerous and block them before they run — the classifier pattern that used to live inside the closed-source parts of Claude Code / Codex / Cursor, now open to every agent.

The documented example is literally AutoModeMiddleware(tools=["bash"]) — a shell gate with no threshold set, relying on the model's default point decision. That is the exact shape jev-guard was built to catch.

Install

pip install jevg           # PyPI package name (the CLI command is still `jev-guard`)
# or, from source:
git clone https://github.com/ppradyoth/jev-guard && cd jev-guard
pip install -e .

Use

jev-guard scan path/to/agent.py        # scan a file
jev-guard scan src/                     # scan a tree
jev-guard scan src/ --format json       # machine-readable
jev-guard scan src/ --fail-on HIGH      # CI gate (default): exit 1 on HIGH+
jev-guard rules                         # list what it checks

Exit code is non-zero when any finding is at or above --fail-on, so it drops straight into CI:

- run: jev-guard scan src/ --fail-on HIGH

In CI (GitHub Action)

- uses: ppradyoth/jev-guard@v0.3.0
  with:
    path: src/
    fail-on: HIGH

Surface findings in the Security tab by emitting SARIF and uploading it — see examples/github-workflow.yml.

Pre-commit

repos:
  - repo: https://github.com/ppradyoth/jev-guard
    rev: v0.3.0
    hooks:
      - id: jev-guard

What it flags

Code Severity What
JG001 HIGH Jev guardrail gates actions with no configured confidence threshold (blocks on the model default).
JG002 CRITICAL A dangerous tool (bash/sql/http/...) is wired into an agent with no AutoModeMiddleware present.
JG003 MEDIUM A .noul/.choice/.score decision is used to branch without ever reading a confidence field.
JG004 MEDIUM Attacker-influenceable content flows straight into a guardrail's state (injection surface).
JG005 INFO Jev is being used as a security control — reminder to validate thresholds against your own adversarial data.
JG006 MEDIUM Threshold set in an unsafe band (blocks only near-certain danger / almost never escalates).
JG007 HIGH Untrusted content interpolated into a question's instructions — the inspected text can rewrite the question.

Full rationale and remediation for each: GUIDE.md.

Example

$ jev-guard scan examples/vulnerable_agent.py
examples/vulnerable_agent.py:5  [HIGH] JG001  Jev guardrail gates actions with no configured confidence threshold
    ↳ Set an explicit threshold and escalate below it.
examples/vulnerable_agent.py:11 [MEDIUM] JG004  Untrusted content flows into a Jev guardrail's state
    ↳ Separate and sanitize untrusted state.
...

Configuration

Drop a .jev-guard.toml at your repo root (jev-guard walks up to find it):

[jev-guard]
disable = ["JG005"]            # rules to silence entirely

[jev-guard.severity]
JG004 = "HIGH"                 # bump a rule's severity

[jev-guard.extra]
dangerous_tools = ["wire_transfer", "post_tweet"]   # your own high-impact tools
import_roots    = ["my_typesafe_wrapper"]           # if you wrap the SDK
guardrail_calls = ["MyGuardrail"]                   # your own guardrail factory

Silence a single line inline:

guardrail = AutoModeMiddleware(tools=["bash"])  # jev-guard: ignore JG001
another = AutoModeMiddleware(tools=["bash"])     # jev-guard: ignore

jev-guard follows assignments, so indirection is caught — tools = ["bash"]; create_agent(tools=tools) and s = user_msg; classifier.invoke({"state": s}) both flag.

Scope and honesty

This is a heuristic linter, not a prover. It reads Python, matches the LangChain langchain_typesafe surface, and reasons about obvious patterns. It will miss guardrails assembled dynamically, wrapped in your own abstractions, or written in another language, and it can raise false positives on safe code that names a variable user_config. It does not test the model, measure real calibration, or prove exploitability. It tells you where to look, not that you're owned.

For what it can and can't do, and when to reach for something else, read GUIDE.md.

License

MIT. Not affiliated with TypeSafe AI or LangChain.

Metadata

Release files for jevg 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jevg 0.3.0
File Size Uploaded
jevg-0.3.0.tar.gz 20.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jevg 0.3.0
File Interpreter ABI Platform
jevg-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 34.0 kB

Release files / jevg-0.3.0.tar.gz

Download URL jevg-0.3.0.tar.gz
Size 20.2 kB
Tags Source
SHA-256 checksum
How to use checksums
6fcc8336e16a212dad599254d6608a62688cd3477119ea661df6cf25f73f15b8
BLAKE2b-256 checksum
How to use checksums
2ab0a4144924bc8e5f2961861a7dccee230fd0b1a40d41a00fb97596d34434ab
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 Sep 21, 2026.

Transparency log

Release files / jevg-0.3.0-py3-none-any.whl

Download URL jevg-0.3.0-py3-none-any.whl
Size 13.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
113f7db93e3bbdcdfc8d10f44aea61ee8bcc5eb02ea75cbe5afe931440f11cec
BLAKE2b-256 checksum
How to use checksums
7b31aabdff36e8e30613519cd492db08dd41315ddf869589d5648df24873efbd
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 Sep 21, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

This release

0.3.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page