Käivita ESLint SQL-i süstimise haavatavusega JavaScripti failil ja see läbib veatult. Käivita CodeQL samal koodibaasil ja see märgistab süstimise täpse faili, rea ja andmevoo teega. Mõlemad on staatilise analüüsi tööriistad. Mõlemad uurivad sama lähtekoodi ilma seda käivitamata. Erinevus selles, mida nad leiavad, ei seisne reegli konfiguratsioonis ega keeletoes, vaid selles, kui kaugele iga tööriist vaatab. ESLint uurib korraga ühte funktsiooni ja annab aru, mida ta selle piiri piires näeb. CodeQL jälgib andmeid funktsioonikõnede kaudu, moodulite vahel ja läbi kogu kõnegraafi, kuni see jõuab millegi ohtlikuni.
See erinevus, protseduuridevaheline ja protseduuridevaheline analüüs, on kõige olulisem tehniline mõiste, et mõista, miks erinevad staatilise analüüsi tööriistad leiavad erinevaid asju. See selgitab, miks linter võib anda koodibaasile puhta arve, samas kui keerukam tööriist leiab samast koodist kriitilisi turvaauke. See selgitab, miks turva-SAST-tööriistad on kallid käitada. See selgitab, miks „kiirete” tööriistade vale-negatiivsete tulemuste määr on struktuurilt kõrgem kui „aeglaste” tööriistade vale-negatiivsete tulemuste määr. Ja see on mõiste, mida ettevõtete meeskonnad peavad enne mis tahes staatilise analüüsi tööriistaketi hindamist mõistma.
Vaadake kogu kõnegraafikut, mitte ainult ühte faili
SMART TS XL jälgib andmevooge COBOLi, Java, Pythoni ja kõigi teie tarnitavate keelte vahel.
Rohkem infotMis on intraprotseduuriline analüüs?
Protseduurisisene analüüs uurib ühe funktsiooni, meetodi või protseduuri sees toimuvat, arvestamata, mis juhtub siis, kui see funktsioon kutsub teisi funktsioone või kui need kutsuvad funktsiooni. Analüüsi piir on funktsiooni piir. Kui protseduurisisene tööriist jõuab funktsioonikutseni, siis see peatub, see ei järgi kutset kutsutavale ega tea, mida kutsutav vastuvõetud andmetega teeb.
Intraprotseduurilise analüüsi kanoonilised näited on linting ja elementaarne andmevoog ühe funktsiooni piires:
püüton
def process_input(user_data):
# Intraprocedural analysis sees: user_data used here
query = "SELECT * FROM users WHERE id = " + user_data # flagged: string concat in SQL
return query
Lihtne reegel, mis märgistab stringide liitmise SQL-päringutesse, toimib protseduurisiseselt, kuna ohtlik muster on nähtav ühe funktsiooni sees. Kuid muutke veidi koodi struktuuri:
püüton
def get_user_id(request):
return request.args.get("id") # untrusted input
def build_query(user_id):
return "SELECT * FROM users WHERE id = " + user_id # looks safe in isolation
def handle_request(request):
uid = get_user_id(request)
query = build_query(uid) # vulnerability spans three functions
db.execute(query)
Nüüd on rikutud andmete allikas (request.args.get("id")) on ohtlikust valamust erinevas funktsioonis (db.execute(query)). Ükski funktsioon ei sisalda piisavalt teavet, et protseduurisisene tööriist saaks haavatavust tuvastada. get_user_id Näeb hea välja, see lihtsalt loeb päringust välja. build_query näeb hea välja, see võtab parameetri ja konstrueerib stringi. handle_request Näeb hea välja, see kutsub funktsioone ja käivitab päringu. SQL-süstimine on reaalne, ärakasutatav ja nähtamatu igale tööriistale, mis ei ületa funktsioonide piire.
Milleks on protseduurisisene analüüs hea
Protseduurisisesed tööriistad on kiired. Väga kiired. Kuna nad analüüsivad iga funktsiooni eraldi, skaleeruvad nad lineaarselt koodibaasi suurusega, miljoni rea pikkuse koodibaasi analüüsimine maksab proportsionaalselt sama palju kui kümne tuhande rea pikkuse koodibaasi analüüsimine. See kiirus muudab need ideaalseks järgmistel eesmärkidel:
- Eelnevalt siduda konksud mis jooksevad sisse vähem kui sekundiga
- IDE-sisene tagasiside samal ajal kui arendaja trükib
- CI/CD kvaliteediväravad iga pull requesti puhul
- Stiili ja konventsioonide jõustamine (nimetamine, vormindamine, keerukusnäitajad)
- Kohalike muutujate väärkasutamine (kasutamata muutujad, määratlemata viited, ilmsed tüübivead)
- Tsüklomaatiline keerukus ja meetodi pikkus, puhtalt funktsioonisisesed mõõdikud
Sellesse kategooriasse kuuluvad tööriistad on ESLint, Pylint, Clippy (Rust), golangci-lint, Checkstyle ja enamik lintreid. Need on olulised ja väärtuslikud just nende probleemide puhul, mida nad näevad. Nende piirang on struktuuriline, mitte kvaliteedipuudujääk.
Mis on interprotseduuriline analüüs?
Protseduuridevaheline (kogu programmi hõlmav) analüüs on tavaliselt kõige võimsam ja ressursimahukam. Protseduuridevaheline analüüs täiendab juhtimisvoo graafikuid funktsiooni kutsumis- ja tagastusservadega kutsumisgraafikult. Analüüsi käigus saab vältida samade funktsioonide korduvat külastamist, luues funktsioonide kokkuvõtteid.
Kui protseduuridevaheline analüüs peatub funktsioonide piiridel, siis protseduuridevaheline analüüs ületab need. See loob kõnegraafiku, mis näitab, millised funktsioonid kutsuvad milliseid teisi, seejärel jälgib andmevoogu, juhtimisvoogu või saastumist selle graafiku servades. Kui protseduuridevaheline tööriist kohtub funktsioonikõnega, järgneb see kõnele kutsutavale või kasutab kutsutava käitumise eelarvutatud kokkuvõtet ja jätkab analüüsi teisel pool.
Ülaltoodud kolm SQL-i süstimisfunktsiooni on lihtne näide. Reaalne interprotseduuriline analüüs käsitleb järgmist:
- Mitme hüppega andmevoog: ebausaldusväärne sisend, mis läbib enne ohtlikku neeldumiskohta jõudmist viis funktsiooni
- Tagastusväärtuse rikkumine: funktsioon tagastab rikutud andmed; kutsujad kasutavad seda rikutud tagastusväärtust ohtlikes toimingutes
- Väljatundlik saastumine: objektiväljale salvestatud ebausaldusväärsed andmed, mis hangitakse hiljem teises funktsioonis
- Tingimuslik paljundamine: saastevoogude arv kulgeb ainult teatud täitmisradade kaudu, olenevalt käitustingimustest, mida analüüs peab staatiliselt modelleerima
Java
// Interprocedural vulnerability: three-hop taint flow
public class UserController {
public String handleRequest(HttpServletRequest request) {
String userId = request.getParameter("id"); // source: untrusted input
User user = userService.getUser(userId); // taint flows through call
return generateReport(user); // taint reaches sink
}
}
public class UserService {
public User getUser(String id) {
// id is tainted -- passed to repository
return userRepository.findByRawId(id); // taint propagates
}
}
public class UserRepository {
public User findByRawId(String id) {
String query = "SELECT * FROM users WHERE id = " + id; // sink: SQL injection
return db.execute(query);
}
}
Protseduurisisene tööriist, mis uurib UserRepository.findByRawId eraldi näeb parameetrit id SQL-päringuks liita. See tundub potentsiaalselt ohtlik, kuid tööriistal pole mingit võimalust teada, kuhu id kust see pärineb, võib see olla usaldusväärne ja valideeritud väärtus sisemisest koodist. Seega protseduurisisene tööriist märgistab selle võimaliku probleemina (tekitades valepositiivseid tulemusi iga parameetrilise, kuid struktureeritud päringu puhul koodibaasis) või ignoreerib seda (tekitades valenegatiivseid tulemusi tegelike haavatavuste korral). Protseduuridevaheline plaastrianalüüs tuvastab, kas ebausaldusväärsed andmed voolavad funktsioonide kaudu tundlikesse operatsioonidesse. See jälgib andmeid alates request.getParameter("id") läbi userService.getUser(), läbi userRepository.findByRawId(), Et db.execute(query), andes täpse leiu täpse saastevooluteekonnaga, ilma valepositiivsete ja valenegatiivsete tulemusteta.
Analüüsi kolm tasandit: praktiline spekter
Reaalse maailma staatilise analüüsi tööriistad paiknevad spektril, mis ulatub puhtalt protseduurisisesest kuni täielikult protseduuridevaheliseni. Iga tööriista asukoha mõistmine selgitab nii seda, mida see leiab, kui ka seda, mida see märkamata jätab.
| Analüüsi tase | Ulatus | Mida see näeb | Mida see igatseb | TÖÖRIISTAD |
|---|---|---|---|---|
| Leksikaalne/süntaktiline | Individuaalsed märgid ja süntaks | Vormindamine, nimetamine, põhisüntaks | Kõik semantiline | Ilusam, rustfmt, gofmt |
| Intraprotseduuriline | Üks funktsioon | Kohalik andmevoog, keerukus, juhtimisvoog funktsioonis | Funktsioonidevahelised haavatavused, arhitektuurilised probleemid | ESLint, Pylint, Clippy, golangci-lint |
| Madal interprotseduuriline | Üks kõne sügavuse tase | Otsesed helistaja-helistaja suhted | Sügavad mitme hüppega vood | Mõned Semgrepi reeglid, SAST-i põhireeglid |
| Täielik interprotseduuriline | Täieliku kõnegraafi läbimine | Mitme hüppega saastevood, kontekstitundlik analüüs | Käitusaja polümorfism (osaline), peegeldavad kõned | CodeQL, Facebooki järeldamine, SMART TS XL |
| Terve programm / semantiline | Täielik programmi semantika | Formaalselt tõestatavad omadused | Skaleeritavus väga suurtel koodibaasidel | Infer, Kani (Rust), formaalsed verifitseerimisvahendid |
Protseduuridevahelisel analüüsil on suhteliselt kõrge potentsiaalne efektiivsus ja suhteliselt madal potentsiaalne jõudlus. Tänu rikkalikule programmimudelile on see ka vähem altid vale-negatiivsetele ja vale-positiivsetele tulemustele ning sellel on suhteliselt kõrgem efektiivsus. Protseduuridevaheline analüüs ei sobi CI/CD keskkondadesse oma jõudluspiirangute tõttu, mis võivad vähendada arendaja kiirust. Seetõttu pakutakse protseduuridevahelist analüüsi sageli spetsiaalse teenusena, mis töötab serverifarmides või spetsiaalsetel tööriistadel.
Kuidas interprotseduuriline analüüs toimib: kolm peamist lähenemisviisi
1. Kokkuvõttel põhinev analüüs
Analüüs võib vältida samade funktsioonide korduvat külastamist, luues funktsioonide kokkuvõtteid (mõnikord nimetatakse neid mudeliteks). Kokkuvõte jäädvustab funktsiooni käitumise kompaktsel kujul: antud sisendite komplekti ja nende saastatuse omadustega annab funktsioon nende saastatuse omadustega väljundite komplekti. Kui kutsuja funktsiooni kutsub, loob analüüs kokkuvõtte eksemplari, selle asemel et funktsiooni põhiosa nullist uuesti analüüsida.
Kokkuvõtetel põhinev analüüs muudab interprotseduuridevahelise analüüsi ulatuslikult teostatavaks. Ilma kokkuvõteteta nõuaks teeki kutsuva funktsiooni analüüsimine kogu teeki lähtekoodist alates, sealhulgas iga funktsiooni, mida teek kutsub, rekursiivset analüüsimist. Kokkuvõtete puhul analüüsitakse teekifunktsioone eelnevalt üks kord ja nende kokkuvõtteid kasutatakse iga väljakutse korral uuesti.
2. Kutseliini meetod (kontekstitundlik analüüs)
Kontekstitundlik analüüs eristab sama funktsiooni erinevaid kutsumiskohti. Kui sanitize(input) kutsutakse välja ühes kohas usaldusväärsete ja teises ebausaldusväärsete andmetega, annab kontekstitundlik analüüs iga kutsumissaidi jaoks erinevad tulemused, selle asemel, et konservatiivselt eeldada kõigi jaoks halvimat stsenaariumi. See vähendab oluliselt valepositiivseid tulemusi võrreldes kontekstivaba analüüsiga.
IFDS-i (interprotseduuriline, lõplik, jaotuv, alamhulk) raamistik formaliseerib selle graafi kättesaadavuse probleemina. IFDS-i raamistikus kirjeldatakse vigade voogu jaotusfunktsioonidega lõpliku faktide domeeni ulatuses ja interprotseduuriline levik taandatakse graafi kättesaadavusele. See formuleering muudab IFDS-i analüüsid nii täpseks kui ka algoritmiliselt tõhusaks, tööriistad nagu FlowDroid (Androidile) ja mitmed CodeQL-päringud kasutavad IFDS-i sisemiselt.
3. Kutsegraafi konstrueerimine
Iga interprotseduuriline analüüs nõuab väljakutsegraafikut: suunatud graafikut, kus sõlmed on funktsioonid ja servad esindavad väljakutseid. Kutsegraafi enda loomine hõlmab keerulisi otsuseid:
Staatiline dispetšer (Java mittevirtuaalsed kõned, C funktsioonikõned, Pythoni moodulitaseme kõned): lihtne modelleerida, f() kõned f.
Dünaamiline väljastamine (Java virtuaalsed meetodid, Pythoni parditüüpi kõned): nõuab klassihierarhia analüüsi (CHA) või täpsemaid kõnegraafiku konstrueerimise algoritme (RTA, VTA), et teha kindlaks, milliseid meetodi implementatsioone antud kõnepunktis tegelikult kutsutakse.
Peegeldavad kõned ja funktsiooniviited : kõige raskemad juhtumid. Tööriistad peavad kas üle-aproksimeerima (eeldama, et mis tahes sobivat funktsiooni saab välja kutsuda, mis annab valepositiivseid tulemusi) või ala-aproksimeerima (mõned kõneteed vahele jätma, mis annab vale-negatiivseid tulemusi).
Kutsegraafi täpsus määrab otseselt protseduuridevahelise analüüsi täpsuse. Kutsegraaf, mis sisaldab liiga palju servi (üleaproksimatsioon), annab valepositiivseid tulemusi; kutsegraaf, mis ei vasta servadele, annab valenegatiivseid tulemusi.
Mida protseduuridevaheline analüüs leiab, mida protseduurisisene analüüs ei suuda leida
Turvahaavatavused (plekianalüüs)
Enamik OWASP-i 10 suurimast haavatavusest vajavad usaldusväärseks tuvastamiseks protseduuridevahelist nakkeanalüüsi:
- SQL süstimine: ebausaldusväärne sisend liigub andmebaasipäringusse läbi mitme funktsiooni
- XSS: ebausaldusväärne HTML voolab läbi renderdusfunktsioonide väljundkonteksti
- Käsu süstiminekasutaja kontrollitud andmete ulatus
exec()orsystem()vahendusfunktsioonide kaudu - Tee läbimine: kasutaja sisendist tuletatud failiteed jõuavad failisüsteemi toiminguteni
- SSRF: kasutaja kontrollitud URL-id suunatakse HTTP-kliendikõnedele
püüton
# Intraprocedural tool: sees no issue in any individual function
# Interprocedural tool: traces the full taint path and reports SSRF
def get_target_url(request):
return request.json().get("url") # source: attacker-controlled
def fetch_resource(url):
return requests.get(url) # sink: SSRF
def api_endpoint(request):
target = get_target_url(request)
data = fetch_resource(target) # full path: source -> sink
return data
Nullpointeri ja mälu turvalisuse probleemid
Facebook Infer on kanooniline interprotseduuriline tööriist nullturvalisuse analüüsiks. See kasutab bi-abduktsiooni, mis on interprotseduurilise arutluskäigu vorm, funktsioonide eeltingimuste ja järeltingimuste avastamiseks ning seejärel kontrollib, kas kutsujad vastavad neile eeltingimustele. Null-dereferents, mis nõuab teadmist, et funktsioon saab teatud tingimustel tagastada nullväärtuse, on intraprotseduurilistele tööriistadele nähtamatu.
Java
// Intraprocedural tool: no issue in either function
// Infer: finds that processResult() can receive null from fetchData()
String fetchData(boolean condition) {
if (condition) return getData();
return null; // can return null
}
void processResult(String result) {
System.out.println(result.length()); // NPE if result is null
}
void run() {
String data = fetchData(false); // passes false: fetchData returns null
processResult(data); // null dereference
}
Pärast vabaks saamist kasutus ja ressursilekked
C ja C++ puhul hõlmavad use-after-free vead sageli mälu eraldamist ühes funktsioonis ja vabastamist teises, kusjuures kolmas funktsioon säilitab viite. Ükski ühe funktsiooni analüüs ei suuda seda tüüpi vigu tuvastada. Protseduuridevaheline analüüs analüüsib juhtimisvoo terviklikkust: tagades, et funktsioonikõned järgivad oodatavaid mustreid, et vältida rünnakuid.
Arhitektuurilise sidumise ja sõltuvuste rikkumised
Lisaks turvalisusele ja korrektsusele rakendatakse interprotseduuride analüüsi ka arhitektuurianalüüsis: millised komponendid kutsuvad millist, millised sõltuvused rikuvad määratletud kihtide piire ja millised muudatused kutsegraafi kaudu kaskaaditakse. See on interprotseduuride analüüsi rakendus, mida sellised tööriistad nagu SMART TS XL Rakenda ettevõtte koodibaasidele, jälgides, kuidas ühe funktsiooni muudatus levib läbi kogu kõnegraafiku, et määrata kindlaks tegelik mõju ulatus.
Kui vajate interprotseduurilist analüüsi
Mitte iga projekt ei vaja täielikku interprotseduurilist analüüsi. Otsus sõltub sellest, mida te otsite ja kui suur on selle leidmata jätmise hind.
Interprotseduurilist analüüsi on vaja järgmistel juhtudel:
- Turvalisus on esmatähtis ja peate usaldusväärselt leidma süstimis-, XSS- või SSRF-nõrkused.
- Sa analüüsid pärand- või ettevõtte koodibaasi, kus äriloogika hõlmab paljusid funktsioone ja mooduleid.
- Enne refaktoreerimist on vaja mõjuanalüüsi, et mõista, mida funktsiooni muutmine mõjutab.
- Te teete vastavus- või auditianalüüsi, mis nõuab põhjalikkuse tõendamist.
- Sa migreerid või kaasajastad koodibaasi ja pead mõistma komponentidevahelisi sõltuvusi.
Intraprotseduurilisest analüüsist piisab, kui:
- Eesmärk on stiili jõustamine, konventsioonide järgimine ja ilmsete kohalike vigade tabamine.
- Teil on vaja kiiret tagasisidet, mis on integreeritud arendustsüklisse (eelkoostamine, IDE, PR-põhine CI).
- Koodibaas on piisavalt väike, et arendajad teaksid kõiki kõnedevahelisi seoseid
- Turvalisust rakendatakse teisel tasandil (valideeritud raamistik, tüübisüsteem) ja funktsioonidevaheliste haavatavuste oht on madal.
Praktiline vastus enamiku meeskondade jaoks: kasutage mõlemat. Protseduurisisesed tööriistad (ESLint, Pylint, Clippy) töötavad iga commit'i korral kiire tagasiside saamiseks. Protseduuridevahelised tööriistad (CodeQL, Infer, Semgrep koos taint-reeglitega) töötavad pull-request'ide korral või öise ajakava alusel põhjaliku analüüsi jaoks. Need kaks kihti täiendavad teineteist, mitte ei konkureeri omavahel.
Interprotseduurilise analüüsi tööriistad: mida igaüks neist hõlmab
| Vahend | Analüüsi lähenemisviis | Keeled | Esmane kasutusjuht |
|---|---|---|---|
| CodeQL | Täielik interprotseduuriline, IFDS-põhine | C/C++, Java, JS/TS, Python, Go, Ruby | Turvanõrkuste tuvastamine |
| Facebooki järeldus | Kahepoolne röövimine, interprotseduuriline | Java, C, C++, Objective-C | Nullturvalisus, mälulekked, võistlustingimused |
| Semgrep (riknemisrežiim) | Madal interprotseduuriline plekk | 30 + keeled | Turvamustrite sobitamine andmevooga |
| Snyki kood | ML-põhine interprotseduuriline | Java, JS/TS, Python, C# | Turvalisus arendajasõbraliku tagasisidega |
| Polüruum | Abstraktne tõlgendus | C, C++, Ada | Ohutuskriitilised manussüsteemid |
| Frama-C | Täielik interprotseduuriline + formaalne | C | Formaalne kontroll, ohutussertifitseerimine |
| SMART TS XL | Keelteülene, süsteemideülene | COBOL, JCL, Java, Python, RPG, SQL | Ettevõtte mõju analüüs, sõltuvuste kaardistamine |
Keelepiirideülene interprotseduuriline analüüs
Standardsed interprotseduurilised tööriistad töötavad ühe keele piires. Java koodibaasil tehtud CodeQL päring jälgib saastumist Java funktsioonikõnede kaudu, kuid peatub, kui Java kood kutsub välja COBOL-programmi või loeb JCL-i partiitöö abil kirjutatud andmestikku. See piir on koht, kus ettevõtte tasemel analüüsitööriistad seisavad silmitsi probleemiga, mida ühe keele tööriistad ei suuda lahendada.
SMART TS XL'S staatilise koodi analüüs teostab interprotseduurilist sõltuvusanalüüsi samaaegselt kõigis ettevõtte keskkonna keeltes. Kui Java teenus kutsub COBOL-programmi, mis loeb DB2 tabelist, et teine JCL-töö täidab tabeli, SMART TS XL jälgib seda ahelat ja esitab seda ühtse sõltuvusmudelina. mõju analüüs Seejärel rakendab võimekus seda keeltevahelist kõnegraafikut, et vastata küsimusele: kui see COBOL-programm muutub, siis millised Java-teenused, millised JCL-tööd ja millised allavoolu tarbijad muutuvad?
See on protseduuridevaheline probleem, mida rakendatakse arhitektuurilisel, mitte funktsioonide tasandil, sama põhimõtet (jälgida sõltuvusgraafikut üle piiride, mitte nende juures peatuda) rakendatakse kogu ettevõtte süsteemile, mitte üksikutele programmidele. Nagu koodi visualiseerimise ja sõltuvuste kaardistamise kontekstis uuritud , on kogu sõltuvusstruktuuri nähtavaks tegemine iga analüüsi eeltingimus, mis väidab, et mõistab muudatuse mõju.
Organisatsioonidele, kes korraldavad pärand moderniseerimine, kõnegraaf, mis SMART TS XL Keelteülene ehitus täidab sama eesmärki kui ühe keele interprotseduraalne kõnegraaf: see on kaart sellest, kuidas kõik on omavahel seotud, ja ilma selleta põhineb igasugune mõju, riski või migratsioonijärjestuse analüüs pigem eeldustel kui tõenditel.
Valepositiivse ja valenegatiivse kompromissi
Põhjus, miks interprotseduraalset analüüsi kõikjal ei kasutata, ei ole see, et keegi pole selle peale mõelnud, vaid see, et täpsus ja jõudlus on pinge all. Miljonirealise koodibaasi täielik kontekstitundlik interprotseduraalne analüüs võib võtta tunde või päevi. Sama koodibaasi analüüsimine ESLinti abil võtab sekundeid. See jõudluse erinevus on struktuuriline: interprotseduraalne analüüs kasvab koos kõnegraafi keerukusega, mitte ainult koodibaasi suurusega.
Investeeringu eeliseks on mõõdetavalt madalam valepositiivsete ja valenegatiivsete tulemuste määr:
- Valepositiivsed (tööriistad, mis väidavad, et midagi on valesti, kui see pole nii): protseduurisisesed tööriistad annavad palju rohkem valepositiivseid tulemusi, kuna nad ei suuda kindlaks teha, kas kahtlane muster on tegelikult ohtlik, ilma helistajatelt konteksti teadmata. Protseduurisisene tööriist, mis näeb SQL-päringut liidetud stringiga, ei saa teada, kas string pärineb kasutaja sisendist või usaldusväärsest sisemisest allikast.
- Vale negatiivid (tööriistad, millel puuduvad tegelikud haavatavused): protseduurisisesed tööriistad annavad palju rohkem vale-negatiivseid tulemusi, kuna need ei suuda tuvastada haavatavusi, mis ületavad funktsioonide piire, mis turvalisusega seotud analüüsi jaoks moodustavadki enamiku tegelikest haavatavustest.
Iga analüüsitaseme kasutamise aja valimise ja mõlema kombineerimise distsipliin kihilises tööriistaketis eristab turvainsenerlust märkeruutude järgimisest. Teadmine, et teie linter annab puhtaid tulemusi, ütleb teile teie turvaseisundi kohta väga vähe. Teadmine, et teie protseduuridevaheline riknemisanalüüs on jälginud iga teed välistest sisendallikatest kuni teie rakenduse tundlike neeldajateni ega leidnud valideerimata voogu, ütleb teile oluliselt rohkem.


