File size: 7,223 Bytes
4b371b6 127023d 64e3179 127023d 4b371b6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | <!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>modelvet — vet a Hugging Face model before you trust it</title>
<style>
:root {
color-scheme: light dark;
--bg: #0f1115;
--panel: #171a21;
--border: #2a2f3a;
--text: #e7e9ee;
--muted: #9aa3b2;
--accent: #ffb020;
--ok: #4fd18b;
--bad: #ff6b6b;
}
@media (prefers-color-scheme: light) {
:root {
--bg: #f7f7f9;
--panel: #ffffff;
--border: #e2e5ea;
--text: #14161a;
--muted: #5b6270;
--accent: #b5720a;
--ok: #1a8a53;
--bad: #c8321f;
}
}
* { box-sizing: border-box; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.55;
}
.wrap {
max-width: 820px;
margin: 0 auto;
padding: 48px 20px 80px;
}
header h1 {
font-size: 2rem;
margin: 0 0 4px;
letter-spacing: -0.02em;
}
header p.tagline {
color: var(--muted);
font-size: 1.1rem;
margin: 0 0 28px;
}
.badges { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 32px; }
.badge {
font-size: 0.78rem;
padding: 3px 10px;
border-radius: 999px;
border: 1px solid var(--border);
color: var(--muted);
}
section { margin-bottom: 36px; }
h2 {
font-size: 1.05rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--muted);
margin: 0 0 14px;
}
p { margin: 0 0 12px; }
a { color: var(--accent); }
ul { margin: 0 0 12px; padding-left: 22px; }
li { margin-bottom: 6px; }
code {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 4px;
padding: 1px 6px;
font-size: 0.92em;
}
pre {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
padding: 16px;
overflow-x: auto;
font-size: 0.85rem;
}
pre code { background: none; border: none; padding: 0; }
.panel {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 10px;
padding: 20px 22px;
}
.note {
font-size: 0.88rem;
color: var(--muted);
border-left: 3px solid var(--accent);
padding: 4px 0 4px 14px;
margin: 16px 0;
}
.example-row {
display: flex;
justify-content: space-between;
gap: 12px;
padding: 5px 0;
border-bottom: 1px solid var(--border);
font-size: 0.85rem;
}
.example-row:last-child { border-bottom: none; }
.ok { color: var(--ok); }
.tool { color: var(--muted); }
footer {
margin-top: 48px;
padding-top: 20px;
border-top: 1px solid var(--border);
color: var(--muted);
font-size: 0.85rem;
}
</style>
</head>
<body>
<div class="wrap">
<header>
<h1>modelvet</h1>
<p class="tagline">Vet a Hugging Face model before you trust it.</p>
<div class="badges">
<span class="badge">MIT licensed</span>
<span class="badge">CLI, stdlib + picklescan + model-signing</span>
<span class="badge">v1</span>
</div>
</header>
<section>
<h2>Why</h2>
<p>
Malicious PyTorch checkpoints have repeatedly bypassed <code>picklescan</code>
(Hugging Face's own scanning dependency) via documented, CVE-tracked techniques —
CVE-2025-1889, CVE-2025-10155, CVE-2026-53875, and more.
</p>
<p>
Hugging Face's website shows scan-result badges, but <code>huggingface_hub</code>'s
<code>hf_hub_download()</code> / <code>snapshot_download()</code> have no API to check
"was this scanned, and did it pass" from a script. A developer or agent downloading a
model programmatically never sees that signal at all. <code>modelvet</code> closes that
gap: it re-scans what you actually downloaded, and checks for a
Sigstore / OpenSSF Model Signing signature (real, working, but essentially unadopted
on Hugging Face today).
</p>
</section>
<section>
<h2>Install & use</h2>
<div class="panel">
<p>Not on PyPI yet — install straight from the source repo:</p>
<pre><code>pip install git+https://github.com/sangmorg1-debug/modelvet.git
modelvet scan bert-base-uncased
modelvet scan bert-base-uncased --format json
modelvet scan local-check --local-dir ./downloaded-model</code></pre>
</div>
</section>
<section>
<h2>Example scan (captured output, not a live demo)</h2>
<div class="note">
This Space is static — Hugging Face's free tier no longer includes compute for
Gradio or Docker Spaces, only static pages. So this isn't an interactive scanner;
it's a real, captured run of <code>modelvet scan hf-internal-testing/tiny-random-gpt2</code>
against an actual public model, shown as-is. Install the CLI locally to scan a real repo
of your own.
</div>
<div class="panel">
<div class="example-row"><span>.gitattributes</span><span class="tool ok">picklescan · clean</span></div>
<div class="example-row"><span>config.json</span><span class="tool ok">picklescan · clean</span></div>
<div class="example-row"><span>merges.txt</span><span class="tool ok">picklescan · clean</span></div>
<div class="example-row"><span>model.safetensors</span><span class="tool ok">picklescan · clean</span></div>
<div class="example-row"><span>pytorch_model.bin</span><span class="tool ok">picklescan · clean</span></div>
<div class="example-row"><span>special_tokens_map.json</span><span class="tool ok">picklescan · clean</span></div>
<div class="example-row"><span>tf_model.h5</span><span class="tool ok">picklescan · clean</span></div>
<div class="example-row"><span>tokenizer.json</span><span class="tool ok">picklescan · clean</span></div>
<div class="example-row"><span>tokenizer_config.json</span><span class="tool ok">picklescan · clean</span></div>
<div class="example-row"><span>vocab.json</span><span class="tool ok">picklescan · clean</span></div>
<p style="margin-top:14px;"><strong>signature:</strong> <code>no_signature</code> — expected; this repo, like almost every repo on Hugging Face today, has never published one.</p>
<p><strong>exit code:</strong> <code>0</code></p>
</div>
</section>
<section>
<h2>What it does not do (yet)</h2>
<ul>
<li>No <code>transformers.from_pretrained()</code> wrapper — CLI only in v1.</li>
<li>No custom pickle-opcode engine — detection is built on <code>picklescan</code> (an actively maintained, if imperfect, tool), with two narrowly-scoped checks added for its documented bypasses (archive-format mismatch, hidden pickles under non-pickle extensions).</li>
<li>Signature verification only works against <code>--local-dir</code> today, not a bare Hub repo id — Hugging Face's cache layout gives no place to put a signature file for a model you didn't download and sign yourself.</li>
</ul>
</section>
<footer>
<p>
<a href="https://github.com/sangmorg1-debug/modelvet">Source on GitHub</a> ·
MIT License
</p>
</footer>
</div>
</body>
</html>
|