A grep for eval( takes two seconds. The reason teams still ship it is that nobody runs the grep, and the twelve other patterns worth checking never turn into a habit. This page runs the whole list at once against whatever you paste, then prints the line number and the replacement you were going to look up anyway.
What follows explains every rule the scanner fires, the false positives baked into a few of them, and the fixes behind the one-line advice in the results pane. Read the rule table before you act on a finding. A flag here is a prompt to look at a line, not a verdict on it.
The scanner reads text. It has no parser, no data flow graph, and no way to tell whether a variable holds user input or a constant. A query built by joining two hardcoded strings gets flagged as SQL injection. A tainted value passed through four safe-looking helpers before reaching innerHTML slips straight past. Use it as a first pass over a file you are already reading.
Every rule the scanner runs
Nine rules fire at any intensity. Three more wait for Strict. Each row lists the trigger so you know exactly why a line lit up.
- SQL Injection Critical
- The file contains
SELECTand a quoted string joined with+. Classic string-built query. Fix with placeholders, never with escaping helpers. - Code Injection Critical
- Any occurrence of
eval(. Whatever string reaches it runs with full page privileges, including anything an attacker planted upstream. - Cross-Site Scripting High
innerHTMLappears alongside a+, a template literal, or the wordlocation. Markup assembled from values you did not write.- DOM-based XSS High
location.hashorlocation.searchin a file that also writes throughinnerHTMLordocument.write. The URL bar becomes an input field for your DOM.- Hardcoded Secrets High
- An assignment matching
api_key,secret_key,password, ortokenwith a quoted value. Git keeps deleted secrets forever, so rotate the key instead of only removing the line. - Weak Cryptography High
btoa(near the word password. Base64 is transport encoding. Anyone holding the string gets the password back in one call.- Insecure Storage Medium
localStorageplus password or token. Every script on the origin reads it, so one XSS bug turns into stolen sessions.- Insecure Communication Medium
- A literal
http://URL. Plain text on the wire, and mixed content blocks the request on an HTTPS page anyway. - CSRF Vulnerability Medium
fetchwith no mention ofcsrforX-CSRF-TOKENin the same file. The noisiest rule on the list, covered below.- Deprecated Function MediumStrict
document.write. Blocks the parser, and after page load it wipes the document before writing.- Unsafe Function Call MediumStrict
setTimeoutorsetIntervalhanded a string instead of a function reference. A secondevalin disguise.- Missing Strict Mode LowStrict
- No
use strictin the file. Hygiene rather than a hole, and irrelevant inside ES modules, which are strict already.
What the two selectors change, and what they do not
Both dropdowns behave differently than their labels suggest, so here is the honest version.
| Control | Real effect | What it does not do |
|---|---|---|
| Editor syntax | Switches highlighting in the editor and picks which sample file the clipboard button loads. | Rules stay identical across all six choices. Nothing turns on a PHP-only or Python-only check. |
| Basic and Standard | Run the same nine rules. No difference between them today. | Basic is not a faster or narrower pass. |
| Strict | Adds document.write, string-argument timers, and the missing strict mode check. | Adds nothing for PHP, Python, SQL, Java, or C# files. |
Rules are written around JavaScript syntax, and several of them carry over cleanly. eval exists in PHP and Python, string-built SELECT statements look the same in every language, and secret assignments match regardless of the file type. Rules keyed to innerHTML, localStorage, and fetch stay quiet outside browser code. A Java or C# file gets syntax highlighting plus the language-neutral subset of checks.
False positives worth knowing before you file tickets
Three rules match more than they should. Recognise them on sight and you save an hour of chasing.
- CSRF on every fetch. The rule scans the whole file for the token strings. Your app might set the header once in an axios interceptor, a Blade meta tag, or a fetch wrapper in another module. A read-only
GETneeds no token at all. Confirm where your token is attached, then move on. - Hardcoded secrets in variable names.
const passwordLabel = "Password"matches the pattern. So does a test fixture and a form placeholder. Look at the value, not the flag. - SQL injection with no user input. Two concatenated constants near a
SELECTtrip the rule. Still worth a glance, because those constants have a way of turning into parameters six months later.
The reverse gap matters more. Anything the scanner cannot see in the text stays invisible: a template rendered server side, a value read from a config object, a sink reached through a callback. Files that come back clean have not been proven safe.
Fixes behind the four findings that matter most
The results pane prints one line of advice. Here is what each one means in practice.
Parameterised queries instead of concatenation
Placeholders keep the query structure and the data on separate channels, so a quote character in a username stops being syntax. Escaping helpers try to solve the same problem by rewriting the data, and they lose to encoding edge cases.
// flagged
const q = "SELECT * FROM users WHERE email='" + email + "'";const q = "SELECT * FROM users WHERE email = ?";db.query(q, [email]);textContent instead of innerHTML
textContent writes a text node. A <script> tag inside the value stays visible as characters rather than becoming an element. When you need real markup, build nodes with createElement or sanitise through a maintained library before assignment.
// flagged
box.innerHTML = "<div>Welcome " + name + "</div>";const row = document.createElement("div");row.textContent = "Welcome " + name;box.replaceChildren(row);JSON.parse instead of eval
Almost every eval in production exists to turn a string into an object. JSON.parse does that job and throws on anything that is not data. If the goal was reaching a dynamic property, bracket notation on a lookup object covers the case with no execution involved.
Environment variables instead of literals
Move the value into .env, read it server side, and confirm the file sits in .gitignore. Then rotate the key, because it has lived in your commit history since the first push. Client-side code is a special case: anything shipped to the browser is public, so a key that reaches the bundle needs origin restrictions and scope limits on the provider dashboard, not hiding.
Where this fits in a review
Run it on a file you are about to review, before you read it line by line. Twelve seconds of scanning tells you which functions deserve slow attention. That is the whole use case.
It replaces nothing in a release gate. Repository-wide scanning belongs to tools that walk your dependency tree and parse each file properly. On this site, the Code Vulnerability Scanner covers overlapping ground with a different rule set, and the Security Test Generator turns these concerns into runnable negative tests against your endpoints.
For SQL specifically, rewriting a flagged query goes faster next to the SQL Query Tester, where you check the parameterised version still returns what you expect. Findings from the Code Complexity Analyzer tend to cluster in the same functions the security rules flag, since long functions hide their sinks well.
Reading the rating
The rating is a label derived from counts, not a score anyone benchmarked. Any Critical finding reads Poor. Any High with no Critical reads Fair. Medium alone reads Good, Low alone reads Very Good, and a clean pass reads Excellent. It gives you a glance value for a single file. Keep it out of dashboards and pull request templates. A file with one real SQL injection and a file with one false-positive CSRF flag both read Poor, and only one of them should stop a merge.
Rules audited August 2026 against the shipping ruleset. Scanning runs entirely in your browser. No code is uploaded, stored, or logged by Toolexe.
