Problem
Hawk-hosted investigations and every child job they launch run on the launching user's Hawk identity. Code in those runners (the audited benchmark's code today, agent-edited eval code once that lands) sits next to a token that can do anything that user can: for an admin that includes Middleman model and provider-key management, and stopping or deleting any job. The agent itself never holds the token, but the code it runs does. Investigation jobs also count against the operator's own job quota (Hawk 3.6 caps outstanding runner jobs per user at 128).
Want
Each investigation gets its own short-lived, least-privilege identity, derived from the user who launched it: only the models on its worker menu, only the eval sets it creates and the log sources it was given, no admin, and credentials that expire. Children inherit a narrower version of the same.
Upstream (METR/hawk)
Our deployment is on Hawk server 3.5.0; METR has released 3.7.0, so adopting any of these also needs a redeploy.
Interim
- A dedicated non-admin Hawk user for investigations (model access only), launched with its own login.
- A dedicated OpenRouter key with a credit cap for direct-mode child jobs.
- Keep the investigator's child submission behind one adapter (
_jobs.Hawk.submit, which today reads the runner hook's refresh token from private state) so switching to workload credentials is one change.
Done when
An investigation and its children run under credentials that cannot reach admin endpoints or other users' jobs, verified by a runner that tries and is refused.
Problem
Hawk-hosted investigations and every child job they launch run on the launching user's Hawk identity. Code in those runners (the audited benchmark's code today, agent-edited eval code once that lands) sits next to a token that can do anything that user can: for an admin that includes Middleman model and provider-key management, and stopping or deleting any job. The agent itself never holds the token, but the code it runs does. Investigation jobs also count against the operator's own job quota (Hawk 3.6 caps outstanding runner jobs per user at 128).
Want
Each investigation gets its own short-lived, least-privilege identity, derived from the user who launched it: only the models on its worker menu, only the eval sets it creates and the log sources it was given, no admin, and credentials that expire. Children inherit a narrower version of the same.
Upstream (METR/hawk)
feat: issue credentials scoped to workload executions(draft): OAuth client-credentials, 30-minute JWTs for Hawk/Middleman/AWS, grants for exact eval sets and model approvals. This is the primitive we want. Part of a stack (SEC-374); workload launches stay disabled until enforcement and runner integration land.feat: bind runner credentials to the current launch identity(review required).feat(api): let a launch name the client that issued its refresh token(approved).Our deployment is on Hawk server 3.5.0; METR has released 3.7.0, so adopting any of these also needs a redeploy.
Interim
_jobs.Hawk.submit, which today reads the runner hook's refresh token from private state) so switching to workload credentials is one change.Done when
An investigation and its children run under credentials that cannot reach admin endpoints or other users' jobs, verified by a runner that tries and is refused.