grithdocs

grith proxy test

Dry-run a tool call through all 18 filters and see the decision, the score and every contribution.

grith proxy test '<CALL>'

Runs one JSON tool call through the full filter pipeline and prints what would happen. Nothing is executed and nothing is recorded. It is the fastest way to answer "would grith stop this".

Exit codes: 0 allow, 1 queue, 2 deny. That makes it usable as a policy assertion in a script.

An allow

terminal
$ grith proxy test '{"type":"FileRead","path":"/etc/passwd"}'

Proxy Test Result
==================================================
Tool call:   FileRead(/etc/passwd)
Score:       2.8
Decision:    ALLOW
Reason:      Score 2.8 below allow threshold
Eval time:   1.35ms
Thresholds:  allow < 3, deny > 8
Filters:     18 active

Filter Breakdown:
  . operation-risk         0.0
  . path-match             0.0
  + sensitive-path-heuristic   2.8  [warning]  read access to sensitive-looking filename
  . allowlist              0.0
  . argument               0.0
  . capability             0.0
  . secret-scan            0.0
  . command                0.0
  . destructive-action     0.0
  . egress-policy          0.0
  . dlp-gate               0.0
  . canary                 0.0
  . reputation             0.0
  . behavioural            0.0
  . taint                  0.0
  . session-containment    0.0
  . rate-limit             0.0
  . egress-rate            0.0

Exit code:   0 (allow)

That is the registration order of all 18 filters. + marks a filter that contributed; . marks one that ran and scored zero.

A queue

terminal
$ grith proxy test '{"type":"ShellExec","command":"curl","args":["https://evil.example.com"]}'

Proxy Test Result
==================================================
Tool call:   ShellExec(curl https://evil.example.com)
Score:       4.5
Decision:    QUEUE (Medium)
Reason:      Score 4.5 in escalation zone
Eval time:   3.07ms
Thresholds:  allow < 3, deny > 8
Filters:     18 active

Filter Breakdown:
  + operation-risk         1.0  [notice]  Shell execution: curl https://evil.example.com
  . path-match             0.0
  . sensitive-path-heuristic   0.0
  . allowlist              0.0
  . argument               0.0
  . capability             0.0
  . secret-scan            0.0
  . command                0.0
  . destructive-action     0.0
  + egress-policy          3.5  [warning]  Review outbound command token: curl
  . dlp-gate               0.0
  . canary                 0.0
  . reputation             0.0
  . behavioural            0.0
  . taint                  0.0
  . session-containment    0.0
  . rate-limit             0.0
  . egress-rate            0.0

Exit code:   1 (queue (medium))

Two filters contributed 1.0 and 3.5, the sum landed between the thresholds, and the call would be held for review. All 18 still ran.

A deny, and why it is short

terminal
$ grith proxy test '{"type":"FileRead","path":"/home/u/.ssh/id_rsa"}'

Tool call:   FileRead(/home/u/.ssh/id_rsa)
Score:       9.0
Decision:    DENY
Reason:      Access to SSH private key; read access to key/certificate file
Eval time:   0.03ms
Thresholds:  allow < 3, deny > 8
Filters:     18 active

Filter Breakdown:
  . operation-risk         0.0
  + path-match             5.0  [critical]  Access to SSH private key
  + sensitive-path-heuristic   4.0  [error]  read access to key/certificate file
  . allowlist              0.0
  . argument               0.0
  . capability             0.0

Exit code:   2 (deny)

Six lines under an 18 active header is correct. A deny reached at the end of a phase returns immediately - the later phases and the meta-rules never run.

Call shapes

The type field is one of 20 variants:

FileRead · FileWrite · FileAppend · FileDelete · DirList · DirCreate · FileRename · FileLink · FileChmod · ShellExec · ProcessSpawn · HttpRequest · NetConnect · NetListen · DnsQuery · OwnershipChange · FilesystemMutation · CrossProcessAccess · NamespaceOp · DbusMethodCall

The command's own error hint lists only 13 of them. The four shapes that catch people out:

TypeRequired fields
FileRead, DirList, FileDeletepath
ShellExec, ProcessSpawncommand and args as an array
HttpRequestmethod and url
FileWritepath and content_hash

A bad payload fails before any filter runs:

terminal
$ grith proxy test 'not json'
Error: Invalid JSON: expected ident at line 1 column 2
Expected format: {"type": "FileRead", "path": "/etc/passwd"}

See also

Last updated: 2026-08-24Edit this page on GitHub →