Security audit

Every plugin gets an automated static scan of its code, dependencies, and permission requests; plugins the static rules rate at risk also enter a model-driven dynamic security audit. Together the two layers are a scalable first line of defense, not a manual review. Audit results are built into every artifact's record rather than bolted on, and when the dynamic audit has a conclusion, the site risk tier that badges, lists, and registry-wide counts show follows it — it can be raised or lowered — with the static scan tier (vet primary, dsh backstop) applying only when there is none.

Latest
Scan report

28,952 plugins scanned · 22 critical-risk

View full scan results →
2026-11-12
Daily report

193 added · 0 critical · 4 high

View details →
Weekly reports

Latest: 2026-W46 (2026-11-12) · risk trends over time

Browse all reports →
Risk levels & standards

Four risk levels · what we scan · how we rate

View the standards ↓
01 / SCOPE

What we scan

Dependency vulnerabilities

Known CVEs in direct and transitive dependencies, from public vulnerability databases.

Suspicious permissions

Requests that reach outside the plugin's declared scope — fs.write, network.external, env access.

Hardcoded secrets

API keys, tokens, or credentials committed into the repository.

Supply chain risks

Unpinned dependencies, suspicious install scripts, or post-install hooks.

02 / RISK LEVELS

Risk levels

LowNo known vulnerabilities or suspicious findings.
MediumModerate or warning-level findings — review the report before installing.
HighHigh-severity findings (code execution, shell calls, install scripts) with no blocking-level finding — read the individual evidence before installing.
CriticalBlocking-level severe findings or leaked secrets — do not install.
03 / DYNAMIC SECURITY AUDIT

Dynamic security audit

Static rules are good at recognising shapes, but not context — whether a piece of code is actually loaded at runtime, or whether a list is defensive or offensive. The dynamic security audit fills that gap: it takes a bounded collection of plugin source, drops secret-bearing files and redacts inline secrets, then hands the source snapshot to a model for a context-level audit. Like the static scan, it never executes plugin code — it only reads the redacted source.

Merging: the dynamic conclusion is authoritative

The site's risk tier follows the dynamic conclusion: when the audit reaches a conclusion, that conclusion is authoritative — it may raise the tier or lower it; the static scan tier (vet primary, dsh backstop) applies only when there is no dynamic conclusion. The conclusion really moves the tier — it is not just a field inside the audit record: the tier comes from that audit's finding counts — any critical finding sets the plugin to critical on this site (red badge, with list filters and registry-wide counts following), otherwise any high finding sets high, otherwise any medium (warning-level) finding sets medium, otherwise low — and where the model rules more leniently than the static scan (for example confirming a static false positive) the tier drops to the dynamic level. Exemptions still have exactly one path — manual, three-pass review written into security-scan-suppressions.json; the dynamic audit script never writes a suppression. A scope limit applies to that: entries outside the scanning scope (scopeExcluded — for example not yet through L4 install testing, or with the topic removed) follow the existing policy — a raise still sets their recorded tier, but they do not participate in the registry-wide risk statistics and are not given a published risk-badge value (the badge reads unknown). The plugin detail page and the per-plugin JSON are the authoritative tier for every entry.

The model can also be wrong, so there is a manual correction path: after review, record the plugin as withdrawn in src/data/dynamic-escalation-review.json — that conclusion is withdrawn and the tier falls back to the static scan tier (vet primary, dsh backstop); the static verdict itself is unchanged: what is withdrawn is the dynamic conclusion, not an exemption of static findings). Currently 2,340 dynamic tier changes are in effect and 1 have been withdrawn by human review; that table is maintained by hand and the dynamic audit script never writes it. A withdrawal takes effect immediately — no pipeline recomputation is needed: the tier drops back as soon as the review entry is committed, and the detail page and the per-plugin JSON show the reverted tier on the next build, while the badge index catches up on its next refresh.

2,922
plugins entered the audit queue
2,341
audited with a conclusion
581
collection or model failure, no conclusion
2,340
dynamic tier changes in effect (the tier follows the dynamic conclusion)

Coverage, stated plainly: the queue by default only admits plugins whose static tier is medium or above (medium/high/critical; since 2026-10-24 entries rated low are not queued), so the dynamic audit is a subset of the static scan, not the whole registry — plugins with no static risk never enter the queue, and “no conclusion” is not a pass. Of the conclusive audits so far, 321 ended up stricter than the static verdict and 794 ended up softer than it — both directions really set the tier shown on this site: when the dynamic conclusion is more lenient, the tier drops accordingly, which is the authoritative-dynamic rule in practice rather than a violation. A conclusion a human review later withdraws stops affecting the tier, which is why “changed the tier” and “in effect” are counted separately.

Where to see the results: the security review card on every plugin page shows the static verdict, the dynamic verdict, and the combined verdict; field-level documentation lives at /data/security/. The individual audit reports are internal pipeline artifacts with no public route on this site.

The same disclaimer applies: the dynamic audit is still automated model output. It is not a security guarantee and not a manual review — combine it with the verification level and plugin health before you install.

04 / STATUS

✓ Static scan + dynamic security audit live

28,952 artifacts have a static heuristic scan (code execution, hardcoded secrets, exfiltration endpoints, destructive commands); 404 remain pending. Automated static analysis — a scalable first line of defense, not a manual review.

On top of that, the dynamic security audit adds model context review for plugins the static rules rate at risk — confirming runtime behaviour and intent the static pass cannot see, whose conclusions really set the site tier — a dynamic verdict is authoritative when there is one (it may raise or lower the tier, and the tier follows the audit's finding counts: critical → Critical, high → High, medium → Medium, otherwise Low), and the static scan tier (vet primary, dsh backstop) applies only without one; exemptions stay manual. Both layers are automated signals: treat them as your first-pass filter and combine them with the verification level and plugin health before installing — one more signal, one less surprise.

05 / FAQ

What does the dsh.so security scan check?

The scan checks repository code and manifest metadata for hardcoded secrets, suspicious permissions, destructive commands, exfiltration endpoints, unpinned dependencies, install hooks, and other supply-chain signals. Results are stored per plugin and summarized in the daily and weekly security reports.

How does the scan relate to a manual audit?

The scan is static analysis: it inspects code patterns, dependency manifests, and permission requests, and never executes plugin code on anyone's machine — which is what makes it safe to run across every collected plugin as a scalable first line of defense, quickly surfacing known risks like hardcoded secrets, dangerous permissions, and supply-chain red flags. Automation has limits: complex context can be missed and false positives happen. Treat a low-risk rating as a strong triage signal and combine it with the verification level (L4/L5 real tests) and plugin health when deciding — more signals, more confidence.

How is the dynamic security audit different from the static scan?

The static scan applies deterministic rules to code, manifests, and permission requests. The dynamic security audit is model-driven and only runs on plugins whose static verdict is warn or worse, so it is a subset of the registry rather than a second full pass. It reads a redacted source snapshot and reasons about context — what actually runs, and whether a list is defensive or offensive. Neither layer executes plugin code. When the dynamic audit reaches a conclusion, that conclusion is authoritative: it sets the published tier and may be stricter or softer than the static verdict. The tier follows the audit's finding counts: any critical finding means critical here (red badge, list filters and counts follow), otherwise any high finding means high, otherwise any medium finding means medium, otherwise low. A model that judges a finding less severe than the static rules did lowers the published level instead of being ignored. The static scan tier (vet primary, dsh backstop) applies only where there is no dynamic conclusion. Exemptions are still written by hand after a three-pass review, never by the audit itself, and a human review that considers a conclusion wrong — whether it raised or lowered the tier — can record withdrawn in the review table, which falls back to the static scan tier (vet primary, dsh backstop) and leaves the static verdict untouched.

Source: dsh.so security reports and public repository metadata · Maintained by dsh.so · Last updated

Was this page helpful?