Authorization and access control security guidance based on Project CodeGuard — covers RBAC/ABAC/ReBAC, IDOR prevention, mass assignment, and transaction authorization
87
82%
Does it follow best practices?
Impact
93%
1.45xAverage score across 6 eval scenarios
Passed
No findings from the security scan
A multi-tenant SaaS platform has an onboarding flow where new organizations fill in their profile. The backend is Python/FastAPI. A developer submitted a PR to add a PATCH endpoint for updating organization details during onboarding. Please review the code and make it production-ready.
Produce a file called org_onboarding.py containing the production-ready endpoint. You may also include a security_notes.md explaining any changes you made and why.
The following files are provided as inputs. Extract them before beginning.
=============== FILE: inputs/org_onboarding.py =============== from fastapi import FastAPI, Request, Depends, HTTPException from pydantic import BaseModel from typing import Optional
app = FastAPI()
class Organization(BaseModel): id: str name: str industry: str website: Optional[str] = None onboarding_complete: bool = False tier: str = "trial" internal_notes: str = "" max_users: int = 10 sso_enabled: bool = False api_rate_limit: int = 100
class Config:
# Allow creating from ORM objects
from_attributes = Trueclass OrganizationUpdate(BaseModel): """Schema for organization profile updates during onboarding.""" model_config = {"extra": "allow"}
name: Optional[str] = None
industry: Optional[str] = None
website: Optional[str] = None_orgs = { "org-1": Organization(id="org-1", name="", industry="", tier="trial"), }
def get_org(org_id: str) -> Organization: if org_id not in _orgs: raise HTTPException(status_code=404) return _orgs[org_id]
def save_org(org: Organization): _orgs[org.id] = org
async def get_current_org_id(request: Request) -> str: return request.headers.get("X-Org-Id", "org-1")
@app.patch("/onboarding/profile") async def update_org_profile( updates: OrganizationUpdate, org_id: str = Depends(get_current_org_id), ): org = get_org(org_id) org_data = org.model_dump() org_data.update(updates.model_dump(exclude_unset=True)) updated_org = Organization(**org_data) save_org(updated_org) return {"status": "ok", "organization": updated_org.model_dump()} =============== END FILE ===============