SkillTotal

Is Last30Days Skill safe?

No malicious indicators - review capabilities before installing
Notable — review in context (capabilities are not malware):
  • Python shell/command execution
  • Python filesystem read
  • Python filesystem write/delete

last30days-skill is an AI python_package analyzed by SkillTotal's deterministic static scanner. The scan found no malicious indicators, though 5 risky constructs are reported for review. It can: filesystem read, filesystem write, mcp tools detected, network egress and shell execution — capabilities are what the code can do, not a verdict on intent. Risk score 0/100 (low).

last30days-skill 3.21.0

python_package · https://github.com/mvanhorn/last30days-skill
LOW
0
/ 100 risk score
Snapshot · scanned Aug 15, 2026 · last30days-skill@3.21.0 · engine 0.38.1 / ruleset 42

Automated static-analysis result. It can contain false positives and false negatives, and is not a claim about the intent of Last30Days Skill's authors. Report a false positive.

Capabilities — what this component can do (not a risk score):
filesystem readfilesystem writemcp tools detectednetwork egressshell execution

Behavioral traits

How this component maps to the CSA agentic threat model. Descriptive — it never affects the risk score.

Tool surface
Tool Usage
Execution authority
Tool Access Control / Direct Tool Access
Filesystem reach
Tool Execution Context
Network egress
Interaction & Communication / Direct Communication

Findings (5)

HIGHPython shell/command executionST-SHELL-PY

The component can run operating-system commands or spawn processes.

subprocess.run(cmd, cwd=ROOT, check=True)
result = subprocess.run(
        cmd,
        cwd=repo_dir,
        env=env,
        capture_output=True,
        text=True,
        timeout=timeout_seconds,
        check=False,
    )
subprocess.run(
        ["git", "worktree", "add", "--detach", str(worktree_dir), rev],
        cwd=REPO_ROOT,
        check=True,
        capture_output=True,
        text=True,
    )
subprocess.run(
        ["git", "worktree", "remove", "--force", str(path)],
        cwd=REPO_ROOT,
        check=False,
        capture_output=True,
        text=True,
    )
result = subprocess.run(
            ["security", "find-generic-password", "-w", "-s", service_name],
            capture_output=True,
            text=True,
            timeout=10,
        )
result = subprocess.run(
            [
                "openssl", "enc", "-aes-128-cbc", "-d",
                "-K", hex_key,
                "-iv", CHROME_IV_HEX,
                "-nopad",
            ],
            input=ciphertext, …
completed = subprocess.run(
            [pdftotext, str(path), "-"],
            capture_output=True,
            check=True,
            text=True,
            timeout=20,
        )
result = subprocess.run(
                [security, "find-generic-password",
                 "-a", account,
                 "-s", service,
                 "-w"],
                capture_output=True, text=True, timeout=5,
            )
result = subprocess.run(
                [pass_bin, "show", f"{prefix}{key}"],
                capture_output=True, text=True, timeout=5,
                encoding="utf-8", errors="replace",
            )
result = subprocess.run(
            ["gh", "auth", "token"],
            capture_output=True, text=True, timeout=5,
        )
result = subprocess.run(
                [binary, "-p", prompt, "--permission-mode", "bypassPermissions"],
                capture_output=True,
                text=True,
                timeout=timeout,
                cwd=workdir, …
proc = subprocess.run(
            command,
            capture_output=True,
            text=True,
            timeout=timeout,
        )
proc = subprocess.run(
            command,
            capture_output=True,
            text=True,
            timeout=timeout,
        )
proc = subprocess.run(
                ["brew", "install", "yt-dlp"],
                capture_output=True, text=True, timeout=120,
            )
proc = subprocess.run(
            [npx, "-y", PRINTING_PRESS_NPM, "install", slug, "--cli-only"],
            capture_output=True, text=True, timeout=DIGG_INSTALL_TIMEOUT,
        )
subprocess.run(["pbcopy"], input=user_code.encode(), check=True, timeout=5)
proc = subprocess.Popen(
        list(cmd),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True,
        encoding="utf-8",
        errors="replace",
        preexec_fn=preexec,
        env=env,
    )
result = subprocess.run(
            ["xurl", "auth", "status"],
            capture_output=True,
            text=True,
            timeout=10,
        )
result = subprocess.run(
            ["xurl", "search", query, "-n", str(max_results), "--auth", "app"],
            capture_output=True,
            text=True,
            timeout=30,
        )
return subprocess.run(
        cmd,
        cwd=REPO_ROOT,
        env=env,
        text=True,
        capture_output=True,
        timeout=timeout,
        check=True,
    )
*subprocess.run(
                [
                    "rg",
                    "--files",
                    "skills/last30days/scripts",
                    "tests",
                    "-g",
                    "*.py", …
result = subprocess.run(
            [
                sys.executable,
                str(SCRIPT_DIR / "last30days.py"),
                search_term,
                "--emit=json",
                "--json-profile=raw",
                "--q …

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.

MEDIUMPython filesystem readST-FS-PY-READ

The component reads files from disk.

text = PYPROJECT.read_text(encoding="utf-8")
text = path.read_text(encoding="utf-8")
text = SKILL_MD.read_text(encoding="utf-8")
data = json.loads(path.read_text(encoding="utf-8"))
data = json.loads(path.read_text(encoding="utf-8"))
text = UV_LOCK.read_text(encoding="utf-8")
with open(path, encoding="utf-8") as f:
rows = json.loads(EVAL_TOPICS_FILE.read_text())
payload = json.loads(cache_file.read_text())
if not engine.exists() or "--json-profile" in engine.read_text(encoding="utf-8"):
payload = json.loads(metrics_path.read_text()) if metrics_path.exists() else {
lines = summary_path.read_text().splitlines() if summary_path.exists() else ["# Search Quality Evaluation", ""]
return Path(path).expanduser().read_text(encoding="utf-8")
with open(plan_str, encoding="utf-8") as f:
payload = json.loads(cache_path.read_text(encoding="utf-8"))
payload = json.loads(cache_path.read_text(encoding="utf-8"))
marker_found = generated_marker in existing_path.read_text(encoding="utf-8")
generated = html_render.LIBRARY_BRIEF_MARKER in path.read_text(
                encoding="utf-8"
            )
with open(plan_str, encoding="utf-8") as f:
return "microsoft" in Path("/proc/version").read_text().lower()
payload = json.loads(path.read_text(encoding="utf-8"))
raw = file_path.read_text(encoding="utf-8")
payload = json.loads(path.read_text(encoding="utf-8"))

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.

MEDIUMPython filesystem write/deleteST-FS-PY-WRITE

The component writes or deletes files on disk.

path.write_text(updated, encoding="utf-8")
SKILL_MD.write_text(text3, encoding="utf-8")
path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
UV_LOCK.write_text(updated, encoding="utf-8")
with open(path, "w", encoding="utf-8") as f:
cache_file.write_text(json.dumps(payload, indent=2))
(output_dir / "metrics.json").write_text(json.dumps(payload, indent=2))
(output_dir / "summary.md").write_text("\n".join(lines) + "\n")
metrics_path.write_text(json.dumps(payload, indent=2))
summary_path.write_text("\n".join(lines).rstrip() + "\n")
_publish_metadata_path(html_path).write_text(json.dumps(payload, indent=2), encoding="utf-8")
(target / "last-run.json").write_text(json.dumps(payload, indent=2))
report_cache_path.write_text(json.dumps(cache_payload, indent=2))
cache_path.write_text(json.dumps(payload, indent=2), encoding="utf-8")
pending_path.write_text(json.dumps(payload, indent=2), encoding="utf-8")
feed_path.write_text(feed_xml, encoding="utf-8")
index_path.write_text(index_html, encoding="utf-8")
feed_path.write_text(
            feed.render_atom(
                entries,
                library_id=library_id,
                entry_urls=entry_urls,
                author=feed_author,
            ),
            encoding="utf-8", …
index_path.write_text(
            html_render.render_library_index(entries, entry_urls=entry_urls),
            encoding="utf-8",
        )
path.write_text(json.dumps(payload, indent=2), encoding="utf-8")
path.write_text(raw, encoding="utf-8")
shutil.copyfile(store, os.path.join(child_store_dir, store.name))

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.

MEDIUMPython network egressST-NET-PY

The component makes outbound network requests.

from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen
request = Request(
        GEMINI_API_URL.format(model=model, api_key=api_key),
        data=json.dumps(body).encode("utf-8"),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
with urlopen(request, timeout=120) as response:
from urllib.parse import urlparse
expected = urlparse(domain or DEFAULT_DOMAIN)
url = f"{_resolve_search_url(config)}?{urlencode(params)}"
from urllib.parse import urlparse
scheme = urlparse(url).scheme.lower()
req = urllib.request.Request(
            url, headers=headers or {"User-Agent": "last30days-doctor"}
        )
with urllib.request.urlopen(req, timeout=timeout) as resp:
params = urllib.parse.urlencode({"q": topic, "limit": limit})
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
parsed = urlparse(url.strip().lower())
query = urlencode(clean_params, doseq=True)
return urlunparse((parsed.scheme, netloc, parsed.path.rstrip("/"), "", query, ""))

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.

LOWMCP tool surface detectedST-MCP-DETECTED

An MCP tool surface (manifest or tool definitions) was found.

Why it matters: Just context — review which tools it offers and their permissions.

Fix: Review the declared MCP tools and their permissions.

Check your own component

Run the same evidence-backed scan on any MCP server, agent skill, or package.

Scan your own component

How we determine this: deterministic static analysis (regex + AST), evidence-anchored, no code execution. Methodology →