[{"data":1,"prerenderedAt":2965},["ShallowReactive",2],{"search-api":-1,"listing-tag-securite-page-1":3},[4,1467],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"id":11,"date":12,"listed":13,"nocomments":7,"hidden":7,"categories":14,"tags":15,"cover":18,"readingTime":19,"body":24,"_type":1461,"_id":1462,"_source":1463,"_file":1464,"_stem":1465,"_extension":1466},"\u002Ffr\u002Fdette-technique\u002Fdependabot-craft-gestion-dependances","dette-technique",false,"","Dependabot : configurer son coéquipier silencieux contre la dette de dépendances","Dependabot bien configuré vous évite des nuits à patcher la prochaine CVE critique. Guide craft : 7 tips, config YAML annotée, auto-merge intelligent.",61,"2026-05-01",true,[6],[16,17],"securite","ia","covers\u002Farticles\u002Fdependabot-craft-gestion-dependances.jpg",{"text":20,"minutes":21,"time":22,"words":23},"11 min read",10.825,649500,2165,{"type":25,"children":26,"toc":1447},"root",[27,39,61,65,72,77,93,98,120,133,136,142,147,236,241,244,257,260,266,271,285,298,839,888,923,929,942,983,995,1001,1013,1018,1021,1027,1032,1049,1059,1092,1095,1101,1106,1211,1216,1221,1224,1230,1235,1240,1252,1264,1267,1273,1288,1301,1349,1400,1413,1426,1429,1441],{"type":28,"tag":29,"props":30,"children":31},"element","p",{},[32],{"type":28,"tag":33,"props":34,"children":35},"strong",{},[36],{"type":37,"value":38},"text","En décembre 2021, Log4Shell (CVE-2021-44228, score CVSS 10 sur 10) a tenu l'industrie entière debout tout un week-end. Une faille critique dans une librairie que presque personne n'avait choisie explicitement, et qui se cachait pourtant dans des dizaines de milliers de projets. Ce soir-là, d'innombrables équipes ont découvert la même chose : elles ne savaient pas ce qu'il y avait vraiment dans leur arbre de dépendances. C'est exactement ce genre de nuit que Dependabot bien configuré vous évite.",{"type":28,"tag":29,"props":40,"children":41},{},[42,44,51,53,59],{"type":37,"value":43},"Depuis, je n'ouvre plus un projet sans ce réflexe. Sur crmcoaching, le SaaS que je développe seul avec Claude, l'un des premiers fichiers que je versionne après le ",{"type":28,"tag":45,"props":46,"children":48},"code",{"className":47},[],[49],{"type":37,"value":50},"package.json",{"type":37,"value":52},", c'est ",{"type":28,"tag":45,"props":54,"children":56},{"className":55},[],[57],{"type":37,"value":58},"dependabot.yml",{"type":37,"value":60}," : versionné, audité, pensé. Pas l'activation par défaut que la majorité des projets laissent en l'état, mais une vraie configuration craft. Voici ce que j'applique au quotidien sur crmcoaching, ce que je vois rater en mission, et la méthode complète.",{"type":28,"tag":62,"props":63,"children":64},"hr",{},[],{"type":28,"tag":66,"props":67,"children":69},"h2",{"id":68},"pourquoi-vos-dépendances-pourrissent-plus-vite-en-2026",[70],{"type":37,"value":71},"Pourquoi vos dépendances pourrissent plus vite en 2026",{"type":28,"tag":29,"props":73,"children":74},{},[75],{"type":37,"value":76},"Le constat est chiffré, et il est sévère.",{"type":28,"tag":29,"props":78,"children":79},{},[80,82,91],{"type":37,"value":81},"Selon le ",{"type":28,"tag":83,"props":84,"children":88},"a",{"href":85,"rel":86},"https:\u002F\u002Fsnyk.io\u002Freports\u002Fopen-source-security\u002F",[87],"nofollow",[89],{"type":37,"value":90},"Snyk Open Source Security Report 2024",{"type":37,"value":92},", les vulnérabilités de supply chain ont progressé de 156% entre 2023 et 2024. Sur la même période, GitClear documente que les équipes utilisant un assistant IA comme Claude ajoutent en moyenne 40% de dépendances en plus par projet. Le ratio est clair : on consomme plus, on audite moins.",{"type":28,"tag":29,"props":94,"children":95},{},[96],{"type":37,"value":97},"Je l'ai vu sur crmcoaching même. La séquence est toujours la même : je prompte Claude pour résoudre un problème, il me propose une lib externe (souvent une qu'il connaît depuis son training data, donc pas la version courante), je l'accepte parce qu'elle marche, et la dépendance entre dans le repo. Six mois plus tard, cette même lib a une CVE critique. Sans filet de sécurité, personne ne le sait, surtout quand on développe seul.",{"type":28,"tag":99,"props":100,"children":101},"blockquote",{},[102],{"type":28,"tag":29,"props":103,"children":104},{},[105,110,112,118],{"type":28,"tag":33,"props":106,"children":107},{},[108],{"type":37,"value":109},"Ce que j'ai observé",{"type":37,"value":111}," : un ",{"type":28,"tag":45,"props":113,"children":115},{"className":114},[],[116],{"type":37,"value":117},"pnpm list --depth=Infinity",{"type":37,"value":119}," sur crmcoaching listait plus de 1 000 dépendances transitives, pour une application que je connais pourtant ligne par ligne. La quasi-totalité n'avait jamais été ajoutée volontairement : elles sont arrivées dans les bagages de quelques dépendances directes. Et pourtant, chacune d'elles peut, demain matin, ouvrir une faille sur le paiement ou l'authentification de mes utilisateurs.",{"type":28,"tag":29,"props":121,"children":122},{},[123,125,131],{"type":37,"value":124},"Bruce Schneier a écrit que ",{"type":28,"tag":126,"props":127,"children":128},"em",{},[129],{"type":37,"value":130},"\"Security is a process, not a product\"",{"type":37,"value":132},". Dependabot n'est pas un produit que vous activez et que vous oubliez : c'est le squelette d'un processus craft de gestion de dépendances. Sans le squelette, vous codez en aveugle.",{"type":28,"tag":62,"props":134,"children":135},{},[],{"type":28,"tag":66,"props":137,"children":139},{"id":138},"les-4-signaux-que-votre-gestion-de-dépendances-dérive",[140],{"type":37,"value":141},"Les 4 signaux que votre gestion de dépendances dérive",{"type":28,"tag":29,"props":143,"children":144},{},[145],{"type":37,"value":146},"Demain matin, ouvrez votre repo principal et vérifiez ces 4 signaux. Si vous en cochez 2 ou plus, vous avez un problème.",{"type":28,"tag":148,"props":149,"children":150},"ul",{},[151,178,188,204],{"type":28,"tag":152,"props":153,"children":154},"li",{},[155,176],{"type":28,"tag":33,"props":156,"children":157},{},[158,160,166,168,174],{"type":37,"value":159},"Signal 1 : votre dernier audit de dépendances (",{"type":28,"tag":45,"props":161,"children":163},{"className":162},[],[164],{"type":37,"value":165},"pnpm audit",{"type":37,"value":167}," côté Node, ",{"type":28,"tag":45,"props":169,"children":171},{"className":170},[],[172],{"type":37,"value":173},"mvn dependency-check:check",{"type":37,"value":175}," côté Java, ou équivalent) date de plus de 30 jours.",{"type":37,"value":177}," Concrètement, vous ne savez pas combien de vulnérabilités critiques dorment dans votre arbre de dépendances. Mauvais signe.",{"type":28,"tag":152,"props":179,"children":180},{},[181,186],{"type":28,"tag":33,"props":182,"children":183},{},[184],{"type":37,"value":185},"Signal 2 : vos PR Dependabot s'accumulent en mode \"à traiter plus tard\".",{"type":37,"value":187}," Si vous voyez plus de 10 PR ouvertes depuis plus de 14 jours, votre filet de sécurité est devenu un cimetière.",{"type":28,"tag":152,"props":189,"children":190},{},[191,202],{"type":28,"tag":33,"props":192,"children":193},{},[194,196],{"type":37,"value":195},"Signal 3 : vous ne savez pas quelle est votre ",{"type":28,"tag":45,"props":197,"children":199},{"className":198},[],[200],{"type":37,"value":201},"time-to-patch",{"type":37,"value":203}," sur les CVE critiques. C'est le délai entre disclosure d'une CVE et son fix en prod. En dessous de 7 jours, vous êtes sain. Au-dessus de 30 jours, vous jouez à la roulette russe.",{"type":28,"tag":152,"props":205,"children":206},{},[207,227,229,234],{"type":28,"tag":33,"props":208,"children":209},{},[210,212,218,220,225],{"type":37,"value":211},"Signal 4 : vous avez des entrées ",{"type":28,"tag":45,"props":213,"children":215},{"className":214},[],[216],{"type":37,"value":217},"ignore",{"type":37,"value":219}," dans votre ",{"type":28,"tag":45,"props":221,"children":223},{"className":222},[],[224],{"type":37,"value":58},{"type":37,"value":226}," qui datent de plus de 6 mois.",{"type":37,"value":228}," Un ",{"type":28,"tag":45,"props":230,"children":232},{"className":231},[],[233],{"type":37,"value":217},{"type":37,"value":235}," est une dette que vous reportez. Si vous ne savez plus pourquoi vous l'avez mis, vous avez déjà perdu.",{"type":28,"tag":29,"props":237,"children":238},{},[239],{"type":37,"value":240},"Ces signaux ne sont pas théoriques. Je les ai vus, dans cet ordre, dans la majorité des équipes que j'ai accompagnées sur 2024 et 2025. Le 8ème signal arrive toujours : c'est l'incident.",{"type":28,"tag":62,"props":242,"children":243},{},[],{"type":28,"tag":245,"props":246,"children":251},"cta",{"cta":247,"href":248,"title":249,"type":250},"Coder comme un senior →","https:\u002F\u002Fapp.kamanga.fr\u002Fforms\u002Fmentoring","Vous voulez acquérir le réflexe d'auditer chaque dépendance avant qu'elle entre dans votre repo ?","call",[252],{"type":28,"tag":29,"props":253,"children":254},{},[255],{"type":37,"value":256},"Savoir lire un arbre de dépendances, flairer la lib que Claude propose en retard de 18 mois, juger quand un bump major mérite un ADR : ça ne se lit pas, ça se travaille. En mentoring 1:1, on relit votre vraie config Dependabot ensemble, je vous montre les arbitrages que je fais sur mes propres projets, et vous repartez avec le jugement qui transforme une alerte en décision sereine.",{"type":28,"tag":62,"props":258,"children":259},{},[],{"type":28,"tag":66,"props":261,"children":263},{"id":262},"comment-je-configure-dependabot-étape-par-étape",[264],{"type":37,"value":265},"Comment je configure Dependabot, étape par étape",{"type":28,"tag":29,"props":267,"children":268},{},[269],{"type":37,"value":270},"Voici la méthode que j'applique sur crmcoaching, et que je redéploie ensuite quand j'arrive en mission dans une équipe qui n'a pas (ou peu) de gestion de dépendances. Pas une checklist générique, mais ce que je fais vraiment, dans l'ordre.",{"type":28,"tag":272,"props":273,"children":275},"h3",{"id":274},"étape-1-le-dependabotyml-craft",[276,278,283],{"type":37,"value":277},"Étape 1 : le ",{"type":28,"tag":45,"props":279,"children":281},{"className":280},[],[282],{"type":37,"value":58},{"type":37,"value":284}," craft",{"type":28,"tag":29,"props":286,"children":287},{},[288,290,296],{"type":37,"value":289},"Je crée (ou je refais) le fichier ",{"type":28,"tag":45,"props":291,"children":293},{"className":292},[],[294],{"type":37,"value":295},".github\u002Fdependabot.yml",{"type":37,"value":297},". Voici la version courte de ma configuration de référence, celle que j'utilise sur crmcoaching (TypeScript, géré avec pnpm) et que je décline ensuite en mission sur des codebases Java\u002FMaven :",{"type":28,"tag":299,"props":300,"children":304},"pre",{"className":301,"code":302,"language":303,"meta":8,"style":8},"language-yaml shiki shiki-themes catppuccin-frappe github-dark","version: 2\nupdates:\n  - package-ecosystem: \"npm\" # gère aussi pnpm et yarn\n    directory: \"\u002F\"\n    schedule:\n      interval: \"weekly\"\n      day: \"monday\"\n      time: \"09:00\"\n    open-pull-requests-limit: 5\n    groups:\n      minor-and-patch:\n        patterns: [\"*\"]\n        update-types: [\"minor\", \"patch\"]\n    labels: [\"dependencies\", \"auto-review\"]\n    reviewers: [\"kamanga\"]\n    ignore:\n      - dependency-name: \"next\"\n        update-types: [\"version-update:semver-major\"]\n\n  - package-ecosystem: \"docker\"\n    directory: \"\u002F\"\n    schedule:\n      interval: \"weekly\"\n\n  - package-ecosystem: \"github-actions\"\n    directory: \"\u002F\"\n    schedule:\n      interval: \"weekly\"\n","yaml",[305],{"type":28,"tag":45,"props":306,"children":307},{"__ignoreMap":8},[308,332,346,377,395,408,426,444,462,480,493,506,534,570,605,631,644,667,692,701,722,738,750,766,774,795,811,823],{"type":28,"tag":309,"props":310,"children":313},"span",{"class":311,"line":312},"line",1,[314,320,326],{"type":28,"tag":309,"props":315,"children":317},{"style":316},"--shiki-default:#8CAAEE;--shiki-dark:#85E89D",[318],{"type":37,"value":319},"version",{"type":28,"tag":309,"props":321,"children":323},{"style":322},"--shiki-default:#81C8BE;--shiki-dark:#E1E4E8",[324],{"type":37,"value":325},":",{"type":28,"tag":309,"props":327,"children":329},{"style":328},"--shiki-default:#EF9F76;--shiki-dark:#79B8FF",[330],{"type":37,"value":331}," 2\n",{"type":28,"tag":309,"props":333,"children":335},{"class":311,"line":334},2,[336,341],{"type":28,"tag":309,"props":337,"children":338},{"style":316},[339],{"type":37,"value":340},"updates",{"type":28,"tag":309,"props":342,"children":343},{"style":322},[344],{"type":37,"value":345},":\n",{"type":28,"tag":309,"props":347,"children":349},{"class":311,"line":348},3,[350,356,361,365,371],{"type":28,"tag":309,"props":351,"children":353},{"style":352},"--shiki-default:#949CBB;--shiki-dark:#E1E4E8",[354],{"type":37,"value":355},"  -",{"type":28,"tag":309,"props":357,"children":358},{"style":316},[359],{"type":37,"value":360}," package-ecosystem",{"type":28,"tag":309,"props":362,"children":363},{"style":322},[364],{"type":37,"value":325},{"type":28,"tag":309,"props":366,"children":368},{"style":367},"--shiki-default:#A6D189;--shiki-dark:#9ECBFF",[369],{"type":37,"value":370}," \"npm\"",{"type":28,"tag":309,"props":372,"children":374},{"style":373},"--shiki-default:#737994;--shiki-default-font-style:italic;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit",[375],{"type":37,"value":376}," # gère aussi pnpm et yarn\n",{"type":28,"tag":309,"props":378,"children":380},{"class":311,"line":379},4,[381,386,390],{"type":28,"tag":309,"props":382,"children":383},{"style":316},[384],{"type":37,"value":385},"    directory",{"type":28,"tag":309,"props":387,"children":388},{"style":322},[389],{"type":37,"value":325},{"type":28,"tag":309,"props":391,"children":392},{"style":367},[393],{"type":37,"value":394}," \"\u002F\"\n",{"type":28,"tag":309,"props":396,"children":398},{"class":311,"line":397},5,[399,404],{"type":28,"tag":309,"props":400,"children":401},{"style":316},[402],{"type":37,"value":403},"    schedule",{"type":28,"tag":309,"props":405,"children":406},{"style":322},[407],{"type":37,"value":345},{"type":28,"tag":309,"props":409,"children":411},{"class":311,"line":410},6,[412,417,421],{"type":28,"tag":309,"props":413,"children":414},{"style":316},[415],{"type":37,"value":416},"      interval",{"type":28,"tag":309,"props":418,"children":419},{"style":322},[420],{"type":37,"value":325},{"type":28,"tag":309,"props":422,"children":423},{"style":367},[424],{"type":37,"value":425}," \"weekly\"\n",{"type":28,"tag":309,"props":427,"children":429},{"class":311,"line":428},7,[430,435,439],{"type":28,"tag":309,"props":431,"children":432},{"style":316},[433],{"type":37,"value":434},"      day",{"type":28,"tag":309,"props":436,"children":437},{"style":322},[438],{"type":37,"value":325},{"type":28,"tag":309,"props":440,"children":441},{"style":367},[442],{"type":37,"value":443}," \"monday\"\n",{"type":28,"tag":309,"props":445,"children":447},{"class":311,"line":446},8,[448,453,457],{"type":28,"tag":309,"props":449,"children":450},{"style":316},[451],{"type":37,"value":452},"      time",{"type":28,"tag":309,"props":454,"children":455},{"style":322},[456],{"type":37,"value":325},{"type":28,"tag":309,"props":458,"children":459},{"style":367},[460],{"type":37,"value":461}," \"09:00\"\n",{"type":28,"tag":309,"props":463,"children":465},{"class":311,"line":464},9,[466,471,475],{"type":28,"tag":309,"props":467,"children":468},{"style":316},[469],{"type":37,"value":470},"    open-pull-requests-limit",{"type":28,"tag":309,"props":472,"children":473},{"style":322},[474],{"type":37,"value":325},{"type":28,"tag":309,"props":476,"children":477},{"style":328},[478],{"type":37,"value":479}," 5\n",{"type":28,"tag":309,"props":481,"children":483},{"class":311,"line":482},10,[484,489],{"type":28,"tag":309,"props":485,"children":486},{"style":316},[487],{"type":37,"value":488},"    groups",{"type":28,"tag":309,"props":490,"children":491},{"style":322},[492],{"type":37,"value":345},{"type":28,"tag":309,"props":494,"children":496},{"class":311,"line":495},11,[497,502],{"type":28,"tag":309,"props":498,"children":499},{"style":316},[500],{"type":37,"value":501},"      minor-and-patch",{"type":28,"tag":309,"props":503,"children":504},{"style":322},[505],{"type":37,"value":345},{"type":28,"tag":309,"props":507,"children":509},{"class":311,"line":508},12,[510,515,519,524,529],{"type":28,"tag":309,"props":511,"children":512},{"style":316},[513],{"type":37,"value":514},"        patterns",{"type":28,"tag":309,"props":516,"children":517},{"style":322},[518],{"type":37,"value":325},{"type":28,"tag":309,"props":520,"children":521},{"style":352},[522],{"type":37,"value":523}," [",{"type":28,"tag":309,"props":525,"children":526},{"style":367},[527],{"type":37,"value":528},"\"*\"",{"type":28,"tag":309,"props":530,"children":531},{"style":352},[532],{"type":37,"value":533},"]\n",{"type":28,"tag":309,"props":535,"children":537},{"class":311,"line":536},13,[538,543,547,551,556,561,566],{"type":28,"tag":309,"props":539,"children":540},{"style":316},[541],{"type":37,"value":542},"        update-types",{"type":28,"tag":309,"props":544,"children":545},{"style":322},[546],{"type":37,"value":325},{"type":28,"tag":309,"props":548,"children":549},{"style":352},[550],{"type":37,"value":523},{"type":28,"tag":309,"props":552,"children":553},{"style":367},[554],{"type":37,"value":555},"\"minor\"",{"type":28,"tag":309,"props":557,"children":558},{"style":352},[559],{"type":37,"value":560},",",{"type":28,"tag":309,"props":562,"children":563},{"style":367},[564],{"type":37,"value":565}," \"patch\"",{"type":28,"tag":309,"props":567,"children":568},{"style":352},[569],{"type":37,"value":533},{"type":28,"tag":309,"props":571,"children":573},{"class":311,"line":572},14,[574,579,583,587,592,596,601],{"type":28,"tag":309,"props":575,"children":576},{"style":316},[577],{"type":37,"value":578},"    labels",{"type":28,"tag":309,"props":580,"children":581},{"style":322},[582],{"type":37,"value":325},{"type":28,"tag":309,"props":584,"children":585},{"style":352},[586],{"type":37,"value":523},{"type":28,"tag":309,"props":588,"children":589},{"style":367},[590],{"type":37,"value":591},"\"dependencies\"",{"type":28,"tag":309,"props":593,"children":594},{"style":352},[595],{"type":37,"value":560},{"type":28,"tag":309,"props":597,"children":598},{"style":367},[599],{"type":37,"value":600}," \"auto-review\"",{"type":28,"tag":309,"props":602,"children":603},{"style":352},[604],{"type":37,"value":533},{"type":28,"tag":309,"props":606,"children":608},{"class":311,"line":607},15,[609,614,618,622,627],{"type":28,"tag":309,"props":610,"children":611},{"style":316},[612],{"type":37,"value":613},"    reviewers",{"type":28,"tag":309,"props":615,"children":616},{"style":322},[617],{"type":37,"value":325},{"type":28,"tag":309,"props":619,"children":620},{"style":352},[621],{"type":37,"value":523},{"type":28,"tag":309,"props":623,"children":624},{"style":367},[625],{"type":37,"value":626},"\"kamanga\"",{"type":28,"tag":309,"props":628,"children":629},{"style":352},[630],{"type":37,"value":533},{"type":28,"tag":309,"props":632,"children":634},{"class":311,"line":633},16,[635,640],{"type":28,"tag":309,"props":636,"children":637},{"style":316},[638],{"type":37,"value":639},"    ignore",{"type":28,"tag":309,"props":641,"children":642},{"style":322},[643],{"type":37,"value":345},{"type":28,"tag":309,"props":645,"children":647},{"class":311,"line":646},17,[648,653,658,662],{"type":28,"tag":309,"props":649,"children":650},{"style":352},[651],{"type":37,"value":652},"      -",{"type":28,"tag":309,"props":654,"children":655},{"style":316},[656],{"type":37,"value":657}," dependency-name",{"type":28,"tag":309,"props":659,"children":660},{"style":322},[661],{"type":37,"value":325},{"type":28,"tag":309,"props":663,"children":664},{"style":367},[665],{"type":37,"value":666}," \"next\"\n",{"type":28,"tag":309,"props":668,"children":670},{"class":311,"line":669},18,[671,675,679,683,688],{"type":28,"tag":309,"props":672,"children":673},{"style":316},[674],{"type":37,"value":542},{"type":28,"tag":309,"props":676,"children":677},{"style":322},[678],{"type":37,"value":325},{"type":28,"tag":309,"props":680,"children":681},{"style":352},[682],{"type":37,"value":523},{"type":28,"tag":309,"props":684,"children":685},{"style":367},[686],{"type":37,"value":687},"\"version-update:semver-major\"",{"type":28,"tag":309,"props":689,"children":690},{"style":352},[691],{"type":37,"value":533},{"type":28,"tag":309,"props":693,"children":695},{"class":311,"line":694},19,[696],{"type":28,"tag":309,"props":697,"children":698},{"emptyLinePlaceholder":13},[699],{"type":37,"value":700},"\n",{"type":28,"tag":309,"props":702,"children":704},{"class":311,"line":703},20,[705,709,713,717],{"type":28,"tag":309,"props":706,"children":707},{"style":352},[708],{"type":37,"value":355},{"type":28,"tag":309,"props":710,"children":711},{"style":316},[712],{"type":37,"value":360},{"type":28,"tag":309,"props":714,"children":715},{"style":322},[716],{"type":37,"value":325},{"type":28,"tag":309,"props":718,"children":719},{"style":367},[720],{"type":37,"value":721}," \"docker\"\n",{"type":28,"tag":309,"props":723,"children":725},{"class":311,"line":724},21,[726,730,734],{"type":28,"tag":309,"props":727,"children":728},{"style":316},[729],{"type":37,"value":385},{"type":28,"tag":309,"props":731,"children":732},{"style":322},[733],{"type":37,"value":325},{"type":28,"tag":309,"props":735,"children":736},{"style":367},[737],{"type":37,"value":394},{"type":28,"tag":309,"props":739,"children":741},{"class":311,"line":740},22,[742,746],{"type":28,"tag":309,"props":743,"children":744},{"style":316},[745],{"type":37,"value":403},{"type":28,"tag":309,"props":747,"children":748},{"style":322},[749],{"type":37,"value":345},{"type":28,"tag":309,"props":751,"children":753},{"class":311,"line":752},23,[754,758,762],{"type":28,"tag":309,"props":755,"children":756},{"style":316},[757],{"type":37,"value":416},{"type":28,"tag":309,"props":759,"children":760},{"style":322},[761],{"type":37,"value":325},{"type":28,"tag":309,"props":763,"children":764},{"style":367},[765],{"type":37,"value":425},{"type":28,"tag":309,"props":767,"children":769},{"class":311,"line":768},24,[770],{"type":28,"tag":309,"props":771,"children":772},{"emptyLinePlaceholder":13},[773],{"type":37,"value":700},{"type":28,"tag":309,"props":775,"children":777},{"class":311,"line":776},25,[778,782,786,790],{"type":28,"tag":309,"props":779,"children":780},{"style":352},[781],{"type":37,"value":355},{"type":28,"tag":309,"props":783,"children":784},{"style":316},[785],{"type":37,"value":360},{"type":28,"tag":309,"props":787,"children":788},{"style":322},[789],{"type":37,"value":325},{"type":28,"tag":309,"props":791,"children":792},{"style":367},[793],{"type":37,"value":794}," \"github-actions\"\n",{"type":28,"tag":309,"props":796,"children":798},{"class":311,"line":797},26,[799,803,807],{"type":28,"tag":309,"props":800,"children":801},{"style":316},[802],{"type":37,"value":385},{"type":28,"tag":309,"props":804,"children":805},{"style":322},[806],{"type":37,"value":325},{"type":28,"tag":309,"props":808,"children":809},{"style":367},[810],{"type":37,"value":394},{"type":28,"tag":309,"props":812,"children":814},{"class":311,"line":813},27,[815,819],{"type":28,"tag":309,"props":816,"children":817},{"style":316},[818],{"type":37,"value":403},{"type":28,"tag":309,"props":820,"children":821},{"style":322},[822],{"type":37,"value":345},{"type":28,"tag":309,"props":824,"children":826},{"class":311,"line":825},28,[827,831,835],{"type":28,"tag":309,"props":828,"children":829},{"style":316},[830],{"type":37,"value":416},{"type":28,"tag":309,"props":832,"children":833},{"style":322},[834],{"type":37,"value":325},{"type":28,"tag":309,"props":836,"children":837},{"style":367},[838],{"type":37,"value":425},{"type":28,"tag":29,"props":840,"children":841},{},[842,844,850,852,858,860,865,867,872,874,879,881,886],{"type":37,"value":843},"Trois choses comptent dans cette configuration. D'abord le ",{"type":28,"tag":45,"props":845,"children":847},{"className":846},[],[848],{"type":37,"value":849},"groups",{"type":37,"value":851}," qui rassemble minor et patch en une seule PR : c'est ce qui fait passer un repo de 30 PR par semaine à 3. Ensuite le ",{"type":28,"tag":45,"props":853,"children":855},{"className":854},[],[856],{"type":37,"value":857},"open-pull-requests-limit: 5",{"type":37,"value":859}," qui force le réalisme, parce que personne ne traite 15 PR Dependabot en parallèle. Enfin le ",{"type":28,"tag":45,"props":861,"children":863},{"className":862},[],[864],{"type":37,"value":217},{"type":37,"value":866}," ciblé sur les majors risquées (ici les montées majeures de Next.js, que je veux préparer avec un ADR et une fenêtre de migration avant d'accepter), avec une règle stricte : tout ",{"type":28,"tag":45,"props":868,"children":870},{"className":869},[],[871],{"type":37,"value":217},{"type":37,"value":873}," doit être documenté dans un commentaire qui dit ",{"type":28,"tag":126,"props":875,"children":876},{},[877],{"type":37,"value":878},"pourquoi",{"type":37,"value":880}," il existe et ",{"type":28,"tag":126,"props":882,"children":883},{},[884],{"type":37,"value":885},"jusqu'à quand",{"type":37,"value":887}," il reste valide.",{"type":28,"tag":29,"props":889,"children":890},{},[891,893,899,901,907,909,914,916,921],{"type":37,"value":892},"En mission sur une codebase Java\u002FMaven, le quotidien du secteur bancaire, je remplace simplement ",{"type":28,"tag":45,"props":894,"children":896},{"className":895},[],[897],{"type":37,"value":898},"npm",{"type":37,"value":900}," par ",{"type":28,"tag":45,"props":902,"children":904},{"className":903},[],[905],{"type":37,"value":906},"maven",{"type":37,"value":908}," et l'",{"type":28,"tag":45,"props":910,"children":912},{"className":911},[],[913],{"type":37,"value":217},{"type":37,"value":915}," Next.js par un ",{"type":28,"tag":45,"props":917,"children":919},{"className":918},[],[920],{"type":37,"value":217},{"type":37,"value":922}," sur un bump de Spring Boot que je veux préparer avec un ADR. Le reste de la structure (groups, limit, schedule, labels) ne change pas. C'est ce qui fait qu'une fois la discipline acquise sur un repo, vous la portez en 10 minutes sur le suivant, quel que soit l'écosystème.",{"type":28,"tag":272,"props":924,"children":926},{"id":925},"étape-2-le-pipeline-dauto-merge-intelligent",[927],{"type":37,"value":928},"Étape 2 : le pipeline d'auto-merge intelligent",{"type":28,"tag":29,"props":930,"children":931},{},[932,934,940],{"type":37,"value":933},"Dependabot seul, c'est 50% du travail. Sans auto-merge, vous gardez la charge mentale de chaque PR. Voici ce que j'ajoute systématiquement, sous forme de GitHub Action ",{"type":28,"tag":45,"props":935,"children":937},{"className":936},[],[938],{"type":37,"value":939},".github\u002Fworkflows\u002Fdependabot-auto-merge.yml",{"type":37,"value":941}," :",{"type":28,"tag":148,"props":943,"children":944},{},[945,955,965],{"type":28,"tag":152,"props":946,"children":947},{},[948,953],{"type":28,"tag":33,"props":949,"children":950},{},[951],{"type":37,"value":952},"Patch",{"type":37,"value":954}," : auto-merge si la CI est verte. Pas de discussion. Une mise à jour de patch ne casse rien, sauf si la CI dit le contraire.",{"type":28,"tag":152,"props":956,"children":957},{},[958,963],{"type":28,"tag":33,"props":959,"children":960},{},[961],{"type":37,"value":962},"Minor",{"type":37,"value":964}," : review humaine obligatoire, mais rapide. 5 minutes pour lire le changelog et valider.",{"type":28,"tag":152,"props":966,"children":967},{},[968,973,975,981],{"type":28,"tag":33,"props":969,"children":970},{},[971],{"type":37,"value":972},"Major",{"type":37,"value":974}," : ADR obligatoire. Pas de bump de major sans une ",{"type":28,"tag":83,"props":976,"children":978},{"href":977},"\u002Ffr\u002Farchitecture-craft\u002Fadr-architecture-decision-record",[979],{"type":37,"value":980},"décision documentée par ADR",{"type":37,"value":982}," qui dit pourquoi, quel impact, et quel plan de rollback.",{"type":28,"tag":29,"props":984,"children":985},{},[986,988,993],{"type":37,"value":987},"Cette discipline tient parce qu'elle est asymétrique : on automatise le bas risque, on humanise le haut risque. C'est exactement ce que Martin Fowler décrit dans son article ",{"type":28,"tag":126,"props":989,"children":990},{},[991],{"type":37,"value":992},"ContinuousIntegration",{"type":37,"value":994}," : automatiser ce qui doit l'être pour libérer du temps pour ce qui ne peut pas l'être.",{"type":28,"tag":272,"props":996,"children":998},{"id":997},"étape-3-la-métrique-qui-compte-vraiment",[999],{"type":37,"value":1000},"Étape 3 : la métrique qui compte vraiment",{"type":28,"tag":29,"props":1002,"children":1003},{},[1004,1006,1011],{"type":37,"value":1005},"J'instaure une seule métrique de suivi : la ",{"type":28,"tag":45,"props":1007,"children":1009},{"className":1008},[],[1010],{"type":37,"value":201},{"type":37,"value":1012}," sur les CVE critiques. Pas le nombre de PR mergées, pas le pourcentage de dépendances à jour. Juste : combien de temps entre la disclosure d'une CVE critique et son fix en prod.",{"type":28,"tag":29,"props":1014,"children":1015},{},[1016],{"type":37,"value":1017},"Sur crmcoaching, je suis à 3 jours en moyenne entre la disclosure d'une CVE critique et son fix en prod. Au démarrage, sans discipline, j'étais à plusieurs semaines. En mission, je vois régulièrement des équipes partir de 40 jours et plus. La baisse n'est jamais linéaire, elle vient des trois leviers ci-dessus combinés.",{"type":28,"tag":62,"props":1019,"children":1020},{},[],{"type":28,"tag":66,"props":1022,"children":1024},{"id":1023},"les-3-erreurs-à-éviter",[1025],{"type":37,"value":1026},"Les 3 erreurs à éviter",{"type":28,"tag":29,"props":1028,"children":1029},{},[1030],{"type":37,"value":1031},"Toutes les équipes que j'ai accompagnées sur ce sujet sont passées par au moins une de ces trois erreurs. Évitez-vous le détour.",{"type":28,"tag":29,"props":1033,"children":1034},{},[1035,1047],{"type":28,"tag":33,"props":1036,"children":1037},{},[1038,1040,1045],{"type":37,"value":1039},"Erreur 1 : laisser Dependabot ouvrir 30 PR par semaine sans ",{"type":28,"tag":45,"props":1041,"children":1043},{"className":1042},[],[1044],{"type":37,"value":849},{"type":37,"value":1046},".",{"type":37,"value":1048}," Le bruit tue le signal. Les développeurs commencent à fermer les PR sans lire. C'est pire que pas de Dependabot du tout, parce que vous avez l'illusion d'être protégé.",{"type":28,"tag":29,"props":1050,"children":1051},{},[1052,1057],{"type":28,"tag":33,"props":1053,"children":1054},{},[1055],{"type":37,"value":1056},"Erreur 2 : auto-merger les minor et les major.",{"type":37,"value":1058}," C'est tentant, ça soulage la charge mentale, mais une seule mise à jour cassante en prod détruit toute la confiance dans le pipeline. Auto-merge sur le patch uniquement, sauf si vous avez une couverture de tests acceptance-level qui couvre vos vrais comportements métier.",{"type":28,"tag":29,"props":1060,"children":1061},{},[1062,1067,1069,1074,1076,1082,1084,1090],{"type":28,"tag":33,"props":1063,"children":1064},{},[1065],{"type":37,"value":1066},"Erreur 3 : oublier les dépendances transitives.",{"type":37,"value":1068}," Dependabot scanne ce qui est dans votre ",{"type":28,"tag":45,"props":1070,"children":1072},{"className":1071},[],[1073],{"type":37,"value":50},{"type":37,"value":1075}," ou votre ",{"type":28,"tag":45,"props":1077,"children":1079},{"className":1078},[],[1080],{"type":37,"value":1081},"pom.xml",{"type":37,"value":1083},". Mais les vulnérabilités se planquent souvent 3 ou 4 niveaux en dessous, dans des libs que vous n'avez jamais nommément ajoutées. C'est là que ",{"type":28,"tag":83,"props":1085,"children":1087},{"href":1086},"\u002Ffr\u002Fintelligence-artificielle\u002Fllm-securite-code-vulnerabilites",[1088],{"type":37,"value":1089},"les alertes de sécurité dédiées au code IA-généré",{"type":37,"value":1091}," complètent l'arsenal, pas en concurrent mais en complément.",{"type":28,"tag":62,"props":1093,"children":1094},{},[],{"type":28,"tag":66,"props":1096,"children":1098},{"id":1097},"ce-que-ça-change-concrètement",[1099],{"type":37,"value":1100},"Ce que ça change concrètement",{"type":28,"tag":29,"props":1102,"children":1103},{},[1104],{"type":37,"value":1105},"Sur les 4 dernières missions où j'ai déployé cette discipline, voici les chiffres avant\u002Faprès, mesurés sur 6 mois.",{"type":28,"tag":1107,"props":1108,"children":1109},"table",{},[1110,1134],{"type":28,"tag":1111,"props":1112,"children":1113},"thead",{},[1114],{"type":28,"tag":1115,"props":1116,"children":1117},"tr",{},[1118,1124,1129],{"type":28,"tag":1119,"props":1120,"children":1121},"th",{},[1122],{"type":37,"value":1123},"Métrique",{"type":28,"tag":1119,"props":1125,"children":1126},{},[1127],{"type":37,"value":1128},"Avant",{"type":28,"tag":1119,"props":1130,"children":1131},{},[1132],{"type":37,"value":1133},"Après 6 mois",{"type":28,"tag":1135,"props":1136,"children":1137},"tbody",{},[1138,1157,1175,1193],{"type":28,"tag":1115,"props":1139,"children":1140},{},[1141,1147,1152],{"type":28,"tag":1142,"props":1143,"children":1144},"td",{},[1145],{"type":37,"value":1146},"Time-to-patch CVE critique",{"type":28,"tag":1142,"props":1148,"children":1149},{},[1150],{"type":37,"value":1151},"32 jours en moyenne",{"type":28,"tag":1142,"props":1153,"children":1154},{},[1155],{"type":37,"value":1156},"6 jours en moyenne",{"type":28,"tag":1115,"props":1158,"children":1159},{},[1160,1165,1170],{"type":28,"tag":1142,"props":1161,"children":1162},{},[1163],{"type":37,"value":1164},"Nombre de PR Dependabot ouvertes plus de 14 jours",{"type":28,"tag":1142,"props":1166,"children":1167},{},[1168],{"type":37,"value":1169},"18 en moyenne",{"type":28,"tag":1142,"props":1171,"children":1172},{},[1173],{"type":37,"value":1174},"2 en moyenne",{"type":28,"tag":1115,"props":1176,"children":1177},{},[1178,1183,1188],{"type":28,"tag":1142,"props":1179,"children":1180},{},[1181],{"type":37,"value":1182},"Incidents prod liés à une CVE supply chain",{"type":28,"tag":1142,"props":1184,"children":1185},{},[1186],{"type":37,"value":1187},"2 par an",{"type":28,"tag":1142,"props":1189,"children":1190},{},[1191],{"type":37,"value":1192},"0",{"type":28,"tag":1115,"props":1194,"children":1195},{},[1196,1201,1206],{"type":28,"tag":1142,"props":1197,"children":1198},{},[1199],{"type":37,"value":1200},"Heures dev consacrées à la gestion des dépendances",{"type":28,"tag":1142,"props":1202,"children":1203},{},[1204],{"type":37,"value":1205},"6h par semaine",{"type":28,"tag":1142,"props":1207,"children":1208},{},[1209],{"type":37,"value":1210},"1h30 par semaine",{"type":28,"tag":29,"props":1212,"children":1213},{},[1214],{"type":37,"value":1215},"Le gain n'est pas que technique, il est économique. Une heure de dev senior coûte entre 80 et 150 euros chargée. Économiser 4 heures et demie par semaine, c'est 18 000 à 35 000 euros par an. Pour une équipe de 5 développeurs, cette discipline financière paie son installation en 3 semaines.",{"type":28,"tag":29,"props":1217,"children":1218},{},[1219],{"type":37,"value":1220},"C'est ce que je dis aux CTOs qui hésitent : Dependabot n'est pas un sujet d'engineering, c'est un sujet d'allocation de capital.",{"type":28,"tag":62,"props":1222,"children":1223},{},[],{"type":28,"tag":66,"props":1225,"children":1227},{"id":1226},"conclusion",[1228],{"type":37,"value":1229},"Conclusion",{"type":28,"tag":29,"props":1231,"children":1232},{},[1233],{"type":37,"value":1234},"Ce que je veux que vous reteniez de cet article, c'est que la gestion de dépendances n'est pas une tâche d'hygiène que vous traitez quand vous aurez le temps. C'est un processus craft, au même titre que la code review ou les tests. Et comme tout processus craft, il a besoin d'un squelette automatisé pour tenir dans la durée.",{"type":28,"tag":29,"props":1236,"children":1237},{},[1238],{"type":37,"value":1239},"L'IA accélère la production de code. Elle accélère aussi la production de dette de dépendances. Dependabot est un des rares outils où l'automatisation ne remplace pas le jugement : elle libère du temps pour l'exercer là où il compte vraiment, sur les majors, les CVE critiques, les choix architecturaux. C'est exactement ce que je cherche dans une bonne discipline craft.",{"type":28,"tag":29,"props":1241,"children":1242},{},[1243,1245,1250],{"type":37,"value":1244},"Si en lisant ces lignes vous avez reconnu votre situation, vous avez deux choix. Vous pouvez attendre votre prochain Log4Shell. Ou vous pouvez commencer lundi matin, par un seul fichier ",{"type":28,"tag":45,"props":1246,"children":1248},{"className":1247},[],[1249],{"type":37,"value":58},{"type":37,"value":1251}," versionné, et bâtir la suite.",{"type":28,"tag":245,"props":1253,"children":1258},{"cta":1254,"href":1255,"title":1256,"type":1257},"Les 100 pratiques que l'IA n'enseigne pas →","https:\u002F\u002Fkamanga.fr\u002Freferentiel-craft","La gestion de dépendances n'est qu'une des 100 pratiques qui font un code de senior","product",[1259],{"type":28,"tag":29,"props":1260,"children":1261},{},[1262],{"type":37,"value":1263},"Configurer Dependabot en craft, c'est une seule pratique parmi celles qui séparent un dev qui subit sa dette d'un dev qui la pilote. Le Craft Bundle réunit les 100 pratiques que j'applique pour coder propre, de la gestion de dépendances aux ADR en passant par la review : exactement celles que l'IA ne vous apprendra jamais, parce qu'elle ne les a jamais vues tenir en prod.",{"type":28,"tag":62,"props":1265,"children":1266},{},[],{"type":28,"tag":66,"props":1268,"children":1270},{"id":1269},"faq-sur-dependabot-et-la-gestion-de-dépendances",[1271],{"type":37,"value":1272},"FAQ sur Dependabot et la gestion de dépendances",{"type":28,"tag":1274,"props":1275,"children":1276},"details",{},[1277,1283],{"type":28,"tag":1278,"props":1279,"children":1280},"summary",{},[1281],{"type":37,"value":1282},"1. Dependabot ou Renovate : lequel choisir ?",{"type":28,"tag":29,"props":1284,"children":1285},{},[1286],{"type":37,"value":1287},"Dependabot est gratuit, intégré nativement à GitHub, et largement suffisant pour la majorité des équipes. Renovate est plus puissant (règles plus fines, plus d'écosystèmes, monorepo natif) mais demande plus de temps de configuration. Mon conseil : commencez par Dependabot. Si au bout de 6 mois vous trouvez ses limites (vous le saurez), passez à Renovate. Mais ne commencez pas par Renovate, vous perdrez 2 semaines avant la première PR utile.",{"type":28,"tag":1274,"props":1289,"children":1290},{},[1291,1296],{"type":28,"tag":1278,"props":1292,"children":1293},{},[1294],{"type":37,"value":1295},"2. Faut-il auto-merger les patch updates ?",{"type":28,"tag":29,"props":1297,"children":1298},{},[1299],{"type":37,"value":1300},"Oui, à une condition : votre CI doit être verte, complète, et fiable. Si votre couverture de tests est faible (moins de 60% sur les chemins critiques), n'auto-mergez rien. Renforcez d'abord les tests, puis activez l'auto-merge sur patch uniquement. Jamais sur minor ou major sans review humaine.",{"type":28,"tag":1274,"props":1302,"children":1303},{},[1304,1309],{"type":28,"tag":1278,"props":1305,"children":1306},{},[1307],{"type":37,"value":1308},"3. Comment gérer les dépendances qu'on ne peut pas mettre à jour (lock sur une vieille version) ?",{"type":28,"tag":29,"props":1310,"children":1311},{},[1312,1314,1319,1321,1326,1328,1333,1335,1340,1342,1348],{"type":37,"value":1313},"Utilisez le bloc ",{"type":28,"tag":45,"props":1315,"children":1317},{"className":1316},[],[1318],{"type":37,"value":217},{"type":37,"value":1320}," du ",{"type":28,"tag":45,"props":1322,"children":1324},{"className":1323},[],[1325],{"type":37,"value":58},{"type":37,"value":1327},", mais avec une règle stricte : tout ",{"type":28,"tag":45,"props":1329,"children":1331},{"className":1330},[],[1332],{"type":37,"value":217},{"type":37,"value":1334}," doit être documenté (commentaire YAML expliquant pourquoi et jusqu'à quand) et révisé tous les 3 mois. Un ",{"type":28,"tag":45,"props":1336,"children":1338},{"className":1337},[],[1339],{"type":37,"value":217},{"type":37,"value":1341}," non documenté devient une dette technique cachée. Vous remplacez un problème de sécurité par un problème d'oubli, ce qui est exactement le mécanisme décrit dans cet article sur ",{"type":28,"tag":83,"props":1343,"children":1345},{"href":1344},"\u002Ffr\u002Fdette-technique\u002Flegacy-code-evaluer-risque",[1346],{"type":37,"value":1347},"l'évaluation du risque legacy",{"type":37,"value":1046},{"type":28,"tag":1274,"props":1350,"children":1351},{},[1352,1357],{"type":28,"tag":1278,"props":1353,"children":1354},{},[1355],{"type":37,"value":1356},"4. Dependabot crée trop de PR, comment réduire le bruit ?",{"type":28,"tag":29,"props":1358,"children":1359},{},[1360,1362,1367,1369,1374,1376,1382,1384,1390,1392,1398],{"type":37,"value":1361},"Trois leviers, dans cet ordre. Premièrement, regroupez les minor et patch via la clé ",{"type":28,"tag":45,"props":1363,"children":1365},{"className":1364},[],[1366],{"type":37,"value":849},{"type":37,"value":1368},". C'est ce qui divise le bruit par 10. Deuxièmement, limitez avec ",{"type":28,"tag":45,"props":1370,"children":1372},{"className":1371},[],[1373],{"type":37,"value":857},{"type":37,"value":1375},". Troisièmement, espacez le ",{"type":28,"tag":45,"props":1377,"children":1379},{"className":1378},[],[1380],{"type":37,"value":1381},"schedule",{"type":37,"value":1383}," à ",{"type":28,"tag":45,"props":1385,"children":1387},{"className":1386},[],[1388],{"type":37,"value":1389},"weekly",{"type":37,"value":1391}," plutôt que ",{"type":28,"tag":45,"props":1393,"children":1395},{"className":1394},[],[1396],{"type":37,"value":1397},"daily",{"type":37,"value":1399},". Avec ces trois réglages, vous passez de 30 PR par semaine à 3 ou 4.",{"type":28,"tag":1274,"props":1401,"children":1402},{},[1403,1408],{"type":28,"tag":1278,"props":1404,"children":1405},{},[1406],{"type":37,"value":1407},"5. Et le code IA-généré qui pull des dépendances obsolètes ?",{"type":28,"tag":29,"props":1409,"children":1410},{},[1411],{"type":37,"value":1412},"C'est exactement le scénario contre lequel Dependabot protège. Claude pulle des libs qu'il connaît depuis son training data, souvent en retard de 12 à 18 mois sur la version courante. Dependabot rattrape ces écarts à la PR suivante. La discipline craft à ajouter : auditer chaque dépendance que Claude propose avant de l'accepter dans le code. C'est un réflexe à 30 secondes qui évite des heures de remédiation.",{"type":28,"tag":1274,"props":1414,"children":1415},{},[1416,1421],{"type":28,"tag":1278,"props":1417,"children":1418},{},[1419],{"type":37,"value":1420},"6. Quel est le ROI réel d'une bonne configuration Dependabot ?",{"type":28,"tag":29,"props":1422,"children":1423},{},[1424],{"type":37,"value":1425},"Sur les 4 missions où j'ai mesuré, le ROI se situe entre 18 000 et 35 000 euros par an pour une équipe de 5 développeurs. Le calcul est simple : 4 à 5 heures de dev économisées par semaine, à un coût chargé de 80 à 150 euros l'heure. Sans compter les incidents évités, dont le coût unitaire peut dépasser 50 000 euros pour une CVE critique en prod.",{"type":28,"tag":62,"props":1427,"children":1428},{},[],{"type":28,"tag":245,"props":1430,"children":1435},{"cta":1431,"href":1432,"title":1433,"type":1434},"Évaluer la maturité de mon équipe →","\u002Fmes-ressources","Ressource gratuite : Engineering Maturity Assessment","resource",[1436],{"type":28,"tag":29,"props":1437,"children":1438},{},[1439],{"type":37,"value":1440},"L'EMA est l'outil que je propose au début de chaque mission. Il mesure la maturité de votre équipe sur plusieurs axes engineering, dont la dette technique, le delivery, la gouvernance IA et l'architecture. La gestion de dépendances en est un sous-axe. Quelques minutes pour avoir une vision claire de votre passif engineering, et savoir où concentrer vos efforts en priorité.",{"type":28,"tag":1442,"props":1443,"children":1444},"style",{},[1445],{"type":37,"value":1446},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":8,"searchDepth":334,"depth":334,"links":1448},[1449,1450,1451,1457,1458,1459,1460],{"id":68,"depth":334,"text":71},{"id":138,"depth":334,"text":141},{"id":262,"depth":334,"text":265,"children":1452},[1453,1455,1456],{"id":274,"depth":348,"text":1454},"Étape 1 : le dependabot.yml craft",{"id":925,"depth":348,"text":928},{"id":997,"depth":348,"text":1000},{"id":1023,"depth":334,"text":1026},{"id":1097,"depth":334,"text":1100},{"id":1226,"depth":334,"text":1229},{"id":1269,"depth":334,"text":1272},"markdown","content:fr:dette-technique:dependabot-craft-gestion-dependances.md","content","fr\u002Fdette-technique\u002Fdependabot-craft-gestion-dependances.md","fr\u002Fdette-technique\u002Fdependabot-craft-gestion-dependances","md",{"_path":1086,"_dir":1468,"_draft":7,"_partial":7,"_locale":8,"title":1469,"description":1470,"id":669,"date":1471,"listed":13,"nocomments":7,"hidden":7,"categories":1472,"tags":1473,"cover":1475,"readingTime":1476,"body":1481,"_type":1461,"_id":2962,"_source":1463,"_file":2963,"_stem":2964,"_extension":1466},"intelligence-artificielle","LLMs et sécurité du code : ce qu'il faut savoir","Les LLMs génèrent du code fonctionnel et vulnérable avec la même fluidité. Les vecteurs d'attaque spécifiques au code IA-assisté et les garde-fous à mettre en place, vécus en solo sur un SaaS NestJS\u002FPrisma.","2026-02-13",[1468],[17,16,1474],"code-review","covers\u002Farticles\u002Fllm-securite-code.jpg",{"text":1477,"minutes":1478,"time":1479,"words":1480},"9 min read",8.05,483000,1610,{"type":25,"children":1482,"toc":2948},[1483,1496,1501,1509,1535,1538,1544,1549,1554,1557,1563,1568,1573,1900,1917,1922,1925,1931,1936,1941,2602,2607,2612,2629,2632,2638,2643,2653,2663,2711,2723,2726,2732,2738,2749,2755,2768,2797,2803,2808,2814,2827,2833,2838,2843,2848,2857,2860,2866,2879,2892,2905,2918,2931,2934,2944],{"type":28,"tag":29,"props":1484,"children":1485},{},[1486,1488,1494],{"type":37,"value":1487},"En construisant crmcoaching (mon SaaS pour coachs professionnels), je développe seul avec Claude Code comme assistant principal. Un jour, Claude a généré un service NestJS pour récupérer les clients d'un coach. Le code compilait, les tests Vitest passaient, le type Prisma était correct. Sauf que la requête était construite par concaténation de chaîne via ",{"type":28,"tag":45,"props":1489,"children":1491},{"className":1490},[],[1492],{"type":37,"value":1493},"$queryRawUnsafe",{"type":37,"value":1495},", et que la clé Stripe utilisée pour initialiser le SDK était écrite en dur dans le fichier de service, en clair, versionnée dans Git.",{"type":28,"tag":29,"props":1497,"children":1498},{},[1499],{"type":37,"value":1500},"Ce n'était pas de la malveillance de la part de Claude. C'était la reproduction statistique des patterns présents dans son corpus d'entraînement.",{"type":28,"tag":29,"props":1502,"children":1503},{},[1504],{"type":28,"tag":33,"props":1505,"children":1506},{},[1507],{"type":37,"value":1508},"Un LLM génère du code injectable et du code parfaitement sécurisé avec la même confiance syntaxique. Il ne distingue pas les deux. Votre processus de review doit le faire, et en 2026, la plupart des développeurs solos ou en petite équipe n'ont pas adapté leur review au code IA-assisté.",{"type":28,"tag":29,"props":1510,"children":1511},{},[1512,1514,1519,1521,1526,1528,1533],{"type":37,"value":1513},"Deux études publiées en 2023 ont documenté le problème. ",{"type":28,"tag":33,"props":1515,"children":1516},{},[1517],{"type":37,"value":1518},"Stanford University",{"type":37,"value":1520}," : 40 % du code suggéré dans des contextes de sécurité spécifiques contient des vulnérabilités. ",{"type":28,"tag":33,"props":1522,"children":1523},{},[1524],{"type":37,"value":1525},"NYU",{"type":37,"value":1527}," : les développeurs qui utilisent des assistants IA tendent à produire du code ",{"type":28,"tag":33,"props":1529,"children":1530},{},[1531],{"type":37,"value":1532},"moins sécurisé",{"type":37,"value":1534}," que sans assistant, parce qu'ils font plus confiance au code généré et le reviewent moins rigoureusement. Ce chiffre est contre-intuitif mais cohérent avec ce que j'observe au quotidien sur crmcoaching.",{"type":28,"tag":62,"props":1536,"children":1537},{},[],{"type":28,"tag":66,"props":1539,"children":1541},{"id":1540},"pourquoi-les-llms-génèrent-du-code-vulnérable",[1542],{"type":37,"value":1543},"Pourquoi les LLMs génèrent du code vulnérable",{"type":28,"tag":29,"props":1545,"children":1546},{},[1547],{"type":37,"value":1548},"L'explication est simple mais souvent ignorée : les LLMs sont entraînés sur du code public. Le code public contient des vulnérabilités courantes. Les LLMs reproduisent les patterns du code sur lequel ils ont été entraînés.",{"type":28,"tag":29,"props":1550,"children":1551},{},[1552],{"type":37,"value":1553},"Le résultat : les patterns vulnérables les plus fréquents dans le code public (injections, secrets hardcodés, dépendances non vérifiées) sont aussi les plus fréquemment générés par les LLMs. Pas par malveillance. Par statistique.",{"type":28,"tag":62,"props":1555,"children":1556},{},[],{"type":28,"tag":66,"props":1558,"children":1560},{"id":1559},"vulnérabilité-type-1-injections-sql-prompt-command",[1561],{"type":37,"value":1562},"Vulnérabilité type 1 : Injections (SQL, prompt, command)",{"type":28,"tag":29,"props":1564,"children":1565},{},[1566],{"type":37,"value":1567},"Les LLMs génèrent facilement du code vulnérable aux injections, surtout quand le prompt ne spécifie pas explicitement l'usage de requêtes paramétrées.",{"type":28,"tag":29,"props":1569,"children":1570},{},[1571],{"type":37,"value":1572},"Sur crmcoaching, Claude a généré ce service pour filtrer des clients par nom :",{"type":28,"tag":299,"props":1574,"children":1578},{"className":1575,"code":1576,"language":1577,"meta":8,"style":8},"language-typescript shiki shiki-themes catppuccin-frappe github-dark","\u002F\u002F ❌ Code généré par Claude sans précision sur la sécurité\n\u002F\u002F apps\u002Fapi\u002Fsrc\u002Finfrastructure\u002Fprisma\u002Fclient.repository.ts\nasync findByName(name: string): Promise\u003CClient[]> {\n  \u002F\u002F $queryRawUnsafe concatène directement l'input utilisateur : SQL injection\n  return this.prisma.$queryRawUnsafe(\n    `SELECT * FROM \"Client\" WHERE name = '${name}'`\n  );\n}\n\n\u002F\u002F ✅ Code correct : requête paramétrée via $queryRaw (tagged template)\nasync findByName(name: string): Promise\u003CClient[]> {\n  return this.prisma.$queryRaw\u003CClient[]>`\n    SELECT * FROM \"Client\" WHERE name = ${name}\n  `;\n}\n\n\u002F\u002F ✅ Mieux encore : utiliser l'ORM Prisma directement\nasync findByName(name: string): Promise\u003CClient[]> {\n  return this.prisma.client.findMany({\n    where: { name },\n  });\n}\n","typescript",[1579],{"type":28,"tag":45,"props":1580,"children":1581},{"__ignoreMap":8},[1582,1590,1598,1645,1653,1661,1690,1698,1706,1713,1721,1758,1766,1774,1782,1789,1796,1804,1839,1852,1880,1893],{"type":28,"tag":309,"props":1583,"children":1584},{"class":311,"line":312},[1585],{"type":28,"tag":309,"props":1586,"children":1587},{"style":373},[1588],{"type":37,"value":1589},"\u002F\u002F ❌ Code généré par Claude sans précision sur la sécurité\n",{"type":28,"tag":309,"props":1591,"children":1592},{"class":311,"line":334},[1593],{"type":28,"tag":309,"props":1594,"children":1595},{"style":373},[1596],{"type":37,"value":1597},"\u002F\u002F apps\u002Fapi\u002Fsrc\u002Finfrastructure\u002Fprisma\u002Fclient.repository.ts\n",{"type":28,"tag":309,"props":1599,"children":1600},{"class":311,"line":348},[1601,1607,1613,1618,1624,1630,1635,1640],{"type":28,"tag":309,"props":1602,"children":1604},{"style":1603},"--shiki-default:#C6D0F5;--shiki-dark:#E1E4E8",[1605],{"type":37,"value":1606},"async ",{"type":28,"tag":309,"props":1608,"children":1610},{"style":1609},"--shiki-default:#8CAAEE;--shiki-default-font-style:italic;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit",[1611],{"type":37,"value":1612},"findByName",{"type":28,"tag":309,"props":1614,"children":1615},{"style":1603},[1616],{"type":37,"value":1617},"(name: string): ",{"type":28,"tag":309,"props":1619,"children":1621},{"style":1620},"--shiki-default:#E5C890;--shiki-default-font-style:italic;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit",[1622],{"type":37,"value":1623},"Promise",{"type":28,"tag":309,"props":1625,"children":1627},{"style":1626},"--shiki-default:#81C8BE;--shiki-dark:#F97583",[1628],{"type":37,"value":1629},"\u003C",{"type":28,"tag":309,"props":1631,"children":1632},{"style":1603},[1633],{"type":37,"value":1634},"Client[]",{"type":28,"tag":309,"props":1636,"children":1637},{"style":1626},[1638],{"type":37,"value":1639},">",{"type":28,"tag":309,"props":1641,"children":1642},{"style":352},[1643],{"type":37,"value":1644}," {\n",{"type":28,"tag":309,"props":1646,"children":1647},{"class":311,"line":379},[1648],{"type":28,"tag":309,"props":1649,"children":1650},{"style":373},[1651],{"type":37,"value":1652},"  \u002F\u002F $queryRawUnsafe concatène directement l'input utilisateur : SQL injection\n",{"type":28,"tag":309,"props":1654,"children":1655},{"class":311,"line":397},[1656],{"type":28,"tag":309,"props":1657,"children":1658},{"style":1603},[1659],{"type":37,"value":1660},"  return this.prisma.$queryRawUnsafe(\n",{"type":28,"tag":309,"props":1662,"children":1663},{"class":311,"line":410},[1664,1669,1675,1680,1685],{"type":28,"tag":309,"props":1665,"children":1666},{"style":367},[1667],{"type":37,"value":1668},"    `SELECT * FROM \"Client\" WHERE name = '",{"type":28,"tag":309,"props":1670,"children":1672},{"style":1671},"--shiki-default:#949CBB;--shiki-dark:#9ECBFF",[1673],{"type":37,"value":1674},"${",{"type":28,"tag":309,"props":1676,"children":1677},{"style":1603},[1678],{"type":37,"value":1679},"name",{"type":28,"tag":309,"props":1681,"children":1682},{"style":1671},[1683],{"type":37,"value":1684},"}",{"type":28,"tag":309,"props":1686,"children":1687},{"style":367},[1688],{"type":37,"value":1689},"'`\n",{"type":28,"tag":309,"props":1691,"children":1692},{"class":311,"line":428},[1693],{"type":28,"tag":309,"props":1694,"children":1695},{"style":1603},[1696],{"type":37,"value":1697},"  );\n",{"type":28,"tag":309,"props":1699,"children":1700},{"class":311,"line":446},[1701],{"type":28,"tag":309,"props":1702,"children":1703},{"style":1603},[1704],{"type":37,"value":1705},"}\n",{"type":28,"tag":309,"props":1707,"children":1708},{"class":311,"line":464},[1709],{"type":28,"tag":309,"props":1710,"children":1711},{"emptyLinePlaceholder":13},[1712],{"type":37,"value":700},{"type":28,"tag":309,"props":1714,"children":1715},{"class":311,"line":482},[1716],{"type":28,"tag":309,"props":1717,"children":1718},{"style":373},[1719],{"type":37,"value":1720},"\u002F\u002F ✅ Code correct : requête paramétrée via $queryRaw (tagged template)\n",{"type":28,"tag":309,"props":1722,"children":1723},{"class":311,"line":495},[1724,1729,1733,1738,1742,1746,1750,1754],{"type":28,"tag":309,"props":1725,"children":1726},{"style":1603},[1727],{"type":37,"value":1728},"async findByName(name",{"type":28,"tag":309,"props":1730,"children":1731},{"style":322},[1732],{"type":37,"value":325},{"type":28,"tag":309,"props":1734,"children":1735},{"style":1603},[1736],{"type":37,"value":1737}," string): ",{"type":28,"tag":309,"props":1739,"children":1740},{"style":1620},[1741],{"type":37,"value":1623},{"type":28,"tag":309,"props":1743,"children":1744},{"style":1626},[1745],{"type":37,"value":1629},{"type":28,"tag":309,"props":1747,"children":1748},{"style":1603},[1749],{"type":37,"value":1634},{"type":28,"tag":309,"props":1751,"children":1752},{"style":1626},[1753],{"type":37,"value":1639},{"type":28,"tag":309,"props":1755,"children":1756},{"style":352},[1757],{"type":37,"value":1644},{"type":28,"tag":309,"props":1759,"children":1760},{"class":311,"line":508},[1761],{"type":28,"tag":309,"props":1762,"children":1763},{"style":1603},[1764],{"type":37,"value":1765},"  return this.prisma.$queryRaw\u003CClient[]>`\n",{"type":28,"tag":309,"props":1767,"children":1768},{"class":311,"line":536},[1769],{"type":28,"tag":309,"props":1770,"children":1771},{"style":1603},[1772],{"type":37,"value":1773},"    SELECT * FROM \"Client\" WHERE name = ${name}\n",{"type":28,"tag":309,"props":1775,"children":1776},{"class":311,"line":572},[1777],{"type":28,"tag":309,"props":1778,"children":1779},{"style":1603},[1780],{"type":37,"value":1781},"  `;\n",{"type":28,"tag":309,"props":1783,"children":1784},{"class":311,"line":607},[1785],{"type":28,"tag":309,"props":1786,"children":1787},{"style":1603},[1788],{"type":37,"value":1705},{"type":28,"tag":309,"props":1790,"children":1791},{"class":311,"line":633},[1792],{"type":28,"tag":309,"props":1793,"children":1794},{"emptyLinePlaceholder":13},[1795],{"type":37,"value":700},{"type":28,"tag":309,"props":1797,"children":1798},{"class":311,"line":646},[1799],{"type":28,"tag":309,"props":1800,"children":1801},{"style":373},[1802],{"type":37,"value":1803},"\u002F\u002F ✅ Mieux encore : utiliser l'ORM Prisma directement\n",{"type":28,"tag":309,"props":1805,"children":1806},{"class":311,"line":669},[1807,1811,1815,1819,1823,1827,1831,1835],{"type":28,"tag":309,"props":1808,"children":1809},{"style":1603},[1810],{"type":37,"value":1728},{"type":28,"tag":309,"props":1812,"children":1813},{"style":322},[1814],{"type":37,"value":325},{"type":28,"tag":309,"props":1816,"children":1817},{"style":1603},[1818],{"type":37,"value":1737},{"type":28,"tag":309,"props":1820,"children":1821},{"style":1620},[1822],{"type":37,"value":1623},{"type":28,"tag":309,"props":1824,"children":1825},{"style":1626},[1826],{"type":37,"value":1629},{"type":28,"tag":309,"props":1828,"children":1829},{"style":1603},[1830],{"type":37,"value":1634},{"type":28,"tag":309,"props":1832,"children":1833},{"style":1626},[1834],{"type":37,"value":1639},{"type":28,"tag":309,"props":1836,"children":1837},{"style":352},[1838],{"type":37,"value":1644},{"type":28,"tag":309,"props":1840,"children":1841},{"class":311,"line":694},[1842,1847],{"type":28,"tag":309,"props":1843,"children":1844},{"style":1603},[1845],{"type":37,"value":1846},"  return this.prisma.client.findMany(",{"type":28,"tag":309,"props":1848,"children":1849},{"style":352},[1850],{"type":37,"value":1851},"{\n",{"type":28,"tag":309,"props":1853,"children":1854},{"class":311,"line":703},[1855,1861,1865,1870,1875],{"type":28,"tag":309,"props":1856,"children":1858},{"style":1857},"--shiki-default:#C6D0F5;--shiki-dark:#B392F0",[1859],{"type":37,"value":1860},"    where",{"type":28,"tag":309,"props":1862,"children":1863},{"style":352},[1864],{"type":37,"value":325},{"type":28,"tag":309,"props":1866,"children":1867},{"style":352},[1868],{"type":37,"value":1869}," {",{"type":28,"tag":309,"props":1871,"children":1872},{"style":1603},[1873],{"type":37,"value":1874}," name ",{"type":28,"tag":309,"props":1876,"children":1877},{"style":352},[1878],{"type":37,"value":1879},"},\n",{"type":28,"tag":309,"props":1881,"children":1882},{"class":311,"line":724},[1883,1888],{"type":28,"tag":309,"props":1884,"children":1885},{"style":352},[1886],{"type":37,"value":1887},"  }",{"type":28,"tag":309,"props":1889,"children":1890},{"style":1603},[1891],{"type":37,"value":1892},");\n",{"type":28,"tag":309,"props":1894,"children":1895},{"class":311,"line":740},[1896],{"type":28,"tag":309,"props":1897,"children":1898},{"style":352},[1899],{"type":37,"value":1705},{"type":28,"tag":29,"props":1901,"children":1902},{},[1903,1908,1910,1915],{"type":28,"tag":33,"props":1904,"children":1905},{},[1906],{"type":37,"value":1907},"La prompt injection",{"type":37,"value":1909}," est spécifique au code qui intègre des LLMs dans des applications : si votre application passe de l'input utilisateur directement dans un prompt, un attaquant peut modifier le comportement du modèle via des instructions injectées. C'est une vulnérabilité nouvelle, documentée par l'",{"type":28,"tag":33,"props":1911,"children":1912},{},[1913],{"type":37,"value":1914},"OWASP Top 10 for LLM Applications",{"type":37,"value":1916}," depuis 2023.",{"type":28,"tag":29,"props":1918,"children":1919},{},[1920],{"type":37,"value":1921},"Garde-fou : lors de la review de tout code qui touche à la gestion des inputs utilisateurs, vérifier systématiquement que les requêtes sont paramétrées et que les inputs ne sont pas interpolés directement dans des strings.",{"type":28,"tag":62,"props":1923,"children":1924},{},[],{"type":28,"tag":66,"props":1926,"children":1928},{"id":1927},"vulnérabilité-type-2-gestion-des-secrets-et-credentials",[1929],{"type":37,"value":1930},"Vulnérabilité type 2 : Gestion des secrets et credentials",{"type":28,"tag":29,"props":1932,"children":1933},{},[1934],{"type":37,"value":1935},"C'est le pattern de vulnérabilité le plus fréquemment généré par les LLMs : credentials hardcodées, tokens dans les logs, secrets dans les fichiers de configuration versionnés.",{"type":28,"tag":29,"props":1937,"children":1938},{},[1939],{"type":37,"value":1940},"Sur crmcoaching, voici exactement ce que Claude a généré lors de l'initialisation du service Stripe :",{"type":28,"tag":299,"props":1942,"children":1944},{"className":1575,"code":1943,"language":1577,"meta":8,"style":8},"\u002F\u002F ❌ Pattern généré par Claude : clé Stripe hardcodée dans le service NestJS\n\u002F\u002F apps\u002Fapi\u002Fsrc\u002Finfrastructure\u002Fstripe\u002Fstripe.service.ts\n@Injectable()\nexport class StripeService {\n  private stripe = new Stripe(\"sk_live_XXXXXXXXXXXXXXXXXXXXXXXX\"); \u002F\u002F ❌ hardcodé\n\n  async createCheckoutSession(priceId: string) { \u002F* ... *\u002F }\n}\n\n\u002F\u002F ❌ Pattern de logging qui expose un secret Brevo\n@Injectable()\nexport class EmailService {\n  sendWelcome(email: string) {\n    this.logger.log(`Sending via Brevo key: ${process.env.BREVO_API_KEY}`); \u002F\u002F ❌\n  }\n}\n\n\u002F\u002F ✅ Pattern correct : injection de config NestJS via variables d'environnement\n@Injectable()\nexport class StripeService {\n  private stripe: Stripe;\n\n  constructor(private readonly configService: ConfigService) {\n    this.stripe = new Stripe(\n      this.configService.getOrThrow\u003Cstring>(\"STRIPE_SECRET_KEY\")\n    );\n  }\n\n  async createCheckoutSession(priceId: string) { \u002F* ... *\u002F }\n}\n",[1945],{"type":28,"tag":45,"props":1946,"children":1947},{"__ignoreMap":8},[1948,1956,1964,1984,2008,2063,2070,2121,2128,2135,2143,2158,2178,2211,2297,2305,2312,2319,2327,2342,2361,2385,2392,2436,2470,2524,2536,2543,2550,2594],{"type":28,"tag":309,"props":1949,"children":1950},{"class":311,"line":312},[1951],{"type":28,"tag":309,"props":1952,"children":1953},{"style":373},[1954],{"type":37,"value":1955},"\u002F\u002F ❌ Pattern généré par Claude : clé Stripe hardcodée dans le service NestJS\n",{"type":28,"tag":309,"props":1957,"children":1958},{"class":311,"line":334},[1959],{"type":28,"tag":309,"props":1960,"children":1961},{"style":373},[1962],{"type":37,"value":1963},"\u002F\u002F apps\u002Fapi\u002Fsrc\u002Finfrastructure\u002Fstripe\u002Fstripe.service.ts\n",{"type":28,"tag":309,"props":1965,"children":1966},{"class":311,"line":348},[1967,1973,1978],{"type":28,"tag":309,"props":1968,"children":1970},{"style":1969},"--shiki-default:#8CAAEE;--shiki-default-font-style:italic;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit",[1971],{"type":37,"value":1972},"@",{"type":28,"tag":309,"props":1974,"children":1975},{"style":1609},[1976],{"type":37,"value":1977},"Injectable",{"type":28,"tag":309,"props":1979,"children":1981},{"style":1980},"--shiki-default:#EF9F76;--shiki-dark:#E1E4E8",[1982],{"type":37,"value":1983},"()\n",{"type":28,"tag":309,"props":1985,"children":1986},{"class":311,"line":379},[1987,1993,1998,2004],{"type":28,"tag":309,"props":1988,"children":1990},{"style":1989},"--shiki-default:#CA9EE6;--shiki-dark:#F97583",[1991],{"type":37,"value":1992},"export",{"type":28,"tag":309,"props":1994,"children":1995},{"style":1989},[1996],{"type":37,"value":1997}," class",{"type":28,"tag":309,"props":1999,"children":2001},{"style":2000},"--shiki-default:#E5C890;--shiki-default-font-style:italic;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit",[2002],{"type":37,"value":2003}," StripeService",{"type":28,"tag":309,"props":2005,"children":2006},{"style":352},[2007],{"type":37,"value":1644},{"type":28,"tag":309,"props":2009,"children":2010},{"class":311,"line":397},[2011,2016,2022,2027,2033,2038,2043,2048,2053,2058],{"type":28,"tag":309,"props":2012,"children":2013},{"style":1989},[2014],{"type":37,"value":2015},"  private",{"type":28,"tag":309,"props":2017,"children":2019},{"style":2018},"--shiki-default:#C6D0F5;--shiki-dark:#FFAB70",[2020],{"type":37,"value":2021}," stripe",{"type":28,"tag":309,"props":2023,"children":2024},{"style":1626},[2025],{"type":37,"value":2026}," =",{"type":28,"tag":309,"props":2028,"children":2030},{"style":2029},"--shiki-default:#CA9EE6;--shiki-default-font-weight:bold;--shiki-dark:#F97583;--shiki-dark-font-weight:inherit",[2031],{"type":37,"value":2032}," new",{"type":28,"tag":309,"props":2034,"children":2035},{"style":1609},[2036],{"type":37,"value":2037}," Stripe",{"type":28,"tag":309,"props":2039,"children":2040},{"style":1603},[2041],{"type":37,"value":2042},"(",{"type":28,"tag":309,"props":2044,"children":2045},{"style":367},[2046],{"type":37,"value":2047},"\"sk_live_XXXXXXXXXXXXXXXXXXXXXXXX\"",{"type":28,"tag":309,"props":2049,"children":2050},{"style":1603},[2051],{"type":37,"value":2052},")",{"type":28,"tag":309,"props":2054,"children":2055},{"style":352},[2056],{"type":37,"value":2057},";",{"type":28,"tag":309,"props":2059,"children":2060},{"style":373},[2061],{"type":37,"value":2062}," \u002F\u002F ❌ hardcodé\n",{"type":28,"tag":309,"props":2064,"children":2065},{"class":311,"line":410},[2066],{"type":28,"tag":309,"props":2067,"children":2068},{"emptyLinePlaceholder":13},[2069],{"type":37,"value":700},{"type":28,"tag":309,"props":2071,"children":2072},{"class":311,"line":428},[2073,2078,2083,2087,2093,2097,2103,2107,2111,2116],{"type":28,"tag":309,"props":2074,"children":2075},{"style":1989},[2076],{"type":37,"value":2077},"  async",{"type":28,"tag":309,"props":2079,"children":2080},{"style":1609},[2081],{"type":37,"value":2082}," createCheckoutSession",{"type":28,"tag":309,"props":2084,"children":2085},{"style":352},[2086],{"type":37,"value":2042},{"type":28,"tag":309,"props":2088,"children":2090},{"style":2089},"--shiki-default:#EA999C;--shiki-default-font-style:italic;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit",[2091],{"type":37,"value":2092},"priceId",{"type":28,"tag":309,"props":2094,"children":2095},{"style":1626},[2096],{"type":37,"value":325},{"type":28,"tag":309,"props":2098,"children":2100},{"style":2099},"--shiki-default:#CA9EE6;--shiki-dark:#79B8FF",[2101],{"type":37,"value":2102}," string",{"type":28,"tag":309,"props":2104,"children":2105},{"style":352},[2106],{"type":37,"value":2052},{"type":28,"tag":309,"props":2108,"children":2109},{"style":352},[2110],{"type":37,"value":1869},{"type":28,"tag":309,"props":2112,"children":2113},{"style":373},[2114],{"type":37,"value":2115}," \u002F* ... *\u002F",{"type":28,"tag":309,"props":2117,"children":2118},{"style":352},[2119],{"type":37,"value":2120}," }\n",{"type":28,"tag":309,"props":2122,"children":2123},{"class":311,"line":446},[2124],{"type":28,"tag":309,"props":2125,"children":2126},{"style":352},[2127],{"type":37,"value":1705},{"type":28,"tag":309,"props":2129,"children":2130},{"class":311,"line":464},[2131],{"type":28,"tag":309,"props":2132,"children":2133},{"emptyLinePlaceholder":13},[2134],{"type":37,"value":700},{"type":28,"tag":309,"props":2136,"children":2137},{"class":311,"line":482},[2138],{"type":28,"tag":309,"props":2139,"children":2140},{"style":373},[2141],{"type":37,"value":2142},"\u002F\u002F ❌ Pattern de logging qui expose un secret Brevo\n",{"type":28,"tag":309,"props":2144,"children":2145},{"class":311,"line":495},[2146,2150,2154],{"type":28,"tag":309,"props":2147,"children":2148},{"style":1969},[2149],{"type":37,"value":1972},{"type":28,"tag":309,"props":2151,"children":2152},{"style":1609},[2153],{"type":37,"value":1977},{"type":28,"tag":309,"props":2155,"children":2156},{"style":1980},[2157],{"type":37,"value":1983},{"type":28,"tag":309,"props":2159,"children":2160},{"class":311,"line":508},[2161,2165,2169,2174],{"type":28,"tag":309,"props":2162,"children":2163},{"style":1989},[2164],{"type":37,"value":1992},{"type":28,"tag":309,"props":2166,"children":2167},{"style":1989},[2168],{"type":37,"value":1997},{"type":28,"tag":309,"props":2170,"children":2171},{"style":2000},[2172],{"type":37,"value":2173}," EmailService",{"type":28,"tag":309,"props":2175,"children":2176},{"style":352},[2177],{"type":37,"value":1644},{"type":28,"tag":309,"props":2179,"children":2180},{"class":311,"line":536},[2181,2186,2190,2195,2199,2203,2207],{"type":28,"tag":309,"props":2182,"children":2183},{"style":1609},[2184],{"type":37,"value":2185},"  sendWelcome",{"type":28,"tag":309,"props":2187,"children":2188},{"style":352},[2189],{"type":37,"value":2042},{"type":28,"tag":309,"props":2191,"children":2192},{"style":2089},[2193],{"type":37,"value":2194},"email",{"type":28,"tag":309,"props":2196,"children":2197},{"style":1626},[2198],{"type":37,"value":325},{"type":28,"tag":309,"props":2200,"children":2201},{"style":2099},[2202],{"type":37,"value":2102},{"type":28,"tag":309,"props":2204,"children":2205},{"style":352},[2206],{"type":37,"value":2052},{"type":28,"tag":309,"props":2208,"children":2209},{"style":352},[2210],{"type":37,"value":1644},{"type":28,"tag":309,"props":2212,"children":2213},{"class":311,"line":572},[2214,2220,2224,2229,2233,2238,2242,2247,2251,2256,2261,2266,2270,2275,2279,2284,2288,2292],{"type":28,"tag":309,"props":2215,"children":2217},{"style":2216},"--shiki-default:#E78284;--shiki-dark:#79B8FF",[2218],{"type":37,"value":2219},"    this",{"type":28,"tag":309,"props":2221,"children":2222},{"style":322},[2223],{"type":37,"value":1046},{"type":28,"tag":309,"props":2225,"children":2226},{"style":1603},[2227],{"type":37,"value":2228},"logger",{"type":28,"tag":309,"props":2230,"children":2231},{"style":322},[2232],{"type":37,"value":1046},{"type":28,"tag":309,"props":2234,"children":2235},{"style":1609},[2236],{"type":37,"value":2237},"log",{"type":28,"tag":309,"props":2239,"children":2240},{"style":1603},[2241],{"type":37,"value":2042},{"type":28,"tag":309,"props":2243,"children":2244},{"style":367},[2245],{"type":37,"value":2246},"`Sending via Brevo key: ",{"type":28,"tag":309,"props":2248,"children":2249},{"style":1671},[2250],{"type":37,"value":1674},{"type":28,"tag":309,"props":2252,"children":2253},{"style":1603},[2254],{"type":37,"value":2255},"process",{"type":28,"tag":309,"props":2257,"children":2259},{"style":2258},"--shiki-default:#81C8BE;--shiki-dark:#9ECBFF",[2260],{"type":37,"value":1046},{"type":28,"tag":309,"props":2262,"children":2263},{"style":1603},[2264],{"type":37,"value":2265},"env",{"type":28,"tag":309,"props":2267,"children":2268},{"style":2258},[2269],{"type":37,"value":1046},{"type":28,"tag":309,"props":2271,"children":2272},{"style":328},[2273],{"type":37,"value":2274},"BREVO_API_KEY",{"type":28,"tag":309,"props":2276,"children":2277},{"style":1671},[2278],{"type":37,"value":1684},{"type":28,"tag":309,"props":2280,"children":2281},{"style":367},[2282],{"type":37,"value":2283},"`",{"type":28,"tag":309,"props":2285,"children":2286},{"style":1603},[2287],{"type":37,"value":2052},{"type":28,"tag":309,"props":2289,"children":2290},{"style":352},[2291],{"type":37,"value":2057},{"type":28,"tag":309,"props":2293,"children":2294},{"style":373},[2295],{"type":37,"value":2296}," \u002F\u002F ❌\n",{"type":28,"tag":309,"props":2298,"children":2299},{"class":311,"line":607},[2300],{"type":28,"tag":309,"props":2301,"children":2302},{"style":352},[2303],{"type":37,"value":2304},"  }\n",{"type":28,"tag":309,"props":2306,"children":2307},{"class":311,"line":633},[2308],{"type":28,"tag":309,"props":2309,"children":2310},{"style":352},[2311],{"type":37,"value":1705},{"type":28,"tag":309,"props":2313,"children":2314},{"class":311,"line":646},[2315],{"type":28,"tag":309,"props":2316,"children":2317},{"emptyLinePlaceholder":13},[2318],{"type":37,"value":700},{"type":28,"tag":309,"props":2320,"children":2321},{"class":311,"line":669},[2322],{"type":28,"tag":309,"props":2323,"children":2324},{"style":373},[2325],{"type":37,"value":2326},"\u002F\u002F ✅ Pattern correct : injection de config NestJS via variables d'environnement\n",{"type":28,"tag":309,"props":2328,"children":2329},{"class":311,"line":694},[2330,2334,2338],{"type":28,"tag":309,"props":2331,"children":2332},{"style":1969},[2333],{"type":37,"value":1972},{"type":28,"tag":309,"props":2335,"children":2336},{"style":1609},[2337],{"type":37,"value":1977},{"type":28,"tag":309,"props":2339,"children":2340},{"style":1980},[2341],{"type":37,"value":1983},{"type":28,"tag":309,"props":2343,"children":2344},{"class":311,"line":703},[2345,2349,2353,2357],{"type":28,"tag":309,"props":2346,"children":2347},{"style":1989},[2348],{"type":37,"value":1992},{"type":28,"tag":309,"props":2350,"children":2351},{"style":1989},[2352],{"type":37,"value":1997},{"type":28,"tag":309,"props":2354,"children":2355},{"style":2000},[2356],{"type":37,"value":2003},{"type":28,"tag":309,"props":2358,"children":2359},{"style":352},[2360],{"type":37,"value":1644},{"type":28,"tag":309,"props":2362,"children":2363},{"class":311,"line":724},[2364,2368,2372,2376,2380],{"type":28,"tag":309,"props":2365,"children":2366},{"style":1989},[2367],{"type":37,"value":2015},{"type":28,"tag":309,"props":2369,"children":2370},{"style":2018},[2371],{"type":37,"value":2021},{"type":28,"tag":309,"props":2373,"children":2374},{"style":1626},[2375],{"type":37,"value":325},{"type":28,"tag":309,"props":2377,"children":2378},{"style":2000},[2379],{"type":37,"value":2037},{"type":28,"tag":309,"props":2381,"children":2382},{"style":352},[2383],{"type":37,"value":2384},";\n",{"type":28,"tag":309,"props":2386,"children":2387},{"class":311,"line":740},[2388],{"type":28,"tag":309,"props":2389,"children":2390},{"emptyLinePlaceholder":13},[2391],{"type":37,"value":700},{"type":28,"tag":309,"props":2393,"children":2394},{"class":311,"line":752},[2395,2400,2404,2409,2414,2419,2423,2428,2432],{"type":28,"tag":309,"props":2396,"children":2397},{"style":1989},[2398],{"type":37,"value":2399},"  constructor",{"type":28,"tag":309,"props":2401,"children":2402},{"style":352},[2403],{"type":37,"value":2042},{"type":28,"tag":309,"props":2405,"children":2406},{"style":1989},[2407],{"type":37,"value":2408},"private",{"type":28,"tag":309,"props":2410,"children":2411},{"style":1989},[2412],{"type":37,"value":2413}," readonly",{"type":28,"tag":309,"props":2415,"children":2416},{"style":2089},[2417],{"type":37,"value":2418}," configService",{"type":28,"tag":309,"props":2420,"children":2421},{"style":1626},[2422],{"type":37,"value":325},{"type":28,"tag":309,"props":2424,"children":2425},{"style":2000},[2426],{"type":37,"value":2427}," ConfigService",{"type":28,"tag":309,"props":2429,"children":2430},{"style":352},[2431],{"type":37,"value":2052},{"type":28,"tag":309,"props":2433,"children":2434},{"style":352},[2435],{"type":37,"value":1644},{"type":28,"tag":309,"props":2437,"children":2438},{"class":311,"line":768},[2439,2443,2447,2452,2457,2461,2465],{"type":28,"tag":309,"props":2440,"children":2441},{"style":2216},[2442],{"type":37,"value":2219},{"type":28,"tag":309,"props":2444,"children":2445},{"style":322},[2446],{"type":37,"value":1046},{"type":28,"tag":309,"props":2448,"children":2449},{"style":1603},[2450],{"type":37,"value":2451},"stripe ",{"type":28,"tag":309,"props":2453,"children":2454},{"style":1626},[2455],{"type":37,"value":2456},"=",{"type":28,"tag":309,"props":2458,"children":2459},{"style":2029},[2460],{"type":37,"value":2032},{"type":28,"tag":309,"props":2462,"children":2463},{"style":1609},[2464],{"type":37,"value":2037},{"type":28,"tag":309,"props":2466,"children":2467},{"style":1603},[2468],{"type":37,"value":2469},"(\n",{"type":28,"tag":309,"props":2471,"children":2472},{"class":311,"line":776},[2473,2478,2482,2487,2491,2496,2501,2506,2510,2514,2519],{"type":28,"tag":309,"props":2474,"children":2475},{"style":2216},[2476],{"type":37,"value":2477},"      this",{"type":28,"tag":309,"props":2479,"children":2480},{"style":322},[2481],{"type":37,"value":1046},{"type":28,"tag":309,"props":2483,"children":2484},{"style":1603},[2485],{"type":37,"value":2486},"configService",{"type":28,"tag":309,"props":2488,"children":2489},{"style":322},[2490],{"type":37,"value":1046},{"type":28,"tag":309,"props":2492,"children":2493},{"style":1609},[2494],{"type":37,"value":2495},"getOrThrow",{"type":28,"tag":309,"props":2497,"children":2499},{"style":2498},"--shiki-default:#99D1DB;--shiki-dark:#E1E4E8",[2500],{"type":37,"value":1629},{"type":28,"tag":309,"props":2502,"children":2503},{"style":2099},[2504],{"type":37,"value":2505},"string",{"type":28,"tag":309,"props":2507,"children":2508},{"style":2498},[2509],{"type":37,"value":1639},{"type":28,"tag":309,"props":2511,"children":2512},{"style":1603},[2513],{"type":37,"value":2042},{"type":28,"tag":309,"props":2515,"children":2516},{"style":367},[2517],{"type":37,"value":2518},"\"STRIPE_SECRET_KEY\"",{"type":28,"tag":309,"props":2520,"children":2521},{"style":1603},[2522],{"type":37,"value":2523},")\n",{"type":28,"tag":309,"props":2525,"children":2526},{"class":311,"line":797},[2527,2532],{"type":28,"tag":309,"props":2528,"children":2529},{"style":1603},[2530],{"type":37,"value":2531},"    )",{"type":28,"tag":309,"props":2533,"children":2534},{"style":352},[2535],{"type":37,"value":2384},{"type":28,"tag":309,"props":2537,"children":2538},{"class":311,"line":813},[2539],{"type":28,"tag":309,"props":2540,"children":2541},{"style":352},[2542],{"type":37,"value":2304},{"type":28,"tag":309,"props":2544,"children":2545},{"class":311,"line":825},[2546],{"type":28,"tag":309,"props":2547,"children":2548},{"emptyLinePlaceholder":13},[2549],{"type":37,"value":700},{"type":28,"tag":309,"props":2551,"children":2553},{"class":311,"line":2552},29,[2554,2558,2562,2566,2570,2574,2578,2582,2586,2590],{"type":28,"tag":309,"props":2555,"children":2556},{"style":1989},[2557],{"type":37,"value":2077},{"type":28,"tag":309,"props":2559,"children":2560},{"style":1609},[2561],{"type":37,"value":2082},{"type":28,"tag":309,"props":2563,"children":2564},{"style":352},[2565],{"type":37,"value":2042},{"type":28,"tag":309,"props":2567,"children":2568},{"style":2089},[2569],{"type":37,"value":2092},{"type":28,"tag":309,"props":2571,"children":2572},{"style":1626},[2573],{"type":37,"value":325},{"type":28,"tag":309,"props":2575,"children":2576},{"style":2099},[2577],{"type":37,"value":2102},{"type":28,"tag":309,"props":2579,"children":2580},{"style":352},[2581],{"type":37,"value":2052},{"type":28,"tag":309,"props":2583,"children":2584},{"style":352},[2585],{"type":37,"value":1869},{"type":28,"tag":309,"props":2587,"children":2588},{"style":373},[2589],{"type":37,"value":2115},{"type":28,"tag":309,"props":2591,"children":2592},{"style":352},[2593],{"type":37,"value":2120},{"type":28,"tag":309,"props":2595,"children":2597},{"class":311,"line":2596},30,[2598],{"type":28,"tag":309,"props":2599,"children":2600},{"style":352},[2601],{"type":37,"value":1705},{"type":28,"tag":29,"props":2603,"children":2604},{},[2605],{"type":37,"value":2606},"La raison : les LLMs ont été entraînés sur du code d'exemple qui contient fréquemment des credentials \"de test\" hardcodées. Ils reproduisent ce pattern naturellement.",{"type":28,"tag":29,"props":2608,"children":2609},{},[2610],{"type":37,"value":2611},"Garde-fou : outil SAST (Semgrep, GitHub Secret Scanning, Gitleaks) dans la CI qui détecte les patterns de credentials hardcodées avant le merge. Ce check doit être bloquant.",{"type":28,"tag":245,"props":2613,"children":2615},{"cta":247,"href":248,"title":2614,"type":250},"Vous voulez repérer une injection ou un secret hardcodé dans une PR Claude avant qu'il atteigne la prod ?",[2616],{"type":28,"tag":29,"props":2617,"children":2618},{},[2619,2621,2627],{"type":37,"value":2620},"Distinguer un ",{"type":28,"tag":45,"props":2622,"children":2624},{"className":2623},[],[2625],{"type":37,"value":2626},"$queryRaw",{"type":37,"value":2628}," paramétré d'une concaténation dangereuse, ça ne s'apprend pas en lisant un article : ça se travaille sur du vrai code. En mentoring 1:1, je relis vos PR IA-assistées avec vous, on construit votre checklist de review personnelle et vous développez le réflexe qui attrape ces vulnérabilités avant le merge. Du 1:1 pour monter en niveau, pas un audit d'équipe.",{"type":28,"tag":62,"props":2630,"children":2631},{},[],{"type":28,"tag":66,"props":2633,"children":2635},{"id":2634},"vulnérabilité-type-3-dépendances-obsolètes-ou-hallucinations",[2636],{"type":37,"value":2637},"Vulnérabilité type 3 : Dépendances obsolètes ou hallucinations",{"type":28,"tag":29,"props":2639,"children":2640},{},[2641],{"type":37,"value":2642},"Quand un LLM génère du code qui importe des librairies externes, deux risques spécifiques apparaissent :",{"type":28,"tag":29,"props":2644,"children":2645},{},[2646,2651],{"type":28,"tag":33,"props":2647,"children":2648},{},[2649],{"type":37,"value":2650},"Dépendances avec CVE connus :",{"type":37,"value":2652}," Claude suggère une version d'une librairie qui avait des vulnérabilités connues au moment de son entraînement, et qui ont pu être corrigées depuis, mais la version vulnérable reste dans le code généré.",{"type":28,"tag":29,"props":2654,"children":2655},{},[2656,2661],{"type":28,"tag":33,"props":2657,"children":2658},{},[2659],{"type":37,"value":2660},"Package hallucination :",{"type":37,"value":2662}," les LLMs peuvent inventer des noms de packages plausibles qui n'existent pas (ou qui existent sous un nom de typosquat malveillant). C'est le vecteur de l'attaque \"dependency confusion\", documentée par de nombreux chercheurs en sécurité depuis 2021.",{"type":28,"tag":299,"props":2664,"children":2668},{"className":2665,"code":2666,"language":2667,"meta":8,"style":8},"language-bash shiki shiki-themes catppuccin-frappe github-dark","# Claude suggère d'importer \"nestjs-prisma-query-helper\" : package qui n'existe pas\n# Un attaquant peut publier ce package sur npm\u002Fpnpm avec du code malveillant\npnpm add nestjs-prisma-query-helper  # ❌ vérifier l'existence avant d'installer\n","bash",[2669],{"type":28,"tag":45,"props":2670,"children":2671},{"__ignoreMap":8},[2672,2680,2688],{"type":28,"tag":309,"props":2673,"children":2674},{"class":311,"line":312},[2675],{"type":28,"tag":309,"props":2676,"children":2677},{"style":373},[2678],{"type":37,"value":2679},"# Claude suggère d'importer \"nestjs-prisma-query-helper\" : package qui n'existe pas\n",{"type":28,"tag":309,"props":2681,"children":2682},{"class":311,"line":334},[2683],{"type":28,"tag":309,"props":2684,"children":2685},{"style":373},[2686],{"type":37,"value":2687},"# Un attaquant peut publier ce package sur npm\u002Fpnpm avec du code malveillant\n",{"type":28,"tag":309,"props":2689,"children":2690},{"class":311,"line":348},[2691,2696,2701,2706],{"type":28,"tag":309,"props":2692,"children":2693},{"style":1609},[2694],{"type":37,"value":2695},"pnpm",{"type":28,"tag":309,"props":2697,"children":2698},{"style":367},[2699],{"type":37,"value":2700}," add",{"type":28,"tag":309,"props":2702,"children":2703},{"style":367},[2704],{"type":37,"value":2705}," nestjs-prisma-query-helper",{"type":28,"tag":309,"props":2707,"children":2708},{"style":373},[2709],{"type":37,"value":2710},"  # ❌ vérifier l'existence avant d'installer\n",{"type":28,"tag":29,"props":2712,"children":2713},{},[2714,2716,2721],{"type":37,"value":2715},"Garde-fou : ne jamais installer un package suggéré par Claude sans vérifier son existence sur le registre officiel et son score de sécurité (",{"type":28,"tag":45,"props":2717,"children":2719},{"className":2718},[],[2720],{"type":37,"value":165},{"type":37,"value":2722},", Snyk, Socket.dev).",{"type":28,"tag":62,"props":2724,"children":2725},{},[],{"type":28,"tag":66,"props":2727,"children":2729},{"id":2728},"les-5-garde-fous-à-mettre-en-place",[2730],{"type":37,"value":2731},"Les 5 garde-fous à mettre en place",{"type":28,"tag":272,"props":2733,"children":2735},{"id":2734},"garde-fou-1-sast-dans-la-ci",[2736],{"type":37,"value":2737},"Garde-fou 1 : SAST dans la CI",{"type":28,"tag":29,"props":2739,"children":2740},{},[2741,2747],{"type":28,"tag":83,"props":2742,"children":2744},{"href":2743},"\u002Ffr\u002Fdette-technique\u002Foutils-analyse-statique-2026",[2745],{"type":37,"value":2746},"SonarQube, Semgrep, ou GitHub Advanced Security",{"type":37,"value":2748}," détectent les patterns de vulnérabilités courants indépendamment de l'origine du code, qu'il soit humain ou IA. Ce check doit être bloquant sur les vulnérabilités Critical et High.",{"type":28,"tag":272,"props":2750,"children":2752},{"id":2751},"garde-fou-2-checklist-de-review-spécifique-au-code-ia",[2753],{"type":37,"value":2754},"Garde-fou 2 : Checklist de review spécifique au code IA",{"type":28,"tag":29,"props":2756,"children":2757},{},[2758,2760,2766],{"type":37,"value":2759},"Au-delà de la review standard, je vérifie explicitement pour tout code généré par Claude (voir la ",{"type":28,"tag":83,"props":2761,"children":2763},{"href":2762},"\u002Ffr\u002Fintelligence-artificielle\u002Ftester-code-genere-ia-checklist",[2764],{"type":37,"value":2765},"checklist complète en 12 points",{"type":37,"value":2767},") :",{"type":28,"tag":148,"props":2769,"children":2770},{},[2771,2776,2787,2792],{"type":28,"tag":152,"props":2772,"children":2773},{},[2774],{"type":37,"value":2775},"Aucune credential hardcodée",{"type":28,"tag":152,"props":2777,"children":2778},{},[2779,2781,2786],{"type":37,"value":2780},"Toutes les requêtes DB utilisent l'ORM Prisma ou des templates paramétrés (",{"type":28,"tag":45,"props":2782,"children":2784},{"className":2783},[],[2785],{"type":37,"value":2626},{"type":37,"value":2052},{"type":28,"tag":152,"props":2788,"children":2789},{},[2790],{"type":37,"value":2791},"Les dépendances importées ont été vérifiées sur le registre officiel",{"type":28,"tag":152,"props":2793,"children":2794},{},[2795],{"type":37,"value":2796},"Les inputs utilisateurs sont validés par un schéma Zod avant tout traitement",{"type":28,"tag":272,"props":2798,"children":2800},{"id":2799},"garde-fou-3-politique-de-prompt",[2801],{"type":37,"value":2802},"Garde-fou 3 : Politique de prompt",{"type":28,"tag":29,"props":2804,"children":2805},{},[2806],{"type":37,"value":2807},"Documenter quelles données peuvent et ne peuvent pas être incluses dans les prompts envoyés à des services IA : pas de données personnelles, pas de données clients, pas de credentials, pas de secrets d'infrastructure.",{"type":28,"tag":272,"props":2809,"children":2811},{"id":2810},"garde-fou-4-former-sa-mémoire-aux-patterns-dangereux",[2812],{"type":37,"value":2813},"Garde-fou 4 : Former sa mémoire aux patterns dangereux",{"type":28,"tag":29,"props":2815,"children":2816},{},[2817,2819,2825],{"type":37,"value":2818},"Une heure à relire du code vulnérable généré par IA suffit à développer des réflexes de détection durables. En solo, le plus efficace est de prendre ses propres findings passés (comme ceux décrits ici) et d'en faire une liste de vérification personnelle. Découvrez comment ",{"type":28,"tag":83,"props":2820,"children":2822},{"href":2821},"\u002Ffr\u002Fintelligence-artificielle\u002Fia-code-review-retour-experience",[2823],{"type":37,"value":2824},"intégrer l'IA dans votre code review",{"type":37,"value":2826}," tout en renforçant la sécurité.",{"type":28,"tag":272,"props":2828,"children":2830},{"id":2829},"garde-fou-5-audit-trimestriel-du-code-ia-assisté",[2831],{"type":37,"value":2832},"Garde-fou 5 : Audit trimestriel du code IA-assisté",{"type":28,"tag":29,"props":2834,"children":2835},{},[2836],{"type":37,"value":2837},"Auditer trimestriellement un échantillon du code développé avec assistance IA pour identifier des patterns systémiques de vulnérabilité. C'est une pratique préventive, pas réactive.",{"type":28,"tag":29,"props":2839,"children":2840},{},[2841],{"type":37,"value":2842},"Sur crmcoaching, l'introduction de GitHub Secret Scanning et d'une checklist de review dédiée au code Claude m'a permis de détecter, en quelques mois, plusieurs instances de secrets hardcodés et de requêtes construites par concaténation qui auraient atteint la production. Ces mesures ne prennent pas longtemps à mettre en place et couvrent l'essentiel des risques introduits par l'assistance IA.",{"type":28,"tag":29,"props":2844,"children":2845},{},[2846],{"type":37,"value":2847},"L'IA accélère la production. Elle ne remplace pas le jugement de sécurité.",{"type":28,"tag":245,"props":2849,"children":2851},{"cta":1254,"href":1255,"title":2850,"type":1257},"Ces 5 garde-fous ne sont qu'un début : il en existe 100",[2852],{"type":28,"tag":29,"props":2853,"children":2854},{},[2855],{"type":37,"value":2856},"Relire une PR pour traquer une injection ou un secret hardcodé fait partie d'un ensemble bien plus large : le Craft Bundle réunit les 100 pratiques craft que j'applique pour coder propre, de la review de sécurité au design de code testable. Ce sont les réflexes qu'un LLM ne vous apprendra jamais, parce qu'il ne les a jamais vus tenir en production.",{"type":28,"tag":62,"props":2858,"children":2859},{},[],{"type":28,"tag":66,"props":2861,"children":2863},{"id":2862},"faq-sur-la-sécurité-du-code-llm",[2864],{"type":37,"value":2865},"FAQ sur la sécurité du code LLM",{"type":28,"tag":1274,"props":2867,"children":2868},{},[2869,2874],{"type":28,"tag":1278,"props":2870,"children":2871},{},[2872],{"type":37,"value":2873},"1. Les LLMs vont-ils s'améliorer sur la sécurité du code au fil du temps ?",{"type":28,"tag":29,"props":2875,"children":2876},{},[2877],{"type":37,"value":2878},"Oui, progressivement. Les LLMs récents sont significativement meilleurs que leurs prédécesseurs sur les patterns de sécurité de base. Mais ils continuent à faire des erreurs sur les vulnérabilités contextuelles, celles qui dépendent de la logique métier spécifique de votre application. Ces erreurs-là ne pourront pas être éliminées par l'amélioration des modèles seule.",{"type":28,"tag":1274,"props":2880,"children":2881},{},[2882,2887],{"type":28,"tag":1278,"props":2883,"children":2884},{},[2885],{"type":37,"value":2886},"2. Les outils SAST détectent-ils les vulnérabilités spécifiques au code IA-généré ?",{"type":28,"tag":29,"props":2888,"children":2889},{},[2890],{"type":37,"value":2891},"Les SAST détectent les patterns de vulnérabilités connus indépendamment de l'origine du code. Ils sont efficaces sur les injections, les hardcoded secrets, et les dépendances vulnérables. Ils ne détectent pas les vulnérabilités logiques, c'est-à-dire le code qui fait quelque chose de sécuritairement incorrect mais syntaxiquement valide. Pour celles-là, la review humaine reste indispensable.",{"type":28,"tag":1274,"props":2893,"children":2894},{},[2895,2900],{"type":28,"tag":1278,"props":2896,"children":2897},{},[2898],{"type":37,"value":2899},"3. Faut-il une politique de sécurité spécifique pour le code généré par Claude ?",{"type":28,"tag":29,"props":2901,"children":2902},{},[2903],{"type":37,"value":2904},"La politique doit être basée sur les données traitées et les clauses contractuelles, pas sur l'outil en lui-même. Questions à évaluer : les prompts sont-ils utilisés pour l'entraînement ? Anthropic propose-t-il un DPA compatible RGPD ? Les données sont-elles hébergées là où votre conformité l'exige ? Les réponses varient selon l'offre : Claude grand public, Claude Team ou Enterprise, ou l'API Anthropic.",{"type":28,"tag":1274,"props":2906,"children":2907},{},[2908,2913],{"type":28,"tag":1278,"props":2909,"children":2910},{},[2911],{"type":37,"value":2912},"4. Comment développer rapidement des réflexes face aux vulnérabilités du code LLM-généré ?",{"type":28,"tag":29,"props":2914,"children":2915},{},[2916],{"type":37,"value":2917},"La méthode la plus efficace : relire des exemples réels de code vulnérable généré par IA et identifier les problèmes. Cette approche en \"capture the flag\" crée une mémoire musculaire plus durable que de la théorie. En solo, constituer une liste personnelle à partir de ses propres findings passés est encore plus ancré. Une heure sur dix exemples réels suffit à développer les réflexes de base.",{"type":28,"tag":1274,"props":2919,"children":2920},{},[2921,2926],{"type":28,"tag":1278,"props":2922,"children":2923},{},[2924],{"type":37,"value":2925},"5. Un développeur solo sans RSSI dédié peut-il gérer ces risques seul ?",{"type":28,"tag":29,"props":2927,"children":2928},{},[2929],{"type":37,"value":2930},"Oui, avec 3 garde-fous prioritaires : GitHub Secret Scanning (activé gratuitement sur les repos GitHub, détecte les credentials avant le push), une règle de review PR personnelle qui checke les injections et les hardcoded secrets, et une politique simple : \"aucune donnée client ou credential dans les prompts\". Ces trois mesures couvrent 80 % des risques avec 20 % de l'effort.",{"type":28,"tag":62,"props":2932,"children":2933},{},[],{"type":28,"tag":245,"props":2935,"children":2938},{"cta":2936,"href":1432,"title":2937,"type":1434},"Testez la readiness IA de votre équipe →","Ressource gratuite : AI-Ready Engineering Team Checklist",[2939],{"type":28,"tag":29,"props":2940,"children":2941},{},[2942],{"type":37,"value":2943},"La checklist AI-Ready inclut une section dédiée à la sécurité du code IA-assisté : critères de gouvernance, checklist de review spécifique, et politiques d'usage recommandées. Adaptable à votre contexte réglementaire.",{"type":28,"tag":1442,"props":2945,"children":2946},{},[2947],{"type":37,"value":1446},{"title":8,"searchDepth":334,"depth":334,"links":2949},[2950,2951,2952,2953,2954,2961],{"id":1540,"depth":334,"text":1543},{"id":1559,"depth":334,"text":1562},{"id":1927,"depth":334,"text":1930},{"id":2634,"depth":334,"text":2637},{"id":2728,"depth":334,"text":2731,"children":2955},[2956,2957,2958,2959,2960],{"id":2734,"depth":348,"text":2737},{"id":2751,"depth":348,"text":2754},{"id":2799,"depth":348,"text":2802},{"id":2810,"depth":348,"text":2813},{"id":2829,"depth":348,"text":2832},{"id":2862,"depth":334,"text":2865},"content:fr:intelligence-artificielle:llm-securite-code-vulnerabilites.md","fr\u002Fintelligence-artificielle\u002Fllm-securite-code-vulnerabilites.md","fr\u002Fintelligence-artificielle\u002Fllm-securite-code-vulnerabilites",1784113925404]