SkillTotal

Is huggingface-hub 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

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

huggingface_hub-2.0.0 2.0.0

python_package · pypi:huggingface-hub
LOW
0
/ 100 risk score
Snapshot · scanned Sep 24, 2026 · huggingface_hub-2.0.0@2.0.0 · engine 0.53.0 / ruleset 60

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

Capabilities — what this component can do (not a risk score):
delegated authenticationfilesystem readfilesystem writeshell execution

Behavioral traits

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

Execution authority
Tool Access Control / Direct Tool Access
Filesystem reach
Tool Execution Context
Delegated authentication
Tool Execution Context / User Delegated Credentials

Findings (4)

HIGHPython shell/command executionST-SHELL-PY

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

result = subprocess.run(
            [self.binary_path, "-json"],
            input=full_query,
            capture_output=True,
            text=True,
            check=False,
        )
subprocess.run([uv_path, "venv", str(venv_dir)], check=True)
subprocess.run(install_cmd, check=True, timeout=_EXTENSIONS_PIP_INSTALL_TIMEOUT)
return subprocess.call([str(executable_path)] + args)
return subprocess.call(["sh", str(executable_path)] + args)
subprocess.run(
        "git config lfs.customtransfer.multipart.path hf".split(),
        check=True,
        cwd=local_path,
    )
subprocess.run(
        f"git config lfs.customtransfer.multipart.args {LFS_MULTIPART_UPLOAD_COMMAND}".split(),
        check=True,
        cwd=local_path,
    )
res = subprocess.run(command, start_new_session=True)
subprocess.call([*_hf_argv(), "skills", "update", DEFAULT_SKILL_ID, "-g"])
return subprocess.run(
        command,
        capture_output=True,
        check=check,
        encoding="utf-8",
        errors="replace",  # if not utf-8, replace char by �
        cwd=folder or os.getcwd(),
        **kwargs,
    )
with subprocess.Popen(
        command,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        encoding="utf-8",
        errors="replace",  # if not utf-8, replace char by �
        cwd=fold …

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.

with open(rel_path, "r") as fp:
long_description=open("README.md", "r", encoding="utf-8").read(),
with open(self.path_or_fileobj, "rb") as file:
with open(local_path, "rb") as f:
with open(path, encoding="utf-8") as f:
existing = path.read_text() if path.exists() else ""
with open(tmp_path, "rb") as f:
parsed = json.loads(local_path.read_text(encoding="utf-8"))
content = (skill_dir / "SKILL.md").read_text(encoding="utf-8")
script=str(local_path), header=parse_uv_script_header(local_path.read_text(encoding="utf-8"))
yield UvScript(script=script, header=parse_uv_script_header(path.read_text(encoding="utf-8")))
return body_file.read_text(encoding="utf-8")
data = json.loads(manifest_path.read_text())
with open(filepath, "rb") as file:
if not ref_path.exists() or commit_hash != ref_path.read_text():
with open(paths.file_path, "rb") as f:
resolved=ref_path.read_text().strip(), initial=revision, repo_id=repo_id, repo_type=repo_type

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.

with open(plan_file, "w") as f:
tag_path.write_text(CACHEDIR_TAG_CONTENT)
path.write_text(_completion_script("fish"))
(install_dir / "SKILL.md").write_text(content, encoding="utf-8")
local_path.write_bytes(response.content)
manifest_path.write_text(json.dumps(data, indent=2, sort_keys=True))
shutil.rmtree(extension_dir, ignore_errors=True)
executable_path.write_bytes(binary)
shutil.copytree(central_skill_path, link_path)
shutil.copytree(temp_dir.name, persistent_temp_dir, dirs_exist_ok=True)
shutil.move(abs_src, abs_dst, copy_function=_copy_no_matter_what)
shutil.copyfile(abs_src, abs_dst)
tmp_path.write_text(commit_hash)
shutil.copyfile(cached_path, paths.file_path)
shutil.move(str(src), str(dst), copy_function=_copy_no_matter_what)

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.

LOWDelegated authentication (OAuth 2.0 / OIDC)ST-AUTH-DELEGATED

An OAuth 2.0 / OpenID Connect delegated-authentication flow was detected (authorization-code / refresh-token / token-exchange grant, an OIDC authorize/discovery endpoint or id_token, or a delegation library). Tools authenticate with the end user's delegated, scoped credentials rather than a long-lived embedded service credential. (11 occurrence(s) shown as evidence).

"authlib>=1.8.0",  # first version supporting httpx2
from authlib.integrations.base_client.errors import MismatchingStateError
from authlib.integrations.starlette_client import OAuth
server_metadata_url=constants.OPENID_PROVIDER_URL + "/.well-known/openid-configuration",
_TOKEN_EXCHANGE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:token-exchange"
_ID_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:id_token"
_REFRESH_TOKEN_GRANT_TYPE = "refresh_token"

Fix: Delegated auth is a lower-blast-radius execution context than an embedded static credential. Confirm the requested scopes are minimal and that tokens are never logged or forwarded off-host.

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 →