1. Operation risk scoring
The baseline every call starts from, decided purely by what kind of operation it is.
| Phase | 1, static |
| Score | 0.0 - 5.0 |
| Source | crates/grith-proxy/src/filters/operation_risk.rs |
| Config | none - the table is compiled in |
The first number on every call. It looks only at the operation type, never at what the
operation touches: a read of /etc/shadow and a read of README.md both get 0.0 here, and
filters 2 and 3 are what tell them apart.
The table
| Operation | Score |
|---|---|
FileRead, DirList | 0.0 |
DirCreate | 0.2 |
FileAppend, FileRename | 0.3 |
FileWrite, FileLink, NetConnect, NetListen, DnsQuery | 0.5 |
HttpRequest - GET, HEAD, OPTIONS, DELETE | 0.5 |
HttpRequest - POST, PUT, PATCH | 1.0 |
ShellExec, ProcessSpawn, FileDelete, FileChmod | 1.0 |
FileChmod setting setuid or setgid | 5.0 |
OwnershipChange, FilesystemMutation, CrossProcessAccess, NamespaceOp | 5.0 |
DbusMethodCall the supervisor did not recognise | 5.0 |
Reads score nothing at all. That is deliberate: a read is the most common call an agent makes, and pricing it here would tax every session for nothing.
Two distinctions are worth knowing. A body-bearing HTTP method scores double a read-shaped
one, because an outbound body is the exfil-relevant shape. And a chmod that sets the setuid
or setgid bit scores 5.0 rather than 1.0 - the octal mode is inspected, so 0o4755 is priced
like chmod +s, not like a plain permission change:
$ grith proxy test '{"type":"FileChmod","path":"/home/u/projects/api/run.sh","mode":2541}'
Tool call: FileChmod(/home/u/projects/api/run.sh, 4755)
Score: 5.0
Decision: QUEUE (Medium)
Filter Breakdown:
+ operation-risk 5.0 [error] setuid/setgid permission change: /home/u/projects/api/run.sh (mode 4755)Spawn provenance
ProcessSpawn normally scores 1.0. It drops to 0.5 when the routine-provenance signal fires -
the binary was launched from a profile-declared routine root, is not outbound-capable, sits on
a path with no unsafe write permissions, and matches the hash pinned at session start.
That signal is off by default (proxy.spawn.routine_provenance_signal = false). On a
stock install every spawn takes the 1.0 baseline.
See also
- 2. Static path matching - what the operation touches
- Composite scoring