{"record":{"id":"4e774ef405cfe652","repo":"langgenius/dify","slug":"forbidden-4e774e","errorCode":null,"errorMessage":"Forbidden","messagePattern":"Forbidden","errorType":"http","errorClass":"Forbidden","httpStatus":403,"severity":"error","filePath":"api/controllers/console/datasets/rag_pipeline/rag_pipeline_workflow.py","lineNumber":668,"sourceCode":"    @account_initialization_required\n    @edit_permission_required\n    @rbac_permission_required(RBACResourceScope.DATASET, RBACPermission.DATASET_EDIT)\n    @with_current_user\n    @get_rag_pipeline\n    @model_validate(WorkflowListQuery)\n    def get(self, req_data: WorkflowListQuery, current_user: Account, pipeline: Pipeline):\n        \"\"\"\n        Get published workflows\n        \"\"\"\n\n        page = req_data.page\n        limit = req_data.limit\n        user_id = req_data.user_id\n        named_only = req_data.named_only\n\n        if user_id:\n            if user_id != current_user.id:\n                raise Forbidden()\n\n        rag_pipeline_service = RagPipelineService(db.session())\n        with sessionmaker(db.engine).begin() as session:\n            workflows, has_more = rag_pipeline_service.get_all_published_workflow(\n                session=session,\n                pipeline=pipeline,\n                page=page,\n                limit=limit,\n                user_id=user_id,\n                named_only=named_only,\n            )\n\n            return WorkflowPaginationResponse.model_validate(\n                {\n                    \"items\": workflows,\n                    \"page\": page,\n                    \"limit\": limit,\n                    \"has_more\": has_more,","sourceCodeStart":650,"sourceCodeEnd":686,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/datasets/rag_pipeline/rag_pipeline_workflow.py#L650-L686","documentation":"Raised as werkzeug Forbidden() (HTTP 403) in PublishedAllRagPipelineApi.get (GET /rag/pipelines/<pipeline_id>/workflows). The list endpoint accepts a `user_id` filter, but a caller may only filter by their own account; any other user_id is rejected. This is an intentional authorization guard, not a bug.","triggerScenarios":"Calling GET /rag/pipelines/<pipeline_id>/workflows?user_id=<X> where <X> differs from the authenticated current_user.id. The check `if user_id != current_user.id` fires and raises Forbidden().","commonSituations":"A client hardcoding or caching another user's id; an admin tool assuming cross-user visibility that the endpoint does not grant; stale session token after account switch.","solutions":["Omit user_id to list published workflows for the pipeline without a user filter.","Only pass user_id equal to the currently authenticated account's id.","If cross-user listing is a product requirement, implement it through an admin/owner-scoped route with proper RBAC rather than this endpoint."],"exampleFix":"// before\nGET /rag/pipelines/<id>/workflows?user_id=<other-user>\n// after\nGET /rag/pipelines/<id>/workflows            // no user_id filter\n// or\nGET /rag/pipelines/<id>/workflows?user_id=<self>","handlingStrategy":"validation","validationCode":"function listWorkflows(pipelineId, selfUserId, opts = {}) {\n  const params = new URLSearchParams({ page: opts.page ?? 1, limit: opts.limit ?? 20 });\n  if (opts.userId) {\n    if (opts.userId !== selfUserId) throw new Error('can only filter by own user_id');\n    params.set('user_id', opts.userId);\n  }\n  if (opts.namedOnly) params.set('named_only', 'true');\n  return fetch(`/rag/pipelines/${pipelineId}/workflows?${params}`);\n}","typeGuard":"function isOwnUserFilter(userId, selfId) {\n  return userId == null || userId === selfId;\n}","tryCatchPattern":"try { await listWorkflows(id, self, { userId }); } catch (e) { if (/forbidden/i.test(e.message)) useNoUserFilter(); else throw e; }","preventionTips":["Default to omitting user_id.","Never send another user's id from this client.","Surface 403 as 'view your own workflows only'."],"tags":["rag-pipeline","workflow","authorization","http-403"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}