Repository navigation
chore(deps): npm audit en verde con subidas y excepciones que caducan - #358
Merged
Merged
Conversation
El gate de npm audit fallaba en CI, staging y producción por advisories nuevas (next critical, proxy-addr, shell-quote y otras), y con él se saltaban Build y los smoke tests de todos los PR. - Sube next y eslint-config-next a 16.3.8, sharp a 0.35.5 y brace-expansion a 5.0.12 (overrides), y las transitivas proxy-addr, shell-quote, undici, @modelcontextprotocol/sdk, source-map-js y compression. Solo cambian versiones: ningún paquete entra ni sale. - braces y node-forge no tienen versión corregida ni alternativa. npm audit no admite excepciones, así que el gate pasa a scripts/npm-audit.mjs, que las lee de scripts/audit-exceptions.json por GHSA y paquete, con caducidad de 90 días como máximo, y falla cerrado si no puede auditar o no reconoce el lockfile o el informe. - La auditoría corre justo después de setup-node, antes de que el job ejecute código del repo. - CODEOWNERS pide la revisión de Andrés en los cambios del gate, sus excepciones y la configuración de npm. Closes #357 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: Paperclip <noreply@paperclip.ing>
El resolved esperado de cada entrada se construye con su version y el name de su clave, así que la comparación solo vale si los dos tienen la forma que publica npm. Ahora el gate exige version semver y name válido de npm, y que el resolved no cambie al normalizarse como URL; si no, falla con "lockfile inesperado". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Las entradas link del lockfile salían de la comprobación sin mirar a dónde apuntaban. Ahora un link solo vale si su resolved es un workspace de package.json#workspaces, sin segmentos node_modules ni .., y si la entrada de ese workspace en el lockfile tiene el mismo name que la clave del link; si no, falla con "lockfile inesperado". Los workspaces se leen de package.json porque packages[""] viene en el mismo lockfile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #357
El gate
npm audit --audit-level=highfalla en CI, staging y producción por advisories publicadas después del último merge adevelop, y con él se saltan Build y los smoke tests de todos los PR. Este PR sube lo que tiene versión corregida, cambia el gate por un script con excepciones que caducan y pide la revisión del propietario en los cambios del gate.Subidas
nexteslint-config-nextnextsharp(overridenext.sharp)brace-expansion(override)proxy-addr@modelcontextprotocol/sdkundicisource-map-jsshell-quotecompressionEn el lockfile solo cambian las versiones de estos paquetes,
@next/*y@img/sharp-*. Las 1600 claves depackagesson las mismas que endevelop, no entra ni sale ningún paquete yapps/android/package.jsonno cambia. Sinnpm audit fix --forceninpx expo install --fix(#304); ninguna de las subidas está enbundledNativeModules.jsonde Expo.npm audit(npm 11.19.0) pasa de 45 vulnerabilidades (3 critical, 33 high, 9 moderate) a 35 (0 critical, 26 high, 9 moderate). Las 26 high cuelgan de las dos advisories de abajo.Excepciones, hasta el 2027-01-04
bracesGHSA-vfj7-8cjw-p6xm (<=3.0.3, CWE-674): sin versión corregida y el mantenedor rechaza el CVE (Security Advisory: Uncontrolled Recursion Depth in Tree Walkers Leads to Stack-Overflow DoS micromatch/braces#70). Llega por metro, Expo, tailwindcss 3, shadcn, ts-morph y patch-package; los patrones vienen de la configuración del repo, nunca de un usuario.node-forgeGHSA-86w9-cpqp-85rv (<=1.4.0, CWE-347): sin versión corregida; el fix está en Fix RSA PKCS#1 v1.5 forgery via nested DigestAlgorithm garbage digitalbazaar/forge#1152, sin publicar. Solo lo trae@expo/cli, herramienta de desarrollo de Android: no está en la imagen web yapps/androidno usa code signing de Expo.Ninguna de las dos tiene alternativa: las últimas versiones de las herramientas que las traen siguen dependiendo de ellas.
Gate
npm auditno admite excepciones.scripts/npm-audit.mjs(Node, sin dependencias) ejecutanpm audit --jsony leescripts/audit-exceptions.json:metadatano cuadran con las entradas devulnerabilities.npm-shrinkwrap.json, los alias y cualquier entrada que no venga del registry de npm con su nombre y su versión, exige version semver y name válido de npm, y solo admite links hacia los workspaces depackage.json.El paso "Auditoría de seguridad npm" cambia en los tres workflows a la vez: si solo cambiara
ci.yml, el primer push adeveloptras el merge fallaría en staging. Además se mueve justo detrás de "Setup Node.js", antes de que el job ejecute código del repo.npm auditsolo necesita el lockfile, así que el resultado no cambia.CODEOWNERS
Para dejar el gate en verde no hace falta tocar las excepciones: basta con cambiar el script, quitar el paso del workflow o añadir un
.npmrc, que cambia lo que audita npm..github/CODEOWNERSpone a @aacienfuegos en/.github/(workflows y el propioCODEOWNERS), en los dos ficheros descripts/y en cualquier.npmrcdel repo. El fichero solo hace que GitHub pida la revisión. La vuelve obligatoria el ruleset de abajo.Después del merge (Andrés)
Ruleset en Settings > Rules > Rulesets > New branch ruleset. Va después del merge porque GitHub lee el
CODEOWNERSde la rama base.develop→main, que abres tú y no puedes aprobarte.developymain.Con 0 aprobaciones, un PR que no toca esas rutas sigue sin necesitar aprobación. En
mainno pide nada hasta el primer release que lleve elCODEOWNERS. La comprobación del ruleset, por configuración y por el efecto, va en otro issue.Verificación
Type check (web y Android), tests, build y smoke tests: no se han ejecutado en local por falta de espacio en disco para instalar las dependencias. Los ha ejecutado el CI de este PR, run 37950677527 sobre
5807ef5, con conclusiónsuccessy todos los pasos ensuccess:El CI (Node 26.11.1, npm 11.20.0, 15:19 UTC) cuenta 30 entradas high y en local salen 26: con npm 11.19.0 y con 11.20.0, sobre el mismo lockfile, a las 19:02 UTC. Las dos auditorías dan exit 0 y solo encuentran como advisories high las de
bracesynode-forge. Con el recuento estricto, eso implica que en el CI las 30 entradas llevaban a una de esas dos. No sé qué cuatro entradas sobran en el CI, porque el script solo imprime el recuento. Que la base de advisories cambiara entre una hora y otra es una deducción, no lo he comprobado.sharp 0.35.5 carga su binario nativo (instalado aparte; la
integritydesharp,@img/sharp-linux-x64y@img/sharp-libvips-linux-x64es la misma que en el lockfile de la rama):Versiones en el lockfile (
jq -r '.packages["node_modules/<paquete>"].version' package-lock.json):Gate en la rama y controles negativos. Cada control se ejecuta en local y sin commitear. Las excepciones se modifican sobre una copia y se restauran después; los lockfiles de
developsalen degit show origin/develop:<fichero>a un directorio aparte, con los cuatropackage.json, y el script se ejecuta desde ahí. Todos dan exit 1 y cada uno por su motivo, salvo el de la rama, que da exit 0. El 5 falla por las advisories dedevelopy no por el formato ni por el lockfile: el recuento estricto y la comprobación del lockfile no dan falsos positivos con datos reales.Salida de los 17 casos
Los seis informes escritos a mano (casos 7a a 7f)
a.json{"auditReportVersion":2,"vulnerabilities":{"micromatch":{"name":"micromatch","severity":"high","via":["braces"]}},"metadata":{"vulnerabilities":{"info":0,"low":0,"moderate":0,"high":1,"critical":0,"total":1}}}b.json{"auditReportVersion":2,"vulnerabilities":{"braces":{"name":"braces","severity":"high","via":[{"source":1240992,"name":"braces","dependency":"braces","title":"braces vulnerable to stack-exhaustion denial of service through deeply nested patterns","url":"https://github.com/advisories/GHSA-vfj7-8cjw-p6xm","severity":"severe","cwe":["CWE-674"],"cvss":{},"range":"<=3.0.3"}]}},"metadata":{"vulnerabilities":{"info":0,"low":0,"moderate":0,"high":1,"critical":0,"total":1}}}c.json{"auditReportVersion":2,"vulnerabilities":{"braces":{"name":"braces","severity":"high","via":[{"source":1240992,"name":"braces","dependency":"braces","title":"braces vulnerable to stack-exhaustion denial of service through deeply nested patterns","url":"https://github.com/advisories/1240992","severity":"high","cwe":["CWE-674"],"cvss":{},"range":"<=3.0.3"}]}},"metadata":{"vulnerabilities":{"info":0,"low":0,"moderate":0,"high":1,"critical":0,"total":1}}}d.json{"auditReportVersion":2,"vulnerabilities":{"braces":{"name":"braces","severity":"high","via":[{"source":1240992,"name":"braces","dependency":"braces","title":"braces vulnerable to stack-exhaustion denial of service through deeply nested patterns","url":"https://github.com/advisories/GHSA-vfj7-8cjw-p6xm","severity":"high","cwe":["CWE-674"],"cvss":{},"range":"<=3.0.3"}]}},"metadata":{"vulnerabilities":{"info":0,"low":0,"moderate":0,"high":2,"critical":0,"total":2}}}e.json{"auditReportVersion":2,"vulnerabilities":{"braces":{"name":"braces","severity":"high","via":[{"source":1240992,"name":"braces","dependency":"braces","title":"braces vulnerable to stack-exhaustion denial of service through deeply nested patterns","url":"https://github.com/advisories/GHSA-vfj7-8cjw-p6xm","severity":"high","cwe":["CWE-674"],"cvss":{},"range":"<=3.0.3"}]},"foo":{"name":"foo","severity":"high","via":["bar"]}},"metadata":{"vulnerabilities":{"info":0,"low":0,"moderate":0,"high":2,"critical":0,"total":2}}}f.json{"auditReportVersion":2,"vulnerabilities":{"braces":{"name":"braces","severity":"high","via":[{"source":1240992,"name":"braces","dependency":"braces","title":"braces vulnerable to stack-exhaustion denial of service through deeply nested patterns","url":"https://github.com/advisories/GHSA-vfj7-8cjw-p6xm","severity":"high","cwe":["CWE-674"],"cvss":{},"range":"<=3.0.3"}]},"foo":{"name":"foo","severity":"high","via":["bar"]},"bar":{"name":"bar","severity":"high","via":["foo"]}},"metadata":{"vulnerabilities":{"info":0,"low":0,"moderate":0,"high":3,"critical":0,"total":3}}}Orden de los pasos en los tres workflows:
En el log del run del PR, "Auditoría de seguridad npm" es el paso 5, justo detrás de "Setup Node.js" (4) y antes de "Instalar dependencias" (6):
CODEOWNERS (configuración; el efecto lo comprueba el issue del ruleset):
Ficheros que cambia el PR (
git diff --stat origin/develop):🤖 Generated with Claude Code