[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6GYC38ZW9VT4MARZQCWSWK1":3,"skill-same:01M6GYC38ZW9VT4MARZQCWSWK1":81},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":16,"sourceHtmlUrl":17,"categories":18,"keywords":19,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":44,"commitSha":45,"skillDirectory":46,"forksCount":47,"repositoryHtmlUrl":48,"repositoryHomepageUrl":6,"ownerHtmlUrl":49,"ownerBlogUrl":50,"ownerDescription":51,"updatedAt":52,"install":53,"resources":66},"01M6GYC38ZW9VT4MARZQCWSWK1","detect-mass-assignment",null,"Use when a request body is bound directly to a model or object. Finds auto-binding sinks, checks which fields a client can set, and adds an explicit allowlist or read-only binding.","jiayaoqijia\u002Fcryptoskill","jiayaoqijia","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1453879?v=4","01M6GMYTX7Q7S504VC6E756ENR","YQ","01M6GMYV1QKJ1CC75MTTGT9PR0",81,"MIT","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-detect-mass-assignment\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-detect-mass-assignment\u002FSKILL.md",[],[20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"detect mass assignment","detect","when","SET","body","fields","request","object","can","which","read-only","client","binding","only","auto","use","read","model","auto-binding","2026-11-10 10:12:30",false,"---\nname: detect-mass-assignment\ndescription: Use when a request body is bound directly to a model or object. Finds auto-binding sinks, checks which fields a client can set, and adds an explicit allowlist or read-only binding.\n---\n\n# Detect mass assignment\n\nMass assignment (over-posting) is when a framework binds every field in a request body to a model,\nso a client can set fields the UI never exposed — `is_admin`, `role`, `credits`, `owner_id`,\n`email_verified`. The fix is an explicit allowlist of assignable fields.\n\n## Procedure\n\n1. Find auto-binding sinks: they take the whole request payload, not a specific field.\n\n       rg -n \"request\\.(json|body|data)|@RequestBody|params\\[:user\\]|strong_parameters|permit\\(\" src\u002F \\\n         | head -50\n\n2. Inspect the target model's writable fields and compare against what the endpoint should accept:\n\n       rg -n \"class User|attr_accessible|guarded|@Column|@JsonProperty|fields\\s*=\" src\u002Fmodels 2>\u002Fdev\u002Fnull\n\n3. Probe by adding privileged fields that the UI does not send and observe whether they take effect:\n\n       curl -s -X PATCH https:\u002F\u002Fapp.example.com\u002Fapi\u002Fme \\\n         -H \"Authorization: Bearer $TOKEN\" -H 'Content-Type: application\u002Fjson' \\\n         -d '{\"display_name\":\"x\",\"is_admin\":true,\"credits\":999999,\"role\":\"admin\"}'\n\n   Then re-read the profile and check whether `role`\u002F`credits` changed.\n\n4. Fix with an explicit allowlist. Framework idioms:\n\n       # Rails: strong parameters\n       params.require(:user).permit(:display_name, :email)\n       # Django REST Framework\n       read_only_fields = [\"role\", \"credits\", \"is_admin\"]\n       # Spring: a DTO, not the entity\n       public record UpdateProfileRequest(String displayName, String email) {}\n\n5. Prefer a dedicated input DTO\u002Fview-model over binding to the persistence entity; the two should\n   not be the same class.\n\n6. Mark security-sensitive fields read-only at the model layer too (defence in depth), so a future\n   endpoint cannot reassign them by accident.\n\n7. Cover nested objects too: `{\"profile\":{\"role\":\"admin\"}}` if the parent binds nested models.\n\n## Pitfalls\n\n- A framework's `fillable`\u002F`permit` list is easy to widen for a feature and never narrow back.\n- `updated_at`, `id`, and foreign keys like `owner_id` are commonly over-postable and enable\n  ownership transfer.\n- PUT often replaces the whole object; a missing field becomes null rather than unchanged.\n- GraphQL input types fed straight into an ORM update have the same exposure.\n- Returning the full serialised entity then re-binding it round-trips attacker-set fields.\n- Adding a new privileged column without updating the allowlist reopens the hole silently.\n\n## Verification\n\n    curl -s -X PATCH https:\u002F\u002Fapp.example.com\u002Fapi\u002Fme \\\n      -H \"Authorization: Bearer $TOKEN\" -H 'Content-Type: application\u002Fjson' \\\n      -d '{\"role\":\"admin\"}' | jq -r '.role'\n    curl -s https:\u002F\u002Fapp.example.com\u002Fapi\u002Fme -H \"Authorization: Bearer $TOKEN\" | jq -r 'has(\"is_admin\")'\n\nPass: the response does not contain the injected `role`, and re-reading the profile shows it\nunchanged. Report each binding sink, the fields exposed, and the allowlist now enforced.\n","# Detect mass assignment\n\nMass assignment (over-posting) is when a framework binds every field in a request body to a model,\nso a client can set fields the UI never exposed — `is_admin`, `role`, `credits`, `owner_id`,\n`email_verified`. The fix is an explicit allowlist of assignable fields.\n\n## Procedure\n\n1. Find auto-binding sinks: they take the whole request payload, not a specific field.\n\n       rg -n \"request\\.(json|body|data)|@RequestBody|params\\[:user\\]|strong_parameters|permit\\(\" src\u002F \\\n         | head -50\n\n2. Inspect the target model's writable fields and compare against what the endpoint should accept:\n\n       rg -n \"class User|attr_accessible|guarded|@Column|@JsonProperty|fields\\s*=\" src\u002Fmodels 2>\u002Fdev\u002Fnull\n\n3. Probe by adding privileged fields that the UI does not send and observe whether they take effect:\n\n       curl -s -X PATCH https:\u002F\u002Fapp.example.com\u002Fapi\u002Fme \\\n         -H \"Authorization: Bearer $TOKEN\" -H 'Content-Type: application\u002Fjson' \\\n         -d '{\"display_name\":\"x\",\"is_admin\":true,\"credits\":999999,\"role\":\"admin\"}'\n\n   Then re-read the profile and check whether `role`\u002F`credits` changed.\n\n4. Fix with an explicit allowlist. Framework idioms:\n\n       # Rails: strong parameters\n       params.require(:user).permit(:display_name, :email)\n       # Django REST Framework\n       read_only_fields = [\"role\", \"credits\", \"is_admin\"]\n       # Spring: a DTO, not the entity\n       public record UpdateProfileRequest(String displayName, String email) {}\n\n5. Prefer a dedicated input DTO\u002Fview-model over binding to the persistence entity; the two should\n   not be the same class.\n\n6. Mark security-sensitive fields read-only at the model layer too (defence in depth), so a future\n   endpoint cannot reassign them by accident.\n\n7. Cover nested objects too: `{\"profile\":{\"role\":\"admin\"}}` if the parent binds nested models.\n\n## Pitfalls\n\n- A framework's `fillable`\u002F`permit` list is easy to widen for a feature and never narrow back.\n- `updated_at`, `id`, and foreign keys like `owner_id` are commonly over-postable and enable\n  ownership transfer.\n- PUT often replaces the whole object; a missing field becomes null rather than unchanged.\n- GraphQL input types fed straight into an ORM update have the same exposure.\n- Returning the full serialised entity then re-binding it round-trips attacker-set fields.\n- Adding a new privileged column without updating the allowlist reopens the hole silently.\n\n## Verification\n\n    curl -s -X PATCH https:\u002F\u002Fapp.example.com\u002Fapi\u002Fme \\\n      -H \"Authorization: Bearer $TOKEN\" -H 'Content-Type: application\u002Fjson' \\\n      -d '{\"role\":\"admin\"}' | jq -r '.role'\n    curl -s https:\u002F\u002Fapp.example.com\u002Fapi\u002Fme -H \"Authorization: Bearer $TOKEN\" | jq -r 'has(\"is_admin\")'\n\nPass: the response does not contain the injected `role`, and re-reading the profile shows it\nunchanged. Report each binding sink, the fields exposed, and the allowlist now enforced.\n",{"name":5,"description":7},"main","3df1d0d67b30ff15236561f8c0f9f06d33f42dfd","skills\u002Fpayments\u002F0xklen-detect-mass-assignment",17,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia","https:\u002F\u002Feth2030.com","Hardcore infra. Building @alt-research and applied cryptography.","2026-11-12 02:28:42",{"source":8,"skillName":5,"commands":54,"prompt":64,"zipAvailable":65},[55,58,61],{"tool":56,"command":57},"npx","npx skills add jiayaoqijia\u002Fcryptoskill --skill detect-mass-assignment",{"tool":59,"command":60},"bunx","bunx skills add jiayaoqijia\u002Fcryptoskill --skill detect-mass-assignment",{"tool":62,"command":63},"pnpm","pnpm dlx skills add jiayaoqijia\u002Fcryptoskill --skill detect-mass-assignment","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-detect-mass-assignment\u002FSKILL.md",true,[67,71,77],{"path":68,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":70,"sourceHtmlUrl":16},"LICENSE","许可证",1063,{"path":72,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":75,"sourceHtmlUrl":76},"SOURCE.md","REFERENCE","参考文档",348,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-detect-mass-assignment\u002FSOURCE.md",{"path":78,"resourceType":73,"resourceTypeDesc":74,"sizeBytes":79,"sourceHtmlUrl":80},"TRUST.auto.yaml",2217,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-detect-mass-assignment\u002FTRUST.auto.yaml",[82,110,133,151,164,174],{"skillNo":83,"name":84,"nameZh":6,"description":85,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":86,"sourceHtmlUrl":87,"categories":88,"keywords":89,"publishedAt":39},"01M712C436EQYE43342Q4E7GG1","recipe-performance","Diagnose a specific MetaMask user flow's real-app performance and Sentry critical-user-flow telemetry with deterministic mm-harness recipes. Use for CUF boundaries, cold\u002Fwarm\u002Fbackground-resume behavior, latency regressions, lifecycle tags, duplicate or blocking network requests, long tasks, layout\u002Fpaint cost, screen redraws, React rerenders, or browser trace analysis where tests alone cannot prove the real app.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FSKILL.md",[],[90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109],"performance","recipe performance","recipe","mm","sentry","harness","app","deterministic","recipes","flow","cold","critical","analysis","tasks","react","browser","layout","screen","network","metamask",{"skillNo":111,"name":112,"nameZh":6,"description":113,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":114,"licenseFileUrl":115,"sourceHtmlUrl":116,"categories":117,"keywords":118,"publishedAt":39},"01M70XT2F8A5CQZ81JBP98KSW3","mexc-spot-websocket","MEXC Spot WebSocket workflows for public streams, protobuf handling, depth maintenance, listen keys, and private streams without exposing API keys.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FSKILL.md",[],[119,120,121,122,123,124,125,126,127,128,129,130,131,132],"mexc spot websocket","spot","websocket","api","workflows","public","listen","streams","depth","keys","for","api keys","maintenance","protobuf",{"skillNo":134,"name":135,"nameZh":6,"description":136,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":114,"licenseFileUrl":137,"sourceHtmlUrl":138,"categories":139,"keywords":140,"publishedAt":39},"01M70XT0MBXN3WZY1BKN0CPNKR","mexc-spot-rest","MEXC Spot REST workflows for public data, signed account requests, orders, wallet\u002Fadmin actions, and secure signing without exposing API keys.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FSKILL.md",[],[141,120,142,143,144,145,146,130,129,128,147,148,149,124,150,123,122],"mexc spot rest","REST","admin","signing","Wallet","requests","actions","secure","data","orders",{"skillNo":152,"name":153,"nameZh":6,"description":154,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":114,"licenseFileUrl":155,"sourceHtmlUrl":156,"categories":157,"keywords":158,"publishedAt":39},"01M70XSYSVZ2N0N91XCAR2CAK0","mexc-futures-websocket","MEXC Futures WebSocket workflows for public streams, private account\u002Forder\u002Fposition streams, ping\u002Fpong, subscriptions, and depth maintenance.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FSKILL.md",[],[159,160,121,161,162,131,129,163,127,126,124,123],"mexc futures websocket","futures","position","ping","subscriptions",{"skillNo":165,"name":166,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":167,"sourceHtmlUrl":168,"categories":169,"keywords":170,"publishedAt":39},"01M6H0ZWHVE5W04WG2DKQE2SQC","0xklen-version-and-refresh-sanctions-lists","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FSKILL.md",[],[171,172,173],"refresh","0xklen version and refresh sanctions lists","version",{"skillNo":175,"name":176,"nameZh":6,"description":177,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":178,"sourceHtmlUrl":179,"categories":180,"keywords":181,"publishedAt":39},"01M6H0Z28Q3R8J0S799GJQWXM3","verify-tests-cover-changed-lines","Use when a PR adds code that the existing suite may not exercise. Measures patch coverage — the share of newly changed lines hit by tests — before approving.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FSKILL.md",[],[182,183,184,185,186,187,188,35,189,190,191],"tests","cover","verify tests cover changed lines","verify","coverage","pr","exercise","patch","code","share"]