{"record":{"id":"de3e20a2ec77fb46","repo":"spring-projects/spring-security","slug":"access-is-denied-de3e20","errorCode":null,"errorMessage":"Access is denied","messagePattern":"Access is denied","errorType":"exception","errorClass":"AccessDeniedException","httpStatus":403,"severity":"error","filePath":"access/src/main/java/org/springframework/security/access/vote/ConsensusBased.java","lineNumber":84,"sourceCode":"\t@SuppressWarnings({ \"rawtypes\", \"unchecked\" })\n\tpublic void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)\n\t\t\tthrows AccessDeniedException {\n\t\tint grant = 0;\n\t\tint deny = 0;\n\t\tfor (AccessDecisionVoter voter : getDecisionVoters()) {\n\t\t\tint result = voter.vote(authentication, object, configAttributes);\n\t\t\tswitch (result) {\n\t\t\t\tcase AccessDecisionVoter.ACCESS_GRANTED -> grant++;\n\t\t\t\tcase AccessDecisionVoter.ACCESS_DENIED -> deny++;\n\t\t\t\tdefault -> {\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (grant > deny) {\n\t\t\treturn;\n\t\t}\n\t\tif (deny > grant) {\n\t\t\tthrow new AccessDeniedException(\n\t\t\t\t\tthis.messages.getMessage(\"AbstractAccessDecisionManager.accessDenied\", \"Access is denied\"));\n\t\t}\n\t\tif ((grant == deny) && (grant != 0)) {\n\t\t\tif (this.allowIfEqualGrantedDeniedDecisions) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow new AccessDeniedException(\n\t\t\t\t\tthis.messages.getMessage(\"AbstractAccessDecisionManager.accessDenied\", \"Access is denied\"));\n\t\t}\n\t\t// To get this far, every AccessDecisionVoter abstained\n\t\tcheckAllowIfAllAbstainDecisions();\n\t}\n\n\tpublic boolean isAllowIfEqualGrantedDeniedDecisions() {\n\t\treturn this.allowIfEqualGrantedDeniedDecisions;\n\t}\n\n\tpublic void setAllowIfEqualGrantedDeniedDecisions(boolean allowIfEqualGrantedDeniedDecisions) {","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/access/src/main/java/org/springframework/security/access/vote/ConsensusBased.java#L66-L102","documentation":"ConsensusBased.decide() throws AccessDeniedException when deny votes outnumber grant votes (deny > grant). The consensus strategy totals ACCESS_GRANTED vs ACCESS_DENIED votes and denies when the majority denies.","triggerScenarios":"An invocation where more voters voted ACCESS_DENIED than ACCESS_GRANTED, e.g. one affirmative, one deny, one abstain with allowIfEqualGrantedDeniedDecisions irrelevant or unequal case.","commonSituations":"Users partially matching role requirements across multiple voters; symmetric configurations where one more role is missing than present; duplicated voters amplifying denies.","solutions":["Grant the missing authorities so grants >= denies","Adjust which voters are registered or the attributes they evaluate","Set allowIfEqualGrantedDeniedDecisions(true) only for tie cases (not this case, but review flag)","Audit voter list for unintended duplicate or overly strict voters"],"exampleFix":"// before\nuser authorities: [ROLE_USER]; access=\"ROLE_USER,ROLE_ADMIN\" -> 1 deny, 1 grant\n\n// after\nuser authorities: [ROLE_USER, ROLE_ADMIN] -> 2 grants, 0 denies","handlingStrategy":"validation","validationCode":"long grants = voters.stream().filter(v -> v.vote(auth, obj, attrs) == AccessDecisionVoter.ACCESS_GRANTED).count();\nlong denies = voters.stream().filter(v -> v.vote(auth, obj, attrs) == AccessDecisionVoter.ACCESS_DENIED).count();\nif (denies > grants) throw new AccessDeniedException(\"Would be denied by consensus\");","typeGuard":"null","tryCatchPattern":"try {\n    consensusBased.decide(auth, object, attrs);\n} catch (AccessDeniedException e) {\n    throw new ResponseStatusException(HttpStatus.FORBIDDEN, \"Consensus denied\");\n}","preventionTips":["Remove duplicate voters that inflate deny counts","Keep the set of securing attributes minimal and aligned to roles","Test consensus outcomes for boundary vote distributions"],"tags":["spring-security","authorization","consensus-based","voters","access-denied"],"backgroundTag":"permission-denied","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}