{"record":{"id":"04617c7e83d37b6a","repo":"argoproj/argo-workflows","slug":"forbidden","errorCode":null,"errorMessage":"Forbidden","messagePattern":"Forbidden","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"server/artifacts/artifact_server.go","lineNumber":119,"sourceCode":"\t\ta.unauthorizedError(w)\n\t\treturn\n\t}\n\n\ta.logger.WithFields(logging.Fields{\n\t\t\"namespace\":            namespace,\n\t\t\"workflowTemplateName\": workflowTemplateName,\n\t\t\"artifactName\":         artifactName,\n\t}).Info(ctx, \"Upload artifact\")\n\n\t// Authorize before reading the request body, so an unprivileged caller\n\t// cannot force the server to buffer a large upload just to be rejected.\n\tallowed, err := auth.CanI(ctx, \"get\", \"workflowtemplates\", namespace, workflowTemplateName)\n\tif err != nil {\n\t\ta.serverInternalError(ctx, err, w)\n\t\treturn\n\t}\n\tif !allowed {\n\t\thttp.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)\n\t\treturn\n\t}\n\tallowed, err = auth.CanI(ctx, \"create\", \"workflows\", namespace, \"\")\n\tif err != nil {\n\t\ta.serverInternalError(ctx, err, w)\n\t\treturn\n\t}\n\tif !allowed {\n\t\thttp.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)\n\t\treturn\n\t}\n\n\t// Get WorkflowTemplate to find artifact configuration\n\twfClient := auth.GetWfClient(ctx)\n\twfTemplate, err := wfClient.ArgoprojV1alpha1().WorkflowTemplates(namespace).Get(ctx, workflowTemplateName, metav1.GetOptions{})\n\tif err != nil {\n\t\thttp.Error(w, fmt.Sprintf(\"Failed to get WorkflowTemplate %s/%s: %v\", namespace, workflowTemplateName, err), http.StatusNotFound)\n\t\treturn","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/artifacts/artifact_server.go#L101-L137","documentation":"Before uploading, the server checks RBAC with auth.CanI for verb 'get' on workflowtemplates in the target namespace for the named template. If the caller's credentials (client token, server SA, or SSO claims) lack that permission, the handler responds 403 Forbidden. This enforces least-privilege: you may only create workflows from templates you can read.","triggerScenarios":"Submitting an upload with a token whose RBAC role has no argoproj.io/workflowtemplates get permission in the target namespace; SSO user not mapped to a service account with that role.","commonSituations":"CI tokens scoped to workflows only; SSO RBAC mapping missing the workflowtemplates rule; wrong namespace used in the URL (permissions are namespace-scoped).","solutions":["Grant the caller's Role/ClusterRole a rule: apiGroups: [argoproj.io], resources: [workflowtemplates], verbs: [get] in that namespace","Bind that role to the user/service account making the request","Verify the namespace in the URL matches the namespace where RBAC was granted","Check SSO RBAC label mapping if using SSO auth mode"],"exampleFix":"# before (Role without workflowtemplates)\nrules:\n- apiGroups: [argoproj.io]\n  resources: [workflows]\n  verbs: [create]\n# after\nrules:\n- apiGroups: [argoproj.io]\n  resources: [workflows]\n  verbs: [create]\n- apiGroups: [argoproj.io]\n  resources: [workflowtemplates]\n  verbs: [get]","handlingStrategy":"validation","validationCode":"kubectl auth can-i get workflowtemplates -n <namespace> --as=<user>   # must be yes\nkubectl auth can-i create workflows -n <namespace> --as=<user>        # must be yes","typeGuard":null,"tryCatchPattern":"if resp.StatusCode == http.StatusForbidden {\n    return fmt.Errorf(\"caller lacks RBAC (workflowtemplates/get or workflows/create) in %s\", namespace)\n}","preventionTips":["Use `kubectl auth can-i` to preflight both permissions before upload","Create a dedicated role for artifact upload bundling both verbs","For SSO, verify claim-to-serviceaccount RBAC mapping includes these rules","Double-check the namespace in the URL matches where RBAC was granted"],"tags":["rbac","http-403","forbidden","kubernetes","authorization"],"backgroundTag":"rbac-forbidden","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}