dumbtv
dumbtv takes the ads, screen tracking and update nags out of your Fire TV over ADB. No root, none of your apps touched, every step can be undone. Free and open source.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Provenance-based tool-call guard for LLM agents. Cuts prompt-injection attack success from 33% to 0% on AgentDojo banking.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Untrusted data must not steer sensitive tool calls.
Live site and playground: https://provguard.vercel.app
LLM agents read e-mails, web pages and documents written by strangers, then call tools with real side effects. Most defences try to detect malicious text. My prompt-injection detector benchmark shows why that is fragile: detectors that score 0.96–0.98 F1 on one dataset drop to 0.37–0.70 on another.
ProvGuard takes the opposite approach, borrowed from information-flow control:
it does not ask "is this text malicious?" but "which source supplied this
argument?" A recipient, an IBAN or an amount that only appears in an e-mail
cannot drive send_email or transfer_money, however the e-mail is worded.
== Hijacked: recipient came from an e-mail
without ProvGuard: send_email(to='[email protected]') runs
with ProvGuard: send_email: block
- [untrusted-argument] to='[email protected]' appears only in untrusted input from tool:read_inbox
- [tainted-context] context contains untrusted input from tool:read_inbox
to: {require: trusted} passes only if a trusted source contains the value.
Values that came from untrusted input, or that the model invented, fail closed.AgentDojo (v1.2.2) ships a reference
solution for every task. python -m bench.oracle replays them through ProvGuard,
with no LLM in the loop, so every number below is deterministic:
important_instructions attack, then the attacker's reference calls follow as
if the agent were fully hijacked. Stopped means at least one of them is denied.| Suite | Legitimate tasks blocked | Attacks stopped (v1) | Attacks stopped (v2) |
|---|---|---|---|
| banking | 3 / 16 | 144 / 144 | 144 / 144 (100%) |
| slack | 12 / 21 | 53 / 105 | 97 / 105 (92%) |
| travel | 0 / 20 | 79 / 120 | 79 / 120 (66%) |
| workspace | 5 / 40 | 200 / 240 | 200 / 240 (83%) |
Pairs whose injection task has no reference solution in AgentDojo (20 in travel, 320 in workspace) cannot be replayed and are excluded, not counted as stopped.
How the policies were written. The four policies in bench/policies/ were
committed before any injection task was read, from tool signatures alone.
They have not been changed since.
v1 → v2, a change informed by the v1 failures. In Slack, the attack text
was planted in a channel name, and v1 trusted the channel list, so a URL
inside that name looked trusted. v2 changes the library, not the policies:
structured tool output now vouches only for complete field values
(general), never for text found inside a field. Both result sets are kept in
results/oracle-v1/ and results/oracle/.
What still gets through, and why. Every remaining attack works the same way: the attacker picks among options that are legitimate anyway.
13, an id that appears in the user's own file list (workspace).Argument provenance cannot stop these by design. on_tainted: confirm on
state-changing tools moves them to a human; the benchmark has no human, so that
trade-off is reported rather than hidden.
What it costs. The blocked legitimate tasks are tasks where the user delegated the choice to untrusted content: "pay the bill in this file", "visit the link Eve posted", "invite Dora, her e-mail is on her website". Under a strict policy these need confirmation. That is the honest price of the guarantee, and the main thing v3 should reduce.
These numbers measure the policy, not an agent. A live model may take other paths, which the next section measures.
Qwen3 8B (local, Ollama, thinking disabled, temperature 0.7) on AgentDojo banking: all 16 user tasks, and the first three injection tasks (chosen by index before the run) against every user task. Same policy, same attack, one run per defence.
| No defence | ProvGuard | |
|---|---|---|
| Attack success | 16 / 48 (33%) | 0 / 48 (0%) |
| Utility, no attack | 8 / 16 | 9 / 16 |
| Utility under attack | 26 / 48 | 24 / 48 |
user_task_0 ("pay the bill in this file"), is the
one the model-free replay predicted: the IBAN comes from an untrusted file.Reproduce with python -m bench.run --suite banking --defense none provguard --no-think --model qwen3-8k --injection-tasks injection_task_0 injection_task_1 injection_task_2 (about 10 hours on a 6 GB laptop GPU).
pip install -e ".[yaml]"
python examples/demo.py
from provguard import Guard, Policy, ToolCallDenied
guard = Guard(Policy.from_yaml("examples/email_agent.yaml"))
guard.user("Read my inbox and send a summary to [email protected]")
read_inbox = guard.protect(read_inbox) # output recorded as untrusted
send_email = guard.protect(send_email, confirm=ask_the_user) # every call checked
try:
send_email(to="[email protected]", body="...")
except ToolCallDenied as denied:
print(denied.decision.explain())
version: 1
default:
on_tainted: confirm # unknown tools are never silently allowed
tools:
read_inbox:
output: untrusted
get_contacts:
output: trusted
send_email:
on_tainted: confirm
args:
to:
require: trusted
allow: ["[email protected]"]
on_violation: block
Unknown keys and invalid values raise PolicyError: a typo in a security policy
fails loudly instead of being ignored.
Stated up front, because a security tool that hides its limits is not one.
"1", "yes") are weak evidence; protect them with
allow lists or tainted-context rules instead.on_tainted, not by argument rules.user, system or record_result is invisible to it.MIT