mermaid — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited mermaid (Agent Skill) and scored it 45/100 (orange). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 3 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 3 flagged
A base64 string of 128+ characters appears in a documentation file. Encoded prompt injection hides the hostile instruction in base64 — invisible to keyword filters — and relies on the agent's ability to decode it at runtime. There is no normal authoring reason to embed a multi-hundred-byte base64 blob in skill docs.
*.sig, SIGNATURES) outside the documentation.Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are rendering Mermaid diagrams from Markdown sources using either the mermaid shell function (Docker-backed, non-sandbox) or mmdc directly (sandbox).
The references/ directory contains supporting material for diagram authoring:
flowchart and graph diagrams.Consult this file when generating or improving diagrams that use colour styling.
mermaid shell function wraps minlag/mermaid-cli via Docker. `mermaid fenced block in the input .md file.example.svg-1.svg)..md file with  references replacing the code blocks.The skill accepts three types of input:
| Type | Example |
|---|---|
| Single file | data/example.md |
| Local directory | ./docs/ or /some/path/ |
| URL (single file) | https://example.com/diagram.md |
| URL (GitHub directory) | https://github.com/user/repo/tree/main/docs |
When invoked with arguments like /mermaid data/example.md -f png, do the following:
echo "${IS_SANDBOX:-no}"IS_SANDBOX=yes -> use the mmdc sandbox render path throughout (see Sandbox render section).source scripts/mermaid.sh && mermaid ... throughout.If `IS_SANDBOX=yes`, immediately resolve the Chromium path before any render attempt:
CHROMIUM_DEFAULT="/opt/pw-browsers/chromium-1194/chrome-linux/chrome"
if [ -x "$CHROMIUM_DEFAULT" ]; then
CHROMIUM_PATH="$CHROMIUM_DEFAULT"
else
CHROMIUM_PATH=$(find /opt/pw-browsers -name "chrome" | grep -v headless | head -1)
fi
if [ -z "$CHROMIUM_PATH" ]; then
echo "ERROR: Chromium not found under /opt/pw-browsers" >&2
exit 1
fiUse $CHROMIUM_PATH (never the hardcoded default) in the puppeteer config written in the Render command section.
Inspect the first non-flag argument:
/, or test -d is true) -> Directory input. Go to Directory handling..svg.md, .png.md, .pdf.md), stop and inform the user -- this is a rendered output file, not a source. Ask them to pass the original .md source instead./mnt/), copy it to /home/claude/ first..md files up to two levels deep (the directory itself and one level of subdirectories): find /path/to/dir -maxdepth 2 -name "*.md" 2>/dev/null find /path/to/dir -maxdepth 2 -name "*.md" | xargs grep -l '```mermaid' 2>/dev/null.svg.md, .png.md, .pdf.md) -- these are already-rendered outputs, not sources.There are two sub-cases:
A URL ending in .md (or clearly pointing to a single Markdown file):
web_fetch tool to retrieve the content (do not use curl -- external domains may be blocked by the egress proxy)./home/claude/<filename>.md where <filename> is derived from the URL path.A URL of the form https://github.com/user/repo/tree/<branch>/path/to/dir:
https://github.com/user/repo/tree/main/docshttps://api.github.com/repos/user/repo/contents/docs?ref=mainweb_fetch to retrieve the directory listing JSON."type" and "name" fields. If the response is HTML, a rate-limit message, or unparseable JSON, stop and report the raw response to the user rather than silently failing."type": "file" and "name" ends in .md..svg.md, .png.md, .pdf.md)..md file, use web_fetch on its download_url field to fetch the content./home/claude/<filename>.md and render it.Note: raw.githubusercontent.com and api.github.com may be blocked by the sandbox egress proxy. If web_fetch fails with a network/403 error, inform the user that GitHub URLs are not reachable from the sandbox and ask them to download the file(s) locally and upload instead.
Write the puppeteer config once per session using $CHROMIUM_PATH resolved in Step 1, then reuse:
cat > /tmp/puppeteer-config.json << EOF
{
"executablePath": "$CHROMIUM_PATH",
"args": ["--no-sandbox", "--disable-setuid-sandbox"]
}
EOF
mmdc -i "$INPUT_FILE" -o "$OUTPUT_FILE" --puppeteerConfigFile /tmp/puppeteer-config.jsonsource scripts/mermaid.sh && mermaid "$INPUT_FILE" [options]| mermaid wrapper | mmdc equivalent |
|---|---|
-f / --format | --outputFormat |
-t / --theme | --theme |
-b / --bg | --backgroundColor |
-w / --width | --width |
-H / --height | --height |
-s / --scale | --scale |
| Flag | Long form | Description |
|---|---|---|
-f | --format | Output format: svg (default), png, pdf |
-t | --theme | Theme: default, dark, forest, neutral |
-b | --bg | Background colour: white, transparent, '#rrggbb' |
-w | --width | Canvas width in pixels |
-H | --height | Canvas height in pixels |
-s | --scale | Pixel density / scale factor (use 2-3 for retina PNG) |
-d | --dir | Override the host directory mounted into Docker |
-h | --help | Print built-in help |
svg1transparent for dark-mode embedding)For input data/example.md rendered as SVG, mmdc writes:
data/example-1.svg, data/example-2.svg, ... (one per diagram block)The mermaid wrapper writes:
data/example.svg-1.svg, data/example.svg-2.svg, ...data/example.svg.md (companion Markdown with image references)Always share these tips with the user after a successful render:
`mermaid fenced blocks render automatically when viewed in a repository.| Symptom | Likely cause | Fix |
|---|---|---|
Chromium not found under /opt/pw-browsers | Chromium version path changed | Auto-detect ran and found nothing -- check /opt/pw-browsers manually; report to user |
Chrome won't launch / puppeteer crash | Missing sandbox flags | Ensure --no-sandbox and --disable-setuid-sandbox are in the puppeteer config args |
| File renders 0 diagrams | Companion file passed directly | Check filename for .svg.md / .png.md / .pdf.md -- pass the source .md instead |
| Directory scan finds no files | Only nested >1 level deep | Files beyond one subdirectory are skipped by design -- user must pass paths explicitly |
web_fetch returns HTML or unparseable JSON on GitHub URL | API rate limit or redirect | Show raw response to user; ask them to download and upload the file directly |
web_fetch fails with 403/network error on GitHub URL | Domain blocked by egress proxy | Inform user; ask them to upload the file directly |
mermaid shell function not found (non-sandbox) | mermaid.sh not sourced | Run: source scripts/mermaid.sh from the skill directory |
| Docker not running (non-sandbox) | Docker Desktop stopped | Tell user to start Docker Desktop |
| File not found | Wrong path or working directory | Report the exact path tried; suggest pwd to check working directory |
| PNG looks low-res | Scale factor not set | Use --scale 2 or --scale 3 for retina-quality PNG output |
| PDF output missing content | PDF requires specific mmdc flags | Ensure -f pdf is passed; PDF support depends on mmdc version |
Always show raw stderr from the render so the user can see which diagrams succeeded (✅) or failed (❌).
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.