Skip to content

Agent command endpoints derive actor and authorization from the request body #140

Description

@Jaro-c

The agent command endpoints derive the actor identity and the authorization level from the request body instead of from the authenticated session and the user's real permissions.

Impact

  • POST /agents/{id}/cmd reads user_id and permission from the JSON body. Because the agent trusts the dashboard's signature and has no user model, an authenticated user could get a dashboard-signed command at an arbitrary authorization level, with a forged audit actor — privilege escalation + audit forgery.
  • POST /agents/{id}/reboot and POST /agents/{id}/nftables-resolve sign a fixed level without checking the caller actually holds it, and the whole /agents router was gated only by require_auth (no vps:* permission check). register/remove agent had no permission gate either.

Fix

  • Derive the actor user_id from Extension<AuthUser> and the command level from the user's real permissions (vps:read→read, vps:create|edit|delete|vps:*→write, *:*→admin); never from the body.
  • Make the /cmd body a typed {type, payload} so user_id/permission cannot be injected.
  • Add a require_vps_access route floor to the /agents user router, and require >= write on the write operations.
  • The signed wire strings the agent consumes are unchanged.

Regression tests assert a low-privilege user is denied /cmd, /reboot, and /nftables-resolve even with permission:"admin" in the body.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions