undoweave@0.4.0
CAUTION· not startedPublisher claims: "Enables agents to record file edits and selectively reverse a chosen edit while preserving separate later work, requiring preview approval and refusing ambiguous overlaps." Observed in sandbox: no network, touches nothing outside the project, writes no memory.
Coverage
Not started: dependency install failed; the server itself was not observed.- Tested
- the dependency install step · every file read, file written and host contacted by what ran
- Not tested
- server startup · the tool list · tool behavior
What this means for the label: Caution here covers what ran. The server's tools were not exercised with a real credential, so nothing about their behavior is asserted; the credential summary below says what to do with that.
Before you give it your token
- It will ask for
- no credential variables read in the code
- Where it talks to
- no vendor host named in the code
- What the honeypot saw
- no credential files read · no network
- What we could not test
- server startup · the tool list · tool behavior
Connect it under the guard. Not started: dependency install failed; the server itself was not observed. The code names no credential variable; the guard pins the network to what the honeypot saw and logs every call.
Never paste a credential into a chat, a ticket or a report, including ours. How the guard holds it.
Is [email protected] safe to install?
KillerSkills ran it in the KillerSkills honeypot sandbox (2 scenarios; not started: dependency install failed; the server itself was not observed) on 2026-11-11 and scored it 78/100 (Caution). It is not known to be malicious, but it has behaviour or code a security policy should decide on before install. Notable findings: Access to sensitive file paths; Access to sensitive file paths; Access to sensitive file paths. Summary: no network, touches nothing outside the project, writes no memory.
Behavior trace
Honeypot run · 0 s · 2 scenarios · 0 deviationsStatic findings
…, "id_rsa", "id_ed25519", "id_ecdsa", "id_dsa", ".git-credentials", ".pgpass", ".netrc", ".npmrc", ".pypirc"} DEVICE = re.compile(r"^(CON|PRN|AUX|NUL|CONIN\$|CONOUT\$…Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.if (lowered in PROTECTED_DIRS or lowered in PROTECTED_NAMES or lowered == ".env"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.or lowered.startswith(".env.") or lowered.endswith((".pem", ".key", ".p12", ".pfx", ".sqlite", ".sqlite3"))):Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.result = subprocess.run(["git", *args], cwd=root, text=True, capture_output=True, check=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.…json.loads((HERE / "fixtures.json").read_text(encoding="utf-8")) baseline = subprocess.run(["node", str(HERE / "pi_rewind_runner.mjs"), str(args.pi_rewind.resolve() / "src…Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.or part.casefold() == '.env' or part.casefold().startswith(('.env.', '.undoweave-write-'))Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.sha = subprocess.run(["git", "-C", str(checkout), "rev-parse", "HEAD"], text=True, capture_output=True, check=True).stdout.strip()Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.or lowered.startswith(".env.") or lowered.endswith((".pem", ".key", ".p12", ".pfx", ".sqlite", ".sqlite3"))):Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.if (lowered in PROTECTED_DIRS or lowered in PROTECTED_NAMES or lowered == ".env"Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.…e__).read_bytes()).hexdigest(), } if args.aider_source: aider = subprocess.run([str(args.aider_python), str(HERE / "aider_runner.py"), str(args.aider_source), …Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.subprocess.run(["git", *arguments], cwd=root, text=True, capture_output=True, check=True)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.…r.mjs"), str(args.pi_rewind.resolve() / "src" / "core.ts"), str(HERE / "fixtures.json")], text=True, encoding="utf-8", capture_output=True, check=True, timeout=180) data = { "schema_version": 1, …Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.…on), str(HERE / "aider_runner.py"), str(args.aider_source), str(HERE / "fixtures.json")], text=True, encoding="utf-8", capture_output=True, check=True, timeout=180) data["aider"] = json.loads(aider.stdout)…Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.dirty = subprocess.run(["git", "-C", str(checkout), "status", "--porcelain", "--untracked-files=no"], text=True, capture_output=True, check=True).stdoutFix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.result = subprocess.run([program, '-NoProfile', '-NonInteractive', '-Command',Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.subprocess.run([str(interpreter), str(repository / "scripts" / "smoke_install.py")], check=True, env=environment, cwd=base, timeout=120)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.subprocess.run([str(interpreter), "-I", "-m", "undoweave", "demo", "--recording"], check=True, env=environment, cwd=base, stdout=subprocess.DEVNULL, timeout=30)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.result = subprocess.run([program, '-c', line + '\npwd -P'], cwd=self.base,Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.result = subprocess.run([sys.executable, "-I", "-m", "undoweave", "--root", str(root), "--state-dir", str(state), "history", "--format", "html"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.actual = json.loads(subprocess.check_output([sys.executable, "-I", "-c", probe], cwd=temporary, text=True, timeout=30))Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.init = subprocess.run(['git', '-C', str(self.root), 'init', '--quiet', '--template=' + str(empty)],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.subprocess.run([str(interpreter), "-I", "-m", "undoweave", "demo"], check=True, env=environment, cwd=base, stdout=subprocess.DEVNULL, timeout=30)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.for name in ('.env', 'secret.py', 'local.py', 'main.py', 'notes.txt'):Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.return subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.setup = subprocess.run([sys.executable, '-I', '-m', 'undoweave', '--state-dir', str(selected_state),Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.preview = self.preview_of("b.txt", b"safe\n", "safe\n")Fix: Replace encoded or assembled strings with plain literals and remove undeclared network calls.made = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.config = subprocess.run([sys.executable, "-I", "-m", "undoweave", "--root", str(project), "config"], check=True, capture_output=True, encoding="utf-8", timeout=30)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.return subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.actual = subprocess.check_output(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.return subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.(self.root / 'src' / '.env').write_bytes(b'private canary\n')Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.result = subprocess.run(child_command(request), cwd=output, capture_output=True,Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.oracle = subprocess.run(['git', '-C', str(self.root), '-c', 'core.ignorecase=true',Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.".env", ".env.local", "nested/.env.production", ".git/config",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.for value in ('.', '../x', '.env', 'node_modules', '.codex/config.toml', 'src/tokens.json'):Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.response = subprocess.run([sys.executable, "-I", "-m", "undoweave", "--root", str(self.root), "--state-dir", str(self.state), *arguments], capture_output=True, encoding="utf-8", timeout=30)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.baseline_source = subprocess.check_output(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.process = subprocess.run([sys.executable, '-I', '-c', script, str(self.root), str(self.base / 'state')],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.('setup', '--watch', 'missing'), ('setup', '--watch', '.env'),Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.process_b = subprocess.Popen(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.raise UndoWeaveError("unsafe_state", "Journal must have owner-only permissions (chmod 600).")Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.Popen(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.process_a = subprocess.Popen(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.subprocess.run([str(interpreter), "-m", "pip", "install", "-c", str(repository / "constraints.txt"), str(wheels[0]) + "[mcp]"], check=True, env=environment, cwd=base, timeout=180)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.for name in ("credentials.json", ".env.production"):Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.self.process = subprocess.Popen(child_command({"mode": "record", "root": str(root), "state": str(state), "scopes": scopes}),Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.generated = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.preview = self.preview_of("b.txt", b"safe\n", "safe\n")Fix: Keep SKILL.md to visible, descriptive text. Remove comments and encoded text that address the agent.raise UndoWeaveError("unsafe_state", "State directory must have owner-only permissions (chmod 700).")Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.return subprocess.run([sys.executable, "-I", "-m", "undoweave", "--root", str(self.root), "--state-dir", str(self.state), *arguments], capture_output=True, encoding="utf-8", timeout=30)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.Cost to the agent
Tokens estimated at four characters each. The tool list is re-read by the agent on every turn, so it is the number to compare between servers that do the same job: ranked across the index.
Known vulnerabilities
Vulnerability advisories (OSV) cover npm and PyPI packages; this registry has no advisory database.
What would make this Verified
2 points to 80 · weights: behavior 45%, static 25%, prompt 15%, publisher 15%- Unclaimed publisher≈ +8 on the totalClaim jgolding1998: a verified publisher gets +50 on publisher trust. It is free and usually instant with GitHub sign-in.
- Access to sensitive file paths≈ +4 on the totalStop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
- Python subprocess execution detected≈ +2 on the totalBuild commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
- File type combined with upload action≈ +2 on the totalRemove the call, or declare the host in frontmatter and explain in the README what is sent and why.
- Bidirectional text override characters detected≈ +2 on the totalReplace encoded or assembled strings with plain literals and remove undeclared network calls.
- File permission modification command≈ +2 on the totalRequest the narrowest permission that works; replace wildcards with the exact paths or hosts.