કોડની એક લાઇન તમારું આખું એક્સેસ કંટ્રોલ મોડલ ખોરવી શકે છે. જો તમે રિકવેસ્ટ બોડીને સીધી ડેટાબેઝ અપડેટમાં મોકલી દો, તો તમે ક્લાયન્ટને તમારા સ્કીમાને ફરીથી લખવા માટે પેન આપી દીધી છે. આને 'mass assignment' કહેવાય છે. તે કોઈ અજાણ્યો બગ (bug) કે દુર્લભ કિસ્સો નથી. તે એક ડિઝાઇન નિષ્ફળતા છે જે ત્યારે જ દેખાય છે જ્યારે કોઈ API પેલોડને તેની પોતાની અપડેટ પોલિસી તરીકે ગણે છે.
await db.users.update(req.params.id, { ...req.body });
તે જોવામાં ચોખ્ખું લાગે છે. તે ટાઈપિંગ બચાવે છે. પરંતુ કી (keys) પર ક્લાયન્ટનું નિયંત્રણ હોય છે. એક અટેકર સામાન્ય પ્રોફાઇલ અપડેટમાં "role": "admin", "accountId": "someone_else", અથવા "credit": 99999" ઉમેરી શકે છે. તમારું વેલિડેશન લેયર કદાચ તે તપાસશે કે તે કિંમતો સ્ટ્રિંગ છે કે નંબર અને કહેશે કે તે બરાબર લાગે છે. જોકે, વેલિડિટી (validity) એ ઓથોરાઈઝેશન (authorization) નથી. એક યુઝર પાસે લક્ષિત રેકોર્ડનું કાયદેસરનું માલિકી હક હોઈ શકે છે. તેનો અર્થ એ નથી કે તેની પાસે તેની અંદરના દરેક ફિલ્ડને એડિટ કરવાનો અધિકાર હોવો જોઈએ.
માસ અસાઇનમેન્ટ ખરેખર કેવું દેખાય છે
જોખમ સુવિધામાં છુપાયેલું છે. ફ્રેમવર્ક અને ORMs JSON કીઝને સીધી ડેટાબેઝ કોલમ્સ સાથે મેપ કરવાનું અત્યંત સરળ બનાવે છે. જ્યારે તમે આવું કરો છો, ત્યારે તમે ડેટાબેઝને એ જણાવો છો કે શું બદલાવવું જોઈએ, માત્ર કેવી રીતે બદલાવવું જોઈએ તે જ નહીં.
પ્રોફાઇલ અપડેટ કરતો યુઝર displayName અને bio માટે માન્ય ડેટા મોકલી શકે છે, પરંતુ તેની સાથે role અથવા balance પણ છુપાવી શકે છે. જો તમારું કંટ્રોલર ફક્ત ઓબ્જેક્ટને આગળ મોકલે છે, તો ડેટાબેઝ તે બધું જ લખી દેશે. વેલિડેશન ખોટી રીતે બનાવેલી કિંમતોને પકડી લેશે. તે ભાગ્યે જ દૂષિત (malicious) કીઝને પકડી શકે છે. "આ યુઝરને તેમની પ્રોફાઇલ અપડેટ કરવાની મંજૂરી છે" એવો બિઝનેસ રૂલ રો (row) માં દરેક કોલમ પર સામાન્ય પરવાનગી બની જાય છે.
તેનો ઉકેલ વધુ વેલિડેશન નથી. તે વધુ કડક આર્કિટેક્ચર છે.
ત્રણ દરવાજા (The Three Gates)
એક સુરક્ષિત મ્યુટેશન સ્ટોરેજને સ્પર્શ કરે તે પહેલાં ત્રણ અલગ-અલગ તપાસમાંથી પસાર થાય છે.
સ્વીકૃત ફિલ્ડ્સ (Allowlist)
તમે કઈ કીઝ પર ધ્યાન આપશો તે નક્કી કરીને શરૂઆત કરો. જો કોઈ ફિલ્ડ એલોલિસ્ટમાં નથી, તો રિકવેસ્ટને નકારી કાઢો અથવા કીને કાઢી નાખો. આ ડિફોલ્ટ અભિગમને બદલી નાખે છે: જ્યાં સુધી ડેવલપર સ્પષ્ટપણે તેને એક્સપોઝ ન કરે ત્યાં સુધી નવા ડેટાબેઝ કોલમ્સ નોન-રાઈટેબલ (non-writable) રહે છે. સમય જતાં સ્કીમા વધતા જાય છે. કોઈ સાથીદાર stripeCustomerId, departmentBudget, અથવા isVerified ફ્લેગ ઉમેરે છે. એલોલિસ્ટ સાથે, તે નવા કોલમ્સ ક્લાયન્ટના રાઈટ્સથી આપમેળે સુરક્ષિત રહે છે. એલોલિસ્ટ વગર, દરેક નવો કોલમ અજાણતામાં એક API સરફેસ બની જાય છે.
માન્ય કિંમતો (Valid Values)
એકવાર તમે જાણી લો કે કયા ફિલ્ડ્સની પરવાનગી છે, પછી તપાસો કે કિંમતો તર્કસંગત છે કે નહીં. શું ટાઈમઝોન સ્ટ્રિંગ ખરેખર માન્ય ટાઈમઝોન છે? શું ઈમેલ ઈમેલ જેવું ફોર્મેટ ધરાવે છે? શું નંબર યોગ્ય રેન્જમાં છે? આ પાયાની સાવચેતી છે. તે તમારા સિસ્ટમમાં કચરો પ્રવેશતા અટકાવે છે, પરંતુ તે દુરુપયોગને અટકાવતું નથી. જો ખોટી વ્યક્તિ "admin" સ્ટ્રિંગ મોકલે છે, તો role ફિલ્ડમાં એકદમ માન્ય "admin" સ્ટ્રિંગ પણ જોખમી છે.
અધિકૃત પરિવર્તનો (Authorized Transitions)
આ એવો દરવાજો છે જે મોટાભાગની ટીમો છોડી દે છે, અને અહીં જ સાચી સુરક્ષા રહેલી છે. એક સૂક્ષ્મ પ્રશ્ન પૂછો: શું આ ચોક્કસ એક્ટર પાસે આ ચોક્કસ રેકોર્ડ પર આ ચોક્કસ ફિલ્ડ બદલવાની પરવાનગી છે? "શું યુઝર એડમિન છે?" એવું નહીં. "શું યુઝર પાસે write:users સ્કોપ છે?" એવું પણ નહીં. તેના બદલે, "શું આ યુઝરને તેમનું પોતાનું displayName બદલવાની મંજૂરી છે, પરંતુ ક્યારેય તેમનું accountId નહીં?" ફિલ્ડ-વાર ઓથોરાઈઝેશન "એડિટર" અથવા "યુઝર" જેવી વ્યાપક પરવાનગીને રો માંના દરેક પ્રોપર્ટી માટે માસ્ટર કી બનતા અટકાવે છે.
પેચ ફંક્શન બનાવવું (Building the Patch Function)
ત્રણેય દરવાજાઓને એક સિંગલ પાઈપલાઈનમાં જોડો. જ્યારે પેચ રિકવેસ્ટ આવે, ત્યારે તેને ક્રમ અનુસાર સ્ટેજમાંથી પસાર કરો.
પ્રથમ, તમારા એલોલિસ્ટ સામે ઇનપુટને ફિલ્ટર કરો. જો આ એન્ડપોઈન્ટ માટે role એ માન્ય ફિલ્ડ નથી, તો ત્યાં જ અટકી જાઓ. જે કિંમત તમારે ક્યારેય મેળવવી જ ન જોઈએ તેના માટે વેલિડેશન અથવા ઓથોરાઈઝેશન કરવાની કોઈ જરૂર નથી.
બીજું, માન્ય કિંમતોનું વેલિડેશન કરો. પ્રકારો (types), ફોર્મેટ્સ અને બિઝનેસ રૂલ્સ તપાસો. લોકેશન ફિલ્ડ એક એવી સ્ટ્રિંગ હોવી જોઈએ જે વાસ્તવિક ટાઈમઝોન દર્શાવે. અવતાર URL એક ચોક્કસ લંબાઈ હેઠળનું માન્ય URI હોવું જોઈએ.
ત્રીજું, એક્શનને ઓથોરાઈઝ કરો. ખાતરી કરો કે એક્ટર પાસે લક્ષિત રેકોર્ડની માલિકી છે, અથવા આ ફિલ્ડ માટે જરૂરી ચોક્કસ પરવાનગી છે. પર્સનલ ડેટા માટે માલિકી (ownership) એ એક સારો ડિફોલ્ટ વિકલ્પ છે, પરંતુ કેટલાક ફિલ્ડ્સ માટે હજુ પણ વધારાના દરવાજાની જરૂર છે. એક યુઝર તેની પ્રોફાઇલનો માલિક હોઈ શકે છે, છતાં માત્ર બિલિંગ એડમિન જ taxRegion ને સ્પર્શી શકે છે.
ચોથું, ડેટાને નોર્મલાઈઝ કરો. વ્હાઇટસ્પેસ દૂર કરો, વારંવાર આવતા સ્પેસને ઘટાડો, ઈમેલને લોઅરકેસ કરો અથવા કંટ્રોલ કેરેક્ટર્સ દૂર કરો. આ વેલિડેશન પછી પરંતુ સ્ટોરેજ પહેલાં કરો જેથી તમે ઓથોરાઈઝેશન ચેક્સ દરમિયાન અયોગ્ય (dirty) સ્ટ્રિંગ્સ સાથે સરખામણી ન કરો.
If the input fails any gate, reject the entire mutation. Do not partially apply the safe fields and quietly drop the bad ones. A mixed response trains clients to spray every key they can think of and see what sticks. Fail explicitly.
The Edge Cases That Actually Matter
Mass assignment defenses live or die on details that unit tests often miss.
Duplicate JSON keys. Attackers can send payloads like {"role": "user", "role": "admin"}. Depending on your HTTP parser and framework, the second value might overwrite the first before your application code sees the object. Test this behavior at the parser level. If your framework silently accepts the last key, your allowlist might be looking at "user" while the database receives "admin".
Nested objects, nulls, and arrays. Do not assume the payload is flat. A client might wrap a restricted field inside a nested object like { "profile": { "role": "admin" } }. Your allowlist must recurse if your schema does. Likewise, decide how you handle null. Does it mean "ignore this field" or "delete this field"? And if an array is expected, does your validator reject unexpected structures, or does it cast a single object into an array and let it through?
Unicode normalization. Two strings can look identical to a human while being different sequences of bytes. A user might send a precomposed é or a decomposed e plus combining accent. If your authorization check normalizes once but your storage layer normalizes differently, you can end up with inconsistent data or, worse, a bypass where a username collision slips past your logic. Normalize early and normalize consistently.
Race conditions. Authorization decisions are not freeze frames. They happen at a point in time. Two requests can read the same record, both see that the actor is allowed to write, and both issue updates. In between, the state or the actor’s permissions might have changed. Always apply database updates with a condition on a version number or a state machine value. Use something like UPDATE users SET ... WHERE id = ? AND version = 5. If the row changed since you read it, the write fails. Handle the failure by retrying or rejecting. This keeps stale authorization checks from corrupting your data.
Monitor What Matters
You cannot secure what you cannot see. Build your audit logging around the decision, not just the action.
Log the actor ID and the target ID. Log the exact field names that were accepted and the ones that were rejected. Log the policy version that made the decision and the final result. If a user suddenly starts getting role rejected in their profile update, you want to know immediately.
Never log bearer tokens. Never dump entire request bodies into your logs. An audit trail should help you investigate abuse, not become a repository of credentials and personal data.
The Only Rule You Need
A request body proposes data. It never defines its own authority. The client can ask for anything. Your server decides, field by field and row by row, what is allowed to land in permanent storage. Build your patches with that separation in mind, and mass assignment becomes a problem you stopped long before it reached your authorization layer.
