Is Drawio Skill safe?
- Python shell/command execution
- Python network egress
- Python filesystem read
repo is an AI directory analyzed by SkillTotal's deterministic static scanner. The scan found no malicious indicators, though 4 risky constructs are reported for review. It can: filesystem read, filesystem write, network egress and shell execution — capabilities are what the code can do, not a verdict on intent. Risk score 0/100 (low).
repo
Automated static-analysis result. It can contain false positives and false negatives, and is not a claim about the intent of Drawio Skill's authors. Report a false positive.
Behavioral traits
How this component maps to the CSA agentic threat model. Descriptive — it never affects the risk score.
Findings (4)
The component can run operating-system commands or spawn processes.
proc = subprocess.run(
["dot", "-Tplain"], input=dot_src,
capture_output=True, text=True, check=True,
)r = subprocess.run(["drawio", "-x", "-f", "png", "--page-index", "1",
"--width", "2000", "-o", png_path, src], capture_output=True)r = subprocess.run(
[sys.executable, os.path.join(HERE, "autolayout.py"), gpath, "-o", opath],
capture_output=True, text=True,
)r = subprocess.run(["drawio", "-x", "-f", "png", "--page-index", str(index),
"-s", str(scale), "-o", out_png, drawio_file],
capture_output=True)r = subprocess.run(["drawio", "-x", "-f", "svg", "--page-index", str(index),
"-o", out_svg, drawio_file], capture_output=True)out = subprocess.run(["tred"], input=dot, capture_output=True,
text=True, check=True).stdoutout = subprocess.run(["tred"], input=dot, capture_output=True,
text=True, check=True).stdoutr = subprocess.run(
["git", "-C", repo, "diff", "--name-status", f"{base}..{head}", "--", "*.drawio"],
capture_output=True, text=True)r = subprocess.run(["git", "-C", repo, "show", f"{ref}:{path}"], capture_output=True)r = subprocess.run(["drawio", "-x", "-f", "png", "--page-index", "1", "-o", out_png, src_drawio],
capture_output=True)r1 = subprocess.run([sys.executable, os.path.join(HERE, "drawiodiff.py"),
base_drawio, head_drawio, "-o", diff_json], capture_output=True)r2 = subprocess.run([sys.executable, os.path.join(HERE, "autolayout.py"),
diff_json, "-o", diff_drawio], capture_output=True)out = subprocess.run(["tred"], input=dot, capture_output=True,
text=True, check=True).stdoutout = subprocess.run(["tred"], input=dot, capture_output=True,
text=True, check=True).stdoutr = subprocess.run([sys.executable, autolayout, graph_path],
capture_output=True, text=True)out = subprocess.run(["tred"], input=dot, capture_output=True,
text=True, check=True).stdoutr = subprocess.run(["drawio", "-x", "-f", "svg", "-o", out, path],
capture_output=True)out = subprocess.run(["tred"], input=dot, capture_output=True,
text=True, check=True).stdoutp = subprocess.run(["git", "-C", root, *args], capture_output=True)
imp = subprocess.run(
[sys.executable, os.path.join(HERE, importer + ".py"), work_path,
"-o", graph_json, *importer_args],
capture_output=True)lay = subprocess.run(
[sys.executable, os.path.join(HERE, "autolayout.py"), graph_json, "-o", drawio],
capture_output=True)exp = subprocess.run(["drawio", "-x", "-f", "png", "--width", "1600",
"-o", png, drawio], capture_output=True)Why it matters: Powerful and often legitimate — confirm the commands aren't built from untrusted input.
Fix: Confirm the command and its arguments are fully controlled and not derived from untrusted input; avoid shell=True.
The component reads files from disk.
manifest = json.load(open(MANIFEST, encoding="utf-8"))
with open(_PALETTE_FILE, encoding="utf-8") as fh:
with open(args.input, encoding="utf-8") as f:
with open(png_path, "rb") as f:
with open(args.input, encoding="utf-8") as f:
with open(path, encoding="utf-8") as f:
with open(path, encoding="utf-8") as f:
with open(opath, encoding="utf-8") as f:
text = sys.stdin.read() if args.input == "-" else open(args.input, encoding="utf-8").read()
with open(path, "rb") as f:
with open(out, encoding="utf-8") as f:
with open(args[0], "r", encoding="utf-8") as f:
m = MODULE.search(open(gomod, encoding="utf-8", errors="ignore").read())
src = open(path, encoding="utf-8", errors="ignore").read()
with open(path, encoding="utf-8") as f:
src = open(path, encoding="utf-8", errors="ignore").read()
with open(path, encoding="utf-8") as f:
with open(path, encoding="utf-8") as f:
with open(path, encoding="utf-8") as f:
tree = ast.parse(open(path, encoding="utf-8").read(), filename=path)
tree = ast.parse(open(path, encoding="utf-8").read(), filename=path)
with open(args.input, encoding="utf-8") as f:
with open(args.mapfile, encoding="utf-8") as f:
with open(path, "rb") as f:
with open(path, encoding="utf-8") as f:
Why it matters: Usually legitimate, but worth confirming it can't be steered into reading sensitive files.
Fix: Confirm which files are read and that paths cannot be influenced by untrusted input to reach sensitive locations.
The component writes or deletes files on disk.
with open(args.output, "w", encoding="utf-8") as f:
with open(f"{os.path.splitext(out)[0]}-frame{k + 1:03d}.png", "wb") as f:with open(out, "w", encoding="utf-8") as f:
with open(args.output, "w", encoding="utf-8") as f:
with open(args.output, "w", encoding="utf-8") as f:
with open(args.output, "w", encoding="utf-8") as f:
with open(gpath, "w", encoding="utf-8") as f:
with open(args.output, "w", encoding="utf-8") as f:
with open(args.output, "w", encoding="utf-8") as f:
with open(args.output, "w", encoding="utf-8") as f:
with open(args.output, "w", encoding="utf-8") as f:
with open(out, "w", encoding="utf-8") as f:
with open(args.output, "w", encoding="utf-8") as f:
open(args.output, "w", encoding="utf-8").write(text)
open(args.output, "w", encoding="utf-8").write(text)
with open(args.output, "w", encoding="utf-8") as f:
with open(args.output, "w", encoding="utf-8") as f:
with open(dest, "wb") as f:
with open(args.output, "w", encoding="utf-8") as f:
open(args.output, "w", encoding="utf-8").write(text)
open(args.output, "w", encoding="utf-8").write(text)
os.unlink(graph_path)
with open(args.output, "w", encoding="utf-8") as f:
with open(args.output, "w", encoding="utf-8") as f:
with open(path, "wb") as f:
Why it matters: Usually legitimate, but worth confirming the paths can't be controlled by untrusted input.
Fix: Confirm which files are written/deleted and that paths cannot be influenced by untrusted input.
The component makes outbound network requests.
import urllib.request
svg = urllib.request.urlopen(url, timeout=15).read()
svg = urllib.request.urlopen(url, timeout=15).read()
import urllib.parse
pre = urllib.parse.quote(xml, safe="!~*'()")
+ urllib.parse.quote(_deflate_b64(xml), safe="")
+ urllib.parse.quote(payload, safe="")
Why it matters: Usually legitimate, but confirm the destinations are expected and no sensitive data leaves.
Fix: Confirm the destination hosts are expected and that no sensitive data is sent off-host.
Check your own component
Run the same evidence-backed scan on any MCP server, agent skill, or package.
Scan your own componentHow we determine this: deterministic static analysis (regex + AST), evidence-anchored, no code execution. Methodology →