← Tornar al blog

Audita el Teu Propi Codi Com Si Fossis l'Atacant

No pots revisar el teu propi codi (i tot i així ho has de fer)

Quan revises la teva pròpia feina, el teu cervell fa trampa. Llegeixes el que volies escriure, no el que vas escriure. El teu objectiu implícit és confirmar que està bé — i el biaix de confirmació és molt bo trobant evidència del que ja creus. Per això l’autorevisió clàssica caça errates, noms de variable i format, però se li escapen els defectes de disseny, els forats de seguretat i els casos límit. Aquests no es veuen quan busques confirmació; es veuen quan busques sang.

La revisió adversària és un canvi d’objectiu deliberat: en lloc de “demostrar que això funciona”, et proposes demostrar que això està trencat. És la mateixa diferència que hi ha entre un test que passa i un test que mira de trencar. I encara que sona a una cosa reservada a pentesters, és una disciplina que pots —i hauries de— aplicar al teu propi codi abans que ho faci algú amb pitjors intencions.

La diferència entre revisar i atacar

Revisar pregunta “està ben fet?”. Atacar pregunta “com el trenco?”. Són dos modes mentals diferents i produeixen troballes diferents.

El mode atacant assumeix hostilitat per defecte. L’entrada no és la que esperes, és la pitjor possible. L’usuari no és benèvol, és un adversari amb temps. La xarxa falla en el pitjor moment, dues peticions arriben alhora just on no toca, i la dada que “sempre” ve plena arriba nul·la. No estàs comprovant que el camí feliç funcioni — estàs caçant els camins infeliços que ningú no va escriure a propòsit.

El canvi de pregunta

Abans de mirar una línia, canvia la pregunta que et fas. No “això és correcte?” sinó “si hagués de provocar una fallada, una fuita o una dada corrupta des d’aquí, per on entraria?”. Aquest reenquadrament, per si sol, canvia el que els teus ulls veuen.

Una passada per cada barret

L’error més comú en revisar és intentar veure-ho tot alhora i, a la pràctica, no veure gairebé res. La revisió adversària funciona molt millor per lents: una passada completa amb un sol barret posat, després una altra amb el següent.

  • Correcció — fa el que diu? els casos límit, el buit, el zero, el negatiu?
  • Seguretat — entrades no fiables, injecció, autorització, secrets als logs?
  • Concurrència — què passa si això s’executa dues vegades alhora? hi ha estat compartit sense protegir?
  • Modes de fallada — què passa quan la dependència de la qual estira això es cau? l’error es propaga o se l’empassa en silenci?
  • Rendiment — escala amb el pitjor cas de mida d’entrada, o és lineal on hauria de ser constant?

Cada lent et fa una persona diferent durant deu minuts. La de concurrència no es distreu amb un nom lleig; la de seguretat no perdona un catch buit. Barrejar-les és la recepta perquè totes perdin agudesa.

No et fiïs del primer veredicte

Un sol revisor —humà o agent— s’equivoca en dues direccions: veu defectes on no n’hi ha (falsos positius) i es perd defectes reals (falsos negatius). La manera de domar tots dos és la verificació independent: més d’un revisor, sense que es vegin entre si, i una regla de decisió sobre els seus vots.

  • Per confirmar que una troballa és real, exigeix majoria. Si tres revisors miren un suposat bug i només un el veu, probablement és soroll. Això retalla els falsos positius que et farien perdre el temps.
  • Per descartar que una cosa és segura, sigues estricte: que un revisor aixequi la mà ja n’hi ha prou per investigar. Aquí el cost d’un fals negatiu (un bug real ignorat) és més gran que el de mirar de més.

La independència és la clau, i és fràgil. Si els revisors es veuen els veredictes entre si, s’ancoren i deixen de ser independents: el segon tendeix a ratificar el primer. Cada judici s’ha d’emetre a cegues sobre l’estat del codi, no sobre l’opinió d’un altre revisor.

Classifica per severitat

Una troballa sense severitat és soroll sense accionar. Abans de tancar l’auditoria, cada troballa rep una classificació —l’esquema CVSS 3.0 és un bon estàndard de partida— en quatre nivells: Crític, Alt, Mitjà, Baix. La severitat no és burocràcia: és el que et diu què arreglar abans de desplegar, què arreglar aquest sprint i què anotar com a deute conscient.

SeveritatSignificatAcció
CríticExplotable, impacte greu, sense mitigacióBloqueja el desplegament
AltRisc seriós, mitigació parcialArregla’l abans de tancar
MitjàRisc real en certes condicionsPlanifica’l, no l’ignoris
BaixDefensa en profunditat, higieneAnota’l i vigila’l

”Zero crítics” no és seguretat

Aquí hi ha el parany que enfonsa més equips: acabar una auditoria amb zero troballes crítiques i cantar victòria. L’absència de crítics no és el mateix que seguretat. La primera cosa, perquè un crític que no vas trobar no apareix a l’informe — i l’informe només reflecteix el que vas mirar. La segona, perquè les troballes mitjanes i baixes es componen: tres “mitjans” alineats —un log que filtra de més, una validació fluixa i un permís heretat— poden encadenar l’incident que cap “crític” aïllat no hauria provocat.

L'informe no és el territori

Un informe d’auditoria amb zero crítics descriu el que l’auditor va mirar i no va trobar, no el que existeix. Tracta’l com un mapa parcial, no com un certificat. La pregunta útil no és “ha sortit net?” sinó “què no vam arribar a mirar?”. El que no vas auditar es llegeix, equivocadament, com a auditat.

Agents com a red team

Hi ha un gir modern: fer servir agents d’IA com a revisors adversaris. Encaixen sorprenentment bé, perquè el patró que ja vam descriure —diversos revisors independents amb lents diferents— es paral·lelitza de manera natural. Llences diversos agents alhora, a cadascun li dones una lent i la instrucció explícita de refutar (no d’aprovar), i apliques la regla de majoria sobre els seus veredictes.

La clau és el prompt adversari: demana-li a l’agent que assumeixi que el codi és culpable i que la seva feina és provar la culpabilitat, no la innocència. Un revisor —de silici o de carboni— a qui li demanes que confirmi que tot està bé, confirmarà que tot està bé. Un a qui li demanes que trobi el defecte, busca de debò. El biaix de confirmació també s’aplica a les màquines; l’antídot és el mateix: canviar la pregunta.

Una checklist adversària

Per a una sessió concreta, aquesta llista cobreix la major part del valor:

  • Modela l’amenaça. Qui voldria trencar això i què hi guanyaria? Sense actor no hi ha focus.
  • Enumera les fronteres de confiança. Cada punt on una dada creua de “no fiable” a “fiable” és un lloc per validar — o per colar-se.
  • Assumeix entrada hostil. Nul, buit, gegant, amb caràcters estranys, fora de rang. Què es trenca?
  • Caça les fallades silencioses. Busca cada catch que no rellança ni registra, cada error que s’empassa, cada valor per defecte que amaga un problema.
  • Qüestiona l’aïllament. En sistemes multi-inquilí, pot un tenant veure dades d’un altre per algun camí? Les fuites d’aïllament gairebé mai no són òbvies.
  • Verifica el que verifiques. Cada troballa, confirma-la amb una segona mirada independent abans de donar-la per bona.

Preguntes freqüents

Què és una revisió de codi adversària?

És una revisió l'objectiu de la qual és demostrar que el codi està trencat, no confirmar que funciona. Adopta la mentalitat de l'atacant —assumeix entrada hostil, concurrència en el pitjor moment i dependències que fallen— per trobar defectes de disseny i de seguretat que l'autorevisió, esbiaixada cap a la confirmació, deixa passar.

Per què és mala idea revisar el teu propi codi buscant que estigui bé?

Pel biaix de confirmació: si el teu objectiu és confirmar que funciona, el teu cervell troba evidència d'això i omet el que ho contradiu. Llegeixes el que volies escriure, no el que vas escriure. Per això l'autorevisió caça errates però es perd els defectes de disseny i els casos límit.

Per què 'zero troballes crítiques' no significa que el codi sigui segur?

Perquè un informe només reflecteix el que es va mirar: un crític no trobat no apareix. A més, diverses troballes de severitat mitjana o baixa es componen —un log que filtra, una validació fluixa i un permís de més poden encadenar un incident que cap crític aïllat no hauria causat. La pregunta útil és què no es va auditar.

Es poden fer servir agents d'IA per a revisió adversària?

Sí, i encaixen bé perquè el patró de diversos revisors independents amb lents diferents es paral·lelitza de manera natural. La clau és el prompt adversari: demanar a cada agent que assumeixi que el codi és culpable i miri de provar-ho, no que confirmi que està bé. Després s'aplica una regla de majoria sobre els seus veredictes.

Conclusió

La revisió adversària no és desconfiança, és disciplina. És acceptar que el teu cervell està cablejat per veure el que espera veure, i construir un procés que compensi aquest biaix: canviar la pregunta de “funciona?” a “com el trenco?”, revisar per lents en lloc de tot alhora, verificar amb diverses mirades independents, classificar per severitat i no confondre “zero crítics” amb “segur”.

Fes-ho com a pràctica permanent, no com a ritual previ a una release. L’atacant auditarà el teu codi tard o d’hora. L’única pregunta és si ho fas tu primer.