Vi reviderede Googles zx med og uden en anmeldelses-skill

Vi reviderede Googles zx med og uden en anmeldelses-skill

Skill Bench, del 4 af 4. Samme model, samme prompt, én skill installeret eller ej. Også i serien: en landingsside, en Telegram-bot og fejlfinding af et slangespil.

Efter tre indlæg i denne serie har mønsteret været konsekvent: skill-armen gør mere, tjekker mere, bruger flere tokens og producerer et mere gennemtænkt resultat. Dette indlæg bryder det mønster. Det er den eneste gang i hele testen, hvor skill-kørslen var billigere end baseline, og det er også den eneste gang, skill-armen overså seriens største fund. Begge dele er sande på én gang, og spændingen mellem dem er det mest nyttige resultat, vi har opnået med dette projekt.

Hvorfor Googles zx

Vi ønskede en kodauditopgave med tre egenskaber: reel kode, ikke et syntetisk, fejl-plantet kodestykke; noget en mellemniveauudvikler sandsynligvis kunne blive bedt om at gennemgå en tirsdag; og en kodebase, der var kendt nok til, at læsere kunne tjekke vores påstande mod den faktiske kilde i stedet for at stole blindt på os.

google/zx opfyldte alle tre. Det er Googles bibliotek til at skrive shell-scripts i JavaScript, populært nok til at en betydelig del af Node-værktøjer afhænger af det, og lille nok til, at en enkelt fil-audit er en rimelig opgave snarere end et forskningsprojekt. Vi valgte src/core.ts, filen der udfører den faktiske proces-spawning og miljøhåndtering, hentet frisk fra repository'et. Intet her er en konstrueret sårbarhed. Det er en reel, aktivt vedligeholdt fil, og zx er generelt velbygget: ren struktur, fornuftige standardindstillinger de fleste steder, den slags kode der består en afslappet læsning. Det er præcis den opsætning, hvor en audit enten tjener sig selv ind ved at finde den ene ting, en afslappet læsning overser, eller også gør den ikke.

Metodologi

To kørsler, samme model, samme instruktion: auditér src/core.ts fra google/zx og producer fund rangeret P0 til P3, hver med en placering, hvad der går i stykker, hvornår det går i stykker, og en minimal løsning. Kørsel ét fik den brief og intet andet. Kørsel to fik den identiske brief plus vores egen sikkerheds- og kodegennemgangs-tjekliste, den der følger med i vores Security Pack og Developer Toolkit, læst fuldt ud før auditten startede.

Samme forbehold som for alle andre indlæg i denne serie: dette er én kørsel per arm, én model, én fil. Vi påstår ikke, at de specifikke antal fund replikeres ved en gentagelse. Hvad vi rapporterer, er hvad der skete, med reel harness-telemetri, og et mønster i den type ting, hver arm fanger, som vi mener generaliserer bedre end de rå tal gør.

Hvad baseline fandt

Efterladt alene læste modellen core.ts og hentede på eget initiativ også util.ts og error.ts for kontekst, før den skrev noget. Ingen bad den om det. Den besluttede, at filen ikke gav mening isoleret og kiggede på dens naboer, hvilket viste sig at være vigtigt.

Baselinens topfund, og det fund med højeste alvorlighed i hele testen, er dette. På linje 139 sætter core.ts sin miljøindstilling til env: process.env som standard. Det er ikke en kopi af miljøet, det er en live reference til det. Når man først ved det, er konsekvensen ligetil: hvis en kodevej gør noget som $.env.FOO = 'x', sætter den ikke en variabel, der er begrænset til det ene shell-kald. Den muterer process.env for hele den kørende applikation, hvilket betyder, at alle andre dele af programmet, alle andre biblioteker, alt der læser miljøvariabler efter det punkt, ser ændringen. En konfigurationsjustering beregnet til ét subprocess-kald lækker ind i global tilstand. I en langvarig serverproces, eller i ethvert script der spreder flere zx-kald med lidt forskellige miljøer, er det den slags fejl, der ikke viser sig i en hurtig test og derefter korrumperer en fuldstændig urelateret del af systemet dage senere. Vi verificerede dette direkte mod kilden i stedet for at stole på modellens ord, og linjen gør præcis, hvad fundet siger.

Resten af baselinens liste, vurderet P2 og P3, var solid uden at være spektakulær: en bash-detektionsfejl, der sluges lydløst og senere dukker op som en misvisende, urelateret fejlmeddelelse i stedet for den virkelige årsag, og et tilfælde hvor break() kaster synkront indefra en .catch()-handler, hvilket er den slags kontrolflow-fejl, der er let at skrive og irriterende at debugge, fordi stack trace peger et unyttigt sted hen.

Fuld baseline-opgørelse: én P1, to P2'ere, fire P3'ere.

GRATIS STARTERPAKKE

Nysgerrig efter hvad en uledsaget Claude-audit fanger i din egen kode, før du tilføjer en tjekliste? Vores gratis starterpakke er en hurtig måde at få en anden gennemgang i gang på.

Få den gratis starterpakke

Hvad tjekliste-armen fandt

Den skill-guidede kørsel fulgte vores kodegennemgangs-tjekliste, den samme som er dækket i vores oversigt over sikkerhedsskills, og den læste som en helt anden anmelder: samme fil, samme adgang, et helt andet sæt af bekymringer kom frem.

Dens bedste fund var en uhåndteret promise-afvisning: kaldesteder for break() og timeout() påkalder kill() uden at afvente den, så en afvisning fra det kald har intet sted at lande og kan crashe processen uden for enhver try/catch en kalder skrev. Den fangede også en TypeError, der opstår, når noget forsøger at async-iterere en ProcessPromise efter den allerede er blevet stoppet, et reelt edge-case, der kun viser sig under en specifik sekvens af kald. Og den markerede, at ZX_PREFIX og ZX_POSTFIX indsættes direkte i hver shell-påkalden uden sanering, hvilket er værd at en vedligeholder kigger på, hvis nogen af værdierne nogensinde kan komme udefra den betroede scriptforfatter.

Dette er reelle, velformede fund, ikke fyld. Tjekliste-armens rapport var også det mest brugbare af de to dokumenter på egne præmisser: ensartet struktur, konsekvent alvorlighedssprog, hver post fulgte den samme placering-påvirkning-løsning-form uden at modellen skulle opfinde det format på stedet.

Fuld tjekliste-opgørelse: to P2'ere, fem P3'ere. Ingen P1'ere, og bemærkelsesværdigt nok, ingen process.env-fund overhovedet.

Overlappet, og hvor lille det var

Stil begge lister op, og overlappet er tæt på nul. Seks baseline-fund, syv tjekliste-fund, tretten i alt, og ikke ét af dem nævner den samme grundårsag. The process.env mutation. The bash-detection swallow. The synchronous throw in a catch. The un-awaited kill(). The halted-iterator TypeError. The unsanitized prefix/postfix splice. Hver eneste er en forskellig kodevej.

Det er en større overraskelse end nogen af de individuelle lister. To kompetente anmeldere, der kigger på de samme omkring 300 linjer TypeScript, den ene guidet af en struktureret tjekliste og den anden ikke, og de lander på næsten helt adskilte sæt af problemer. Hvis du havde fortalt os på forhånd, at tjekliste-kørslen stort set ville dobbelttjekke baselinens liste og tilføje polering, ville vi have troet det. Det var ikke, hvad der skete. Tjeklisten forfinede ikke den samme søgning, den udførte en anden søgning.

Tallene

Baseline (ingen skill) Skill-arm (kodegennemgangs-tjekliste) Delta
Tokens brugt 87,899 81,743 −7%
P1 fund 1 0 −1
P2 fund 2 2 0
P3 fund 4 5 +1
Samlede fund 7 7 0
Læste proaktivt nabofiler Ja (util.ts, error.ts) Nej
Fund med højeste alvorlighed process.env mutation (verificeret)

Hvert andet indlæg i denne serie viste, at skill-armen kostede flere tokens for et mere disciplineret resultat. Dette er den ene undtagelse: tjekliste-armen var 7% billigere. Vores fortolkning er, at en tjekliste indsnævrer søgerummet, og et smallere søgerum er billigere at udføre, selv når det også er et, der lukker af for nogle af de stier, en fritgående gennemgang ville have udforsket.

Gulv vs. loft

Dette er det skarpeste, vi har lært på tværs af alle fire indlæg, og det viser sig tydeligst her. Tjeklisten gjorde auditten billigere og gav den et mere stringent, mere konsekvent format. Hvad den ikke gjorde, var at finde process.env-fejlen, fordi det fund ikke kom fra nogen kategori på tjeklisten. Det kom fra, at baseline bemærkede, at core.ts alene var svær at ræsonnere over, besluttede på egen hånd at hente util.ts og error.ts, og fulgte den fornemmelse et sted hen, hvor tjeklistens struktur aldrig pegede.

En tjekliste hæver gulvet. Den garanterer en minimumsstandard for dækning: hver kategori bliver tjekket, hvert fund bliver skrevet op på samme måde, og du mister ikke en nem fangst på grund af en dårlig dag. Den hæver ikke loftet. Det bedst mulige fund på en given fil kan ligge uden for enhver kategori, tjeklisten opregner, og en proces, der kun følger tjeklisten, vil gå lige forbi det, selvsikkert, i en pænt formateret rapport.

Det er ikke et argument imod tjeklister. Nul af tjeklistens syv fund var dårlige, og to af dem var den slags, en travl menneskelig anmelder sandsynligvis overser under tidspres. Det er et argument for at vide, hvad en tjekliste er til for. Det er et gulv-hævende værktøj, ikke et loft-hævende, og at behandle det som begge dele er, hvordan en reel P1 slipper igennem en gennemgang, der ellers ser grundig ud.

SKILLPROOF PAKKE

Den præcise tjekliste, der kørte i denne test, den der fandt det uafventede kill() og den usanerede prefix-indsættelse, følger med i vores Security Pack sammen med resten af vores top-scorede review skills.

Få Security Pack — $10

Sådan udfører du en to-pass audit selv

Ud fra hvad vi fandt, er vores egentlige anbefaling ikke "brug en tjekliste" eller "spring tjeklisten over." Det er at køre begge, på alt der betyder noget.

Start med en fri gennemgang. Peg modellen mod filen, giv den audit-briefen, og lad den læse hvad den ellers vil læse. Giv den ikke en rubrik. Dette er den gennemgang, der har de bedste chancer for at fange det, ingen tænkte på at sætte på en liste, fordi den ikke er begrænset til listen.

Kør derefter en anden, separat gennemgang med en struktureret tjekliste, vores eller din egen. Dette er den gennemgang, der garanterer dækning: de kategorier, der er kedelige at tjekke manuelt, men lette at springe over, når du følger en fornemmelse – sanering, fejlhåndtering, ressourceoprydning – bliver gennemgået hver gang.

Sammenlign de to rapporter, før du læser nogen af dem som endelige. Hvis vores overlapstal holder på din kode, som det holdt på zx's, forvent da at de to lister deler mindre end halvdelen af deres fund. Betragt det som det forventede resultat, ikke et tegn på at nogen af gennemgangene fejlede. Den fulde testprotokol dækker mere detaljeret, hvordan vi strukturerer denne type parrede kørsler, herunder hvordan vi kontrollerer, at modellen ikke læser sin egen tidligere output.

Hvis du kun har budget til én gennemgang, er vores ærlige råd baseret på dette resultat: kør den frie gennemgang først. Det er den, der er mere tilbøjelig til at finde det fund, du ikke vidste, du skulle lede efter. Derefter, hvis tiden tillader det, følg op med tjeklisten for at sikre, at intet kedeligt blev overset. For et bredere overblik over hvilke skills der håndterer denne type gennemgang godt, se vores oversigt over de bedste kodningsskills.

FAQ

Er process.env-fundet en reel sårbarhed i zx? Det er en reel adfærd, der er værd at en vedligeholder kigger på, ikke en offentliggjort CVE og ikke noget, vi fremstiller som et aktivt exploit. zx er et velbygget, aktivt vedligeholdt bibliotek generelt, og dette er et designvalg, en live reference i stedet for en kopi, der har en ægte mutationskonsekvens for enhver kodevej, der skriver til $.env. Vi verificerede selv linjen mod kilden i stedet for at stole på modellens rapport, hvilket er præcis derfor, vi er trygge ved at kalde det det største fund i hele testen.

Hvorfor kostede skill-armen mindre her, når den kostede mere alle andre steder i denne serie? Vores bedste forklaring er omfang. En design-skill i landingsside-indlægget inviterer til iteration: tjek output, revider, tjek igen. En gennemgangs-tjekliste fungerer anderledes. Den definerer et fast sæt kategorier, der skal gennemgås én gang, hvilket indsnævrer søgningen i stedet for at udvide den. Smallere søgning, færre tokens. Det er en plausibel mekanisme, ikke en bevist, da dette er en enkelt kørsel.

Skal jeg stole på en tjekliste-guidet AI-kodegennemgang til at fange alt? Nej, og det er hovedfundet her. En tjekliste er et gulv-hævende værktøj: den garanterer en konsekvent minimumsgennemgang på tværs af kendte kategorier. Det er ikke et loft-hævende værktøj, og det største fund i hele denne test kom fra en gennemgang, der ikke fulgte en. Brug en tjekliste for dækning og konsistens. Brug den ikke som din eneste gennemgang af kode, der faktisk betyder noget.

Hvad betyder dette for valget af en Claude kodegennemgangs-skill i praksis? Betragt ikke "hvilken skill" som den eneste beslutning. Betragt "hvor mange gennemgange" som den vigtigere. En god tjekliste-skill, som den i vores code-review-checklist listing, er værd at installere for den konsistens og de kategorier, den garanterer. Par den med mindst én uledsaget gennemgang på alt, du faktisk ville udgive, og læs vores dækning af sikkerhedsskills for at se, hvordan vi vejer review skills mod hinanden i kataloget.

Det var serien. Fire opgaver, fire ærlige domme, og den røde tråd gennem dem alle er den samme: en skill ændrer, hvad en model tjekker, ikke om den er i stand til arbejdet. Hvorvidt den udveksling er det værd, afhænger helt af, hvad du bygger, og hvor nøje nogen vil kigge på det bagefter.

★ 9.6/10 × 3

Den gratis startpakke

De 3 skills med vores højeste testscorer plus installations-tjeklisten — det setup, vi selv ville lægge på en frisk maskine. Gratis, på mail.

Én mail med pakken + et kort ugentligt overblik over nye testresultater. Afmeld når som helst.