Mostly safe โ a couple of notes worth reading.
Scanned 5/3/2026, 6:57:28 PMยทCached resultยทFast Scanยท45 rulesยทHow we decide โ
AIVSS Score
Low
Severity Breakdown
0
critical
0
high
6
medium
19
low
MCP Server Information
Findings
This package earns a B grade with a safety score of 84/100 but has 6 medium-severity issues primarily related to readiness gaps and server configuration weaknesses. The main concerns center on deployment readiness and container image security rather than critical vulnerabilities, making it moderately safe for use with attention to the flagged configuration areas. The 19 low-severity readiness findings suggest you should review setup documentation and deployment practices before integrating it into production.
No known CVEs found for this package or its dependencies.
Scan Details
Want deeper analysis?
Fast scan found 25 findings using rule-based analysis. Upgrade for LLM consensus across 5 judges, AI-generated remediation, and cross-file taint analysis.
Building your own MCP server?
Same rules, same LLM judges, same grade. Private scans stay isolated to your account and never appear in the public registry. Required for code your team hasnโt shipped yet.
25 of 25 findings
25 findings
Dockerfile never sets a non-root `USER` directive, so the CMD runs as root by default. Any RCE or library-level vulnerability exploited inside this container gets full privileges (MCP Top-10 R3). Add `USER <non-root>` before CMD / ENTRYPOINT in the final stage โ e.g. `USER 1000`, `USER nobody`, or `USER nonroot` on distroless.
Evidence
| 1 | FROM node:20-slim |
| 2 | |
| 3 | # Playwright chromium deps |
| 4 | RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 5 | ca-certificates fonts-liberation libasound2 libatk-bridge2.0-0 libatk1.0-0 \ |
| 6 | libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 \ |
| 7 | libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 \ |
| 8 | libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \ |
| 9 | libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 lib |
Remediation
Create and switch to a non-root user before the CMD / ENTRYPOINT: RUN adduser --system --uid 1000 app USER 1000 Or reuse the base image's shipped non-root account (e.g. `USER nobody`, `USER nonroot` on distroless). Multi-stage builds only need the USER directive in the final stage.
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 35 | uses: github/codeql-action/autobuild@v3 |
| 36 | |
| 37 | - name: Perform CodeQL Analysis |
| 38 | uses: github/codeql-action/analyze@v3 |
| 39 | with: |
| 40 | category: /language:javascript-typescript |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 12 | if: | |
| 13 | (github.event_name == 'pull_request' && github.event.pull_request.draft == false) |
| 14 | || (github.event_name == 'issue_comment' && github.event.issue.pull_request != null && startsWith(github.event.comment.body, '/bot')) |
| 15 | uses: bot-manavarya/reviewer/.github/workflows/review.yml@main |
| 16 | with: |
| 17 | provider: 'gemini' |
| 18 | model: 'gemini-2.5-flash' |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 32 | queries: security-and-quality |
| 33 | |
| 34 | - name: Autobuild |
| 35 | uses: github/codeql-action/autobuild@v3 |
| 36 | |
| 37 | - name: Perform CodeQL Analysis |
| 38 | uses: github/codeql-action/analyze@v3 |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 23 | contents: read |
| 24 | steps: |
| 25 | - name: Checkout |
| 26 | uses: actions/checkout@v4 |
| 27 | |
| 28 | - name: Initialize CodeQL |
| 29 | uses: github/codeql-action/init@v3 |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 26 | uses: actions/checkout@v4 |
| 27 | |
| 28 | - name: Initialize CodeQL |
| 29 | uses: github/codeql-action/init@v3 |
| 30 | with: |
| 31 | languages: javascript-typescript |
| 32 | queries: security-and-quality |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 123 | // GitHub Actions niceties: if running in GHA, write the report to the step summary. |
| 124 | if (process.env.GITHUB_STEP_SUMMARY) { |
| 125 | try { writeFileSync(process.env.GITHUB_STEP_SUMMARY, md, { flag: 'a' }); } catch {} |
| 126 | } |
| 127 | |
| 128 | const threshold = opts.failOn || 'notable-drift'; |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 74 | // history.replaceState avoids a Next router navigation (we want to keep |
| 75 | // the live extraction state, just change the URL). |
| 76 | if (typeof window !== 'undefined' && event.hash) { |
| 77 | try { window.history.replaceState({}, '', `/x/${event.hash}`); } catch {} |
| 78 | } |
| 79 | break; |
| 80 | } |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 88 | if ((e.duration || 0) > window.__dlVitals.inp) window.__dlVitals.inp = e.duration; |
| 89 | } |
| 90 | }).observe({ type: 'event', buffered: true, durationThreshold: 16 }); |
| 91 | } catch {} |
| 92 | }); |
| 93 | |
| 94 | const start = Date.now(); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 95 | function parseJsonLoose(text) { |
| 96 | try { return JSON.parse(text); } catch { /* try to find a JSON object */ } |
| 97 | const m = text.match(/\{[\s\S]*\}/); |
| 98 | if (m) { try { return JSON.parse(m[0]); } catch {} } |
| 99 | return null; |
| 100 | } |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 1368 | if (opts.open !== false) { |
| 1369 | const { spawn } = await import('child_process'); |
| 1370 | const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open'; |
| 1371 | try { spawn(cmd, [`http://localhost:${port}`], { stdio: 'ignore', detached: true }).unref(); } catch {} |
| 1372 | } |
| 1373 | } catch (err) { |
| 1374 | console.error(chalk.red(`\n ${err.message}\n`)); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 46 | try { |
| 47 | await page.goto(url, { waitUntil: 'networkidle', timeout: 25000 }); |
| 48 | } catch { |
| 49 | try { await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 15000 }); } catch {} |
| 50 | } |
| 51 | |
| 52 | // Scripted motion pass: slow scroll โ hover first CTA โ scroll back. |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 367 | var cur = document.documentElement.getAttribute('data-theme') === 'dark' ? '' : 'dark'; |
| 368 | if (cur) document.documentElement.setAttribute('data-theme', cur); |
| 369 | else document.documentElement.removeAttribute('data-theme'); |
| 370 | try { localStorage.setItem('dl-theme', cur); } catch (e) {} |
| 371 | }); |
| 372 | })(); |
| 373 | </script> |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 72 | new PerformanceObserver((list) => { |
| 73 | for (const e of list.getEntries()) window.__dlVitals.lcp = e.startTime; |
| 74 | }).observe({ type: 'largest-contentful-paint', buffered: true }); |
| 75 | } catch {} |
| 76 | try { |
| 77 | let cls = 0; |
| 78 | new PerformanceObserver((list) => { |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 686 | for (const inr of rule.cssRules) { |
| 687 | if (inr.selectorText) inner.push(inr.selectorText); |
| 688 | } |
| 689 | } catch {} |
| 690 | results.containerQueries.push({ |
| 691 | condition: rule.conditionText || rule.containerQuery || '', |
| 692 | selectorText: inner.join(', '), |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 361 | (function () { |
| 362 | var btn = document.getElementById('themeBtn'); |
| 363 | var saved = null; |
| 364 | try { saved = localStorage.getItem('dl-theme'); } catch (e) {} |
| 365 | if (saved) document.documentElement.setAttribute('data-theme', saved); |
| 366 | btn && btn.addEventListener('click', function () { |
| 367 | var cur = document.documentElement.getAttribute('data-theme') === 'dark' ? '' : 'dark'; |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 95 | try { |
| 96 | for (const f of readdirSync(videoDir)) unlinkSync(join(videoDir, f)); |
| 97 | rmdirSync(videoDir); |
| 98 | } catch {} |
| 99 | |
| 100 | const result = { |
| 101 | url, |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 64 | try { |
| 65 | const btn = await page.$('button, [role="button"], a.btn, .button, [class*="btn"]'); |
| 66 | if (btn) await btn.hover({ timeout: 1000 }).catch(() => {}); |
| 67 | } catch {} |
| 68 | } |
| 69 | await page.waitForTimeout(frameMs); |
| 70 | } |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 175 | } |
| 176 | } |
| 177 | if (buffer.trim()) { |
| 178 | try { handleEvent(JSON.parse(buffer.trim())); } catch {} |
| 179 | } |
| 180 | } catch (err) { |
| 181 | setErrorMsg('Stream interrupted. Try another URL.'); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 137 | if (!res.ok) { |
| 138 | let body = null; |
| 139 | try { body = await res.json(); } catch {} |
| 140 | if (res.status === 429) { |
| 141 | setRateLimitMsg(body?.error || 'Rate limit reached. Try again in 24h.'); |
| 142 | } else if (res.status === 400) { |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 309 | var cur = document.documentElement.getAttribute('data-theme') === 'dark' ? '' : 'dark'; |
| 310 | if (cur) document.documentElement.setAttribute('data-theme', cur); |
| 311 | else document.documentElement.removeAttribute('data-theme'); |
| 312 | try { localStorage.setItem('dl-theme', cur); } catch (e) {} |
| 313 | }); |
| 314 | })(); |
| 315 | </script> |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 869 | } |
| 870 | } catch { /* cross-origin โ already tracked */ } |
| 871 | } |
| 872 | } catch {} |
| 873 | for (const link of document.querySelectorAll('link[href*="fonts.googleapis.com"]')) { |
| 874 | results.fontData.googleFontsLinks.push(link.href); |
| 875 | } |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 205 | await navigator.clipboard.writeText(content); |
| 206 | setCopied(true); |
| 207 | setTimeout(() => setCopied(false), 1500); |
| 208 | } catch {} |
| 209 | }, [content]); |
| 210 | |
| 211 | const downloadFile = useCallback(() => { |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 303 | (function () { |
| 304 | var btn = document.getElementById('themeBtn'); |
| 305 | var saved = null; |
| 306 | try { saved = localStorage.getItem('dl-theme'); } catch (e) {} |
| 307 | if (saved) document.documentElement.setAttribute('data-theme', saved); |
| 308 | btn && btn.addEventListener('click', function () { |
| 309 | var cur = document.documentElement.getAttribute('data-theme') === 'dark' ? '' : 'dark'; |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 81 | } |
| 82 | window.__dlVitals.cls = cls; |
| 83 | }).observe({ type: 'layout-shift', buffered: true }); |
| 84 | } catch {} |
| 85 | try { |
| 86 | new PerformanceObserver((list) => { |
| 87 | for (const e of list.getEntries()) { |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.