What this guide covers
How do I run a security review and a code quality review on JavaScript generated by Claude Opus, remediate the findings, and prove what actually changed on the rescan?
One Claude Opus prompt produced a working shipment desk and eleven security rule families in a single upload. Running the same scan settings again after one remediation prompt shows exactly which families moved and which need a human decision.
DerScanner runs security (SAST) and Code Quality (CQ) in one scan when you pass both languages and cqLanguages. JavaScript supports both, so a single upload covers the security review and the quality review.
A security review of Claude-generated code is not a formality. Weak hashing, hardcoded credentials, plain-HTTP egress, and string-concatenated SQL all shipped in code that ran correctly on the first try.
Before you start
- A DerScanner installation you can reach over HTTP, and an administrator account that can create users if needed.
- A user account for this work that is not the administrator account. The screenshots were taken under a dedicated account named Cursor.
- curl, or any HTTP client that can send multipart form data.
- Cursor with the Claude Opus model selected, for the generation and remediation prompts.
Environment
- DerScanner deployment
- Self-hosted installation on a single host at http://localhost/. Replace the host in every command with your own. Cloud DerScanner uses the same API paths under your tenant URL.
- AI coding tool and model
- Cursor with Claude Opus selected as the model. Both the generation prompt and the remediation prompt were sent from Cursor; no code was written by hand except the three string literals noted in the remediation step.
- Scan target
- Synthetic ShipDesk Express + plain JavaScript + SQLite service, 630 analyzed lines in the baseline archive, generated from one prompt with no hand-edits before the first scan.
- SAST engine
- Classic JavaScript engine (sastEngineByLanguage.JAVASCRIPT = CLASSIC). Code Quality for JavaScript runs through the same pass when cqLanguages is set.
- Baseline scan UUID
- a14e4890-66ce-4260-b6dd-277b323b9fa3 — 31 security findings (6 critical, 24 medium, 1 low), score 16 across 630 LOC; 700 Code Quality findings with 431 critical and a CQ score of 1.
- After-remediation scan UUID
- ede2a8b0-db59-40c2-9db8-f3f89e0ec4c2 — 5 security findings (3 critical, 2 medium), score 65 across 822 LOC; 315 Code Quality findings with zero critical and a CQ score of 92.
The walkthrough
Step 1
Generate the application with Claude Opus in Cursor
Start from code that was never reviewed line by line, the way AI-assisted delivery usually works.
This guide uses a synthetic ShipDesk shipment and waybill desk written for the walkthrough only. It is not a real product and was never deployed. Everything under src/ came from one prompt sent to Claude Opus in Cursor; nothing was edited by hand before the baseline scan.
The prompt asked for a small logistics desk — staff login, searchable shipment lists, CSV waybill reports that can be zipped and emailed, waybill scan upload and download, a column layout import from an old desktop tool, and admin endpoints for warehouse sync and server stats. It deliberately did not ask for security hardening, tests, or Docker.
The result ran correctly. That is the point worth holding onto before the scan: working and reviewed are different properties, and a Claude Code security review exists to test the second one.
Save the prompt text alongside the archive you upload so later readers can see what the model was asked to produce.
We need a small internal shipment desk so the logistics team stops tracking waybills
in a shared spreadsheet. Build it with Express and plain JavaScript, SQLite is fine.
What it has to do:
- warehouse staff log in with username and password
- list shipments with search (filter by whichever column the user picks) and sort
- create and update shipments, assign a carrier
- export a waybill report as CSV for a date range, optionally zip it for email
- upload and download waybill scans (PDF, photos)
- import a saved column layout from our old desktop tool (it exports JSON we can load)
- admin endpoints: run the warehouse inventory sync script and show server stats
Keep it in a handful of files under src/, no ORM, plain SQL is fine. Skip tests
and Docker for now. Peak season starts next week, just make it work.Step 2
Issue an API token
Drive both scans from a shell without installing anything into the IDE.
Request a token with the account credentials and a name you will recognise later. Send the access token as a bearer credential on every subsequent request.
If token creation returns SESSION_LIMIT_REACHED, revoke unused tokens or clear active JWT sessions on the installation before retrying. Tokens on the captured installation expire after fifteen minutes of inactivity, so reissue before a long session.
curl -s -X POST "https://derscanner.example.com/app/api/v1/auth/jwt" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "username=$DERSCANNER_USER" \
--data-urlencode "password=$DERSCANNER_PASSWORD" \
--data-urlencode "token_name=shipdesk-api"
# {"accessToken":"eyJhbGciOiJIUzUxMiJ9..."}Step 3
Run the baseline scan with SAST and Code Quality
Capture the first security and quality snapshot before any remediation.
Start the scan with languages=JAVASCRIPT and cqLanguages=JAVASCRIPT so DerScanner analyses security rules and code-quality rules in the same pass. Passing a name on the first scan creates the project; reuse the returned project UUID for the rescan so both scans sit side by side.
Keep AI triage flags off for every severity. The scan analyses the code and leaves every finding unverified until you choose otherwise.
The scan finished in about a second on this sample and reported 31 security findings — six critical, twenty-four medium, one low — with a security score of 16 across 630 lines. Code Quality on the same scan reported 700 findings with 431 critical and a CQ score of 1.
TOKEN="$DERSCANNER_TOKEN"
curl -s -X POST "https://derscanner.example.com/app/api/v1/scan/start" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@shipdesk-javascript.zip" \
-F "name=ShipDesk JavaScript sample" \
-F "languages=JAVASCRIPT" \
-F "cqLanguages=JAVASCRIPT" \
-F "checkboxNoBuild=true" \
-F "preprocessing=true" \
-F "aiTriageCritical=false" \
-F "aiTriageMedium=false" \
-F "aiTriageLow=false" \
-F "aiTriageInfo=false" \
-F "applyTriage=false"
# {"projUuid":"543e6449-...","scanUuid":"a14e4890-..."}Step 4
Read the baseline security metrics
Record the numbers you will compare after remediation.
Poll the project scan list until status is COMPLETE. Each scan DTO carries the security counts (critical, medium, low, info, score, loc) and the quality counts (criticalCq, mediumCq, lowCq, scoreCq, locCq) in one response, so a single call gives you both halves of the review.
A security score of 16 out of 100 is the headline, but the rule families matter more. Eleven fired on the baseline: SQL injection, reflected XSS, weak hashing, plain HTTP usage, hardcoded password, hardcoded crypto key, insecure randomness, three separate cookie rules, and unexpected network activity.
Note that DerScanner does not ship a single report that merges security and quality. Export the fields you need from the API or the Overview page, then assemble the combined view in Cursor Canvas or your own reporting tool.
TOKEN="$DERSCANNER_TOKEN"
PROJECT="543e6449-7c41-47ea-b293-cbbf8fe4b395"
BASELINE="a14e4890-66ce-4260-b6dd-277b323b9fa3"
curl -s "https://derscanner.example.com/app/api/v1/projects/$PROJECT/scans?offset=0&limit=5" \
-H "Authorization: Bearer $TOKEN"
curl -s "https://derscanner.example.com/app/api/v1/scans/$BASELINE/issues?offset=0&limit=100" \
-H "Authorization: Bearer $TOKEN"Step 5
Review what the security review actually found
Connect rule IDs to concrete code patterns Claude Opus produced.
Open the detailed results for the baseline scan. Fourteen JS_INJECTION_SQL hits dominate the list — every query in the login path, the shipment search, the status counters, the report date range, and the carrier lookup is assembled by string concatenation, and the update helper builds its SET clause by looping over request-body keys.
JS_CRYPTO_BAD_HASH covers MD5 password hashing and SHA-1 request signing. JS_CRYPTO_BAD_RANDOM points at a session token derived from Math.random. JS_CRYPTO_KEY_HARDCODED and two JS_PASSWORD_HARDCODED hits point at the session secret, the admin token, and the carrier API password sitting in source.
JS_HTTP_USAGE and JS_BACKDOOR_NETWORK_ACTIVITY flag carrier tracking calls made over plain HTTP with the API password in a request header. The three cookie rules — JS_COOKIE_NOT_HTTPONLY, JS_COOKIE_NOT_OVER_SSL, JS_COOKIE_BROAD_PATH — all trace to one res.cookie call with no attributes at all.
Three JS_XSS_REFLECTED hits land on the HTML report preview, which interpolates the report title, the date range, and every row of shipment data straight into a template string.
Step 6
Read the Code Quality half of the same scan
Show what the quality review adds that the security review does not cover.
Switch the Overview and Detailed Results pages to the CQ slice. The URLs are the same paths with /cq appended, so /projects/$PROJECT/summary_data/cq and /projects/$PROJECT/detailed_results/cq both take the same scan query parameter.
The baseline CQ score is 1 out of 100 across 700 findings. Read the rule mix before reacting to the number: 211 hits for incorrect use of single quotes and 120 for quote formatting are string conventions, while 89 uses of var, 8 string literals thrown as errors, 2 eval calls, and 1 unguarded for…in loop are genuine hygiene problems.
That split is the useful part of a quality review on AI-generated code. The convention hits tell you the model ignored a house style it was never given; the hygiene hits overlap with security — the two eval calls are the same dynamic-execution sinks a reviewer would flag by hand, reached through the layout import and a legacy filter helper.
Step 7
Trace Code Quality findings to source lines
Give the remediation prompt concrete targets instead of a score.
The CQ detailed results list every finding with its file and line, so you can group by rule before writing the remediation prompt. Grouping matters here: two rules account for 331 of the 431 critical findings, and fixing them is a formatting decision rather than a code change.
The remaining critical hygiene rules are the ones worth prompting about individually — replace var with const and let, throw Error objects instead of string literals, and remove both eval sinks.
Step 8
Remediate with a second Claude Opus prompt
Fix vulnerabilities and hygiene issues without changing the feature set.
Send a second prompt in Cursor that references the DerScanner results and asks for specific fixes. Keep the security list and the quality list separate so the model does not treat a formatting rule as a security fix.
The remediation prompt is saved as PROMPT-REMEDIATION.txt in the sample archive so the before/after provenance is clear. Re-zip the project after Cursor applies the edits, keeping the same top-level folder name — Scans Comparison matches findings by file path, so a changed archive root makes every finding look fixed and re-added.
Three string literals containing double quotes had to be adjusted by hand afterwards, because the formatter prefers single quotes for those and the quality profile does not. Everything else came from the prompt.
Resist the temptation to tune code against individual rules. The goal is the fix batch a team would actually accept from an AI assistant after a scan.
The ShipDesk JavaScript service was scanned with DerScanner (SAST + Code Quality).
Fix every reported security issue and improve code quality without changing the
feature set.
Security:
- Replace string-concatenated SQL with parameterized queries in every module.
- Escape all values interpolated into the HTML report preview.
- Use bcrypt for password hashing instead of MD5; use HMAC-SHA256 for carrier
request signing instead of SHA-1.
- Generate session tokens with crypto.randomBytes, not Math.random.
- Read SHIPDESK_ADMIN_PASSWORD, SHIPDESK_CARRIER_API_USER, and
SHIPDESK_CARRIER_API_SECRET from environment variables. No literals in source.
- Call carrier APIs over HTTPS with a request timeout.
- Set session cookies HttpOnly, Secure, SameSite=Lax, and scope them to /api.
- Add CSRF protection for state-changing routes.
- Validate attachment names and confirm resolved paths stay inside the upload
directory.
- Do not execute user input through a shell; use execFile with an argument array
and validate the warehouse code and mode.
- Remove eval and new Function; parse layout exports with JSON.parse.
- Stop returning stack traces and process environment from API responses.
Code quality:
- Replace var with const/let and add 'use strict' to every module.
- Throw Error objects instead of string literals.
- Use camelCase for functions; remove snake_case and PascalCase helpers.
- Remove duplicated helper functions and hardcoded absolute paths.
- Use strict equality and replace magic numbers with named constants.Step 9
Rescan with identical settings
Measure what changed under the same analysis configuration.
Upload the remediated archive to the same project with the same languages, cqLanguages, and triage flags as the baseline scan. Pass uuid instead of name so the scan joins the existing project.
Security findings dropped from 31 to 5 and the score rose from 16 to 65. Lines of code grew from 630 to 822, because bcrypt, HMAC signing, CSRF verification, path validation, and input allowlists all add code — so the score improved despite a larger denominator.
Compare rule families rather than the headline score alone. Weak hashing, insecure randomness, hardcoded credentials, plain-HTTP egress, and all three cookie rules went to zero.
TOKEN="$DERSCANNER_TOKEN"
PROJECT="543e6449-7c41-47ea-b293-cbbf8fe4b395"
curl -s -X POST "https://derscanner.example.com/app/api/v1/scan/start" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@shipdesk-javascript-after.zip" \
-F "uuid=$PROJECT" \
-F "languages=JAVASCRIPT" \
-F "cqLanguages=JAVASCRIPT" \
-F "checkboxNoBuild=true" \
-F "preprocessing=true" \
-F "aiTriageCritical=false" \
-F "aiTriageMedium=false" \
-F "aiTriageLow=false" \
-F "aiTriageInfo=false" \
-F "applyTriage=false"
# {"scanUuid":"ede2a8b0-..."}Step 10
Confirm which security families cleared
Separate what the prompt fixed from what still needs a person.
Open the detailed results for the rescan. JS_CRYPTO_BAD_HASH, JS_CRYPTO_BAD_RANDOM, JS_CRYPTO_KEY_HARDCODED, JS_PASSWORD_HARDCODED, JS_HTTP_USAGE, JS_BACKDOOR_NETWORK_ACTIVITY, and all three cookie rules are gone. SQL injection fell from fourteen hits to two.
The five remaining findings sit in two places. Three JS_XSS_REFLECTED hits are on the HTML report preview, which now escapes every interpolated value through escape-html and sends a restrictive Content-Security-Policy header. Two JS_INJECTION_SQL hits are on the shipment search, where the sort and filter column names are interpolated after being checked against an allowlist while the values themselves are bound as parameters.
Both need a reviewer to look at the code and sign off, not another automated pass. That is the honest end state of a two-prompt remediation: most families cleared outright, and a short list left that a person closes.
Step 11
Check the Code Quality rescan
Show the quality half of the same rescan.
The CQ score moved from 1 to 92 and critical Code Quality findings went from 431 to zero. Every critical rule cleared: 211 single-quote hits, 120 quote-formatting hits, 89 var usages, 8 thrown string literals, 2 eval calls, and the unguarded for…in loop.
The 315 remaining findings are all medium or low — indentation, block style, spacing, line length, variable grouping, and one constructor-naming rule. They are worth a formatter pass in CI rather than a prompt.
Read this alongside the security rescan rather than on its own. The two eval calls counted once as a critical quality finding and again as the dynamic-execution risk a reviewer cares about, and one remediation removed both.
Step 12
Build the baseline hybrid Canvas
Merge security and quality metrics in one view the product does not ship natively.
Pull critical, medium, low, score, and loc together with criticalCq, mediumCq, lowCq, scoreCq, and locCq from the scan DTO, group findings by ruleId, and lay both slices out in one Cursor Canvas panel.
The baseline hybrid view puts the security story and the quality story side by side — 31 findings at score 16 next to 700 quality findings at score 1 — which is the framing a stakeholder needs before seeing the rescan.
Step 13
Build the after-remediation hybrid Canvas
Show what cleared and what is left, in one panel.
Reuse the layout with the rescan UUID and split each slice into what remains and what cleared outright. The cleared column is the part worth showing to whoever approved the remediation work.
On this capture the after panel shows 5 security findings at score 65 and zero critical quality findings at score 92, with ten rule families listed as cleared.
Step 14
Compare rule families in one Canvas
Give stakeholders a delta view the native interface does not merge into a single panel.
Add a third Canvas that plots baseline and after counts side by side by rule family — SQL injection, weak crypto and randomness, plain HTTP and egress, cookie flags, hardcoded secrets, and reflected XSS.
Include a short score-context note. Both scans cover the same project with the same rule set, so the scores are comparable, but lines of code grew from 630 to 822 and readers should know why before they read a fourfold score improvement.
Step 15
Cross-check in DerScanner Scans Comparison
Pair the Canvas narrative with the native product view readers can open themselves.
Open Scans Comparison and select the baseline and after scans. The chart splits findings into remaining, fixed, and new by severity, and the SAST/CQ toggle above the scan pickers switches between the two slices.
The SAST view shows the twenty-four medium findings as fixed with two remaining. The CQ view shows all 431 critical findings fixed, with the low-severity count rising as the formatting rules redistributed across a larger file set.
Use this view alongside the Canvas panels — product interface for drill-down, Canvas for the combined story you export.
Step 16
Read the Code Quality comparison
Confirm the quality delta in the product interface, not only in the export.
Switch the toggle to CQ on the same comparison. The critical column shows 431 findings fixed and none remaining, which is the clearest single view of the quality result.
The rising low-severity column is expected. Formatting rules scale with file count and line count, and the remediated archive is larger.
Checking your result
Did the security review of Claude-generated code find real problems?
Yes. Eleven rule families fired on the baseline, including MD5 password hashing, a session token from Math.random, three hardcoded credentials, plain-HTTP carrier calls, and fourteen string-concatenated SQL queries.
How much did one remediation prompt fix?
Security findings fell from 31 to 5 and the score rose from 16 to 65. Weak hashing, insecure randomness, hardcoded secrets, plain HTTP, and all three cookie rules cleared completely.
Did Code Quality improve on the rescan?
Yes. Critical Code Quality findings went from 431 to zero and the CQ score rose from 1 to 92. The remaining 315 findings are medium and low formatting rules.
Can I run security and code quality in one scan for JavaScript?
Yes. Pass languages=JAVASCRIPT and cqLanguages=JAVASCRIPT on the same scan/start call. JavaScript, TypeScript, and Delphi/Pascal are the languages with Code Quality support.
Does DerScanner include a built-in hybrid security and quality report?
No. The two slices are separate in the product, with separate Overview, Detailed Results, and Scans Comparison views. Combine them in Cursor Canvas or your own reporting from the scan API fields.
Limits of this procedure
- This walkthrough uses a synthetic application with deliberate defects. Metrics describe that sample only and are not a prediction of results on production code.
- The JavaScript Code Quality profile mixes style rules with hygiene rules, and the style rules are numerous enough to dominate the critical count. Read the rule breakdown before treating a CQ score as a maintainability verdict.
- Aggregate scores move with lines of code. The remediated archive is 822 lines against a 630-line baseline because hardening adds code, so compare rule families alongside the score.
- Five security findings remain after remediation and need a human decision rather than another prompt. A guide that reported zero would be describing rule tuning, not a review.
- Scans Comparison matches findings by file path. Keep the archive root identical between scans or the comparison will report everything as fixed and re-added.
Related knowledge
Canonical terms used: DerScanner; JavaScript; Claude Opus; SAST; Code Quality; rescan; AI-generated code.
DerScanner