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