diff --git a/server/src/__tests__/board-access-denial.test.ts b/server/src/__tests__/board-access-denial.test.ts index 991a9f30561..8b8759af6ac 100644 --- a/server/src/__tests__/board-access-denial.test.ts +++ b/server/src/__tests__/board-access-denial.test.ts @@ -35,6 +35,7 @@ describe("board-only denial", () => { ["post", `/api/companies/${COMPANY_ID}/secrets`, "[Open company secrets](//company/settings/secrets)"], ["post", `/api/secrets/${AGENT_ID}/rotate`, "[Open company secrets](//company/settings/secrets)"], ["post", `/api/companies/${COMPANY_ID}/budget-incidents/i-1/resolve?x=1`, "[Open budgets](//activity/budgets)"], + ["put", `/api/companies/${COMPANY_ID}/prompt-injection-prevention`, "[Open connection settings](//company/settings/connections)"], ["patch", `/api/agents/${AGENT_ID}/permissions`, `[Open the agent's permissions](//agents/${AGENT_ID}/permissions)`], ["post", `/api/agents/${AGENT_ID}/keys`, `[Open the agent's API keys](//agents/${AGENT_ID}/api-keys)`], ["post", `/api/agents/${AGENT_ID}/pause`, `[Open the agent's profile](//agents/${AGENT_ID})`], @@ -52,6 +53,7 @@ describe("board-only denial", () => { expect(res.body.code).toBe(BOARD_ACCESS_REQUIRED_CODE); expect(res.body.remediation).toContain("this denial is final"); expect(res.body.remediation).toContain("Paperclip web app or with their own board credentials"); + expect(res.body.remediation).toContain("Link a page only if you already know its route; do not search for one"); expect(res.body.remediation).not.toContain("](/"); }); diff --git a/server/src/routes/authz.ts b/server/src/routes/authz.ts index 27709a3b8c0..b0a64ec9a54 100644 --- a/server/src/routes/authz.ts +++ b/server/src/routes/authz.ts @@ -48,6 +48,7 @@ const AGENT_PROFILE_TABS: Record = { const BOARD_CONTROL_PAGES: Array<[RegExp, (match: RegExpExecArray) => [string, string]]> = [ [/^\/(?:companies\/[^/]+\/)?secrets?(?:[-/]|$)/, () => ["company secrets", "//company/settings/secrets"]], [/^\/companies\/[^/]+\/(?:budgets|budget-incidents|costs)(?:\/|$)/, () => ["budgets", "//activity/budgets"]], + [/^\/companies\/[^/]+\/(?:prompt-injection-prevention|decision-model|fast-response)(?:\/|$)/, () => ["connection settings", "//company/settings/connections"]], [/^\/companies\/[^/]+\/(?:members|invites|join-requests)(?:\/|$)/, () => ["company members", "//company/settings/members"]], [/^\/companies\/[^/]+\/(?:tools\/)?gateways(?:\/|$)|^\/tool-gateway\//, () => ["tool gateways", "//apps/gateways"]], [/^\/approvals\/([^/]+)/, match => ["the approval", `//approvals/${match[1]}`]], @@ -76,7 +77,7 @@ export function boardAccessRequired(req: Request) { const page = boardControlPage(req); const where = page ? `They can do it in the Paperclip web app: link [Open ${page[0]}](${page[1]}), with this conversation's company prefix as .` - : "They can do it in the Paperclip web app or with their own board credentials; link the most specific page you know."; + : "They can do it in the Paperclip web app or with their own board credentials. Link a page only if you already know its route; do not search for one."; return forbidden("Board access required", { code: BOARD_ACCESS_REQUIRED_CODE, remediation: `This action is board-only by design and this denial is final: no agent credential, tool or other API route can do it, so do not search for one. Tell the person that a board user must do it. ${where}`,