Install
openclaw skills install @j3ffyang/untrusted-code-safetyZero-trust procedure for reviewing or running code from an unknown source. Use when reviewing, vetting, cloning, installing, or running code from an untrusted source (repo invites, packages, scripts, executable config files), when asked whether code is safe or hazardous, when executed code may read secrets/files or reach the network, and when the user says "raise hands", "stop and alert", or "sandbox it". Also trigger on suspicion of malicious, harmful, deceptive, cheating, or stealing behavior.
openclaw skills install @j3ffyang/untrusted-code-safetyA zero-trust procedure for handling code you do not control. It records the standing contract the user requires, then the workflow to honor it. When in doubt, stop and ask — never assume.
/tmp is the only workspace for untrusted code. Never let it read, collect, or send data from this machine outside /tmp.Halt the run, do not continue, and report to the user at once (with what was attempted, the path/target, and the evidence) if any executed code:
/tmp (or outside the declared sandbox);process.env, API keys, tokens, credentials, SSH/Git config, wallets;Raising hands is not a status update — it is a hard stop. Do not "finish the run first". Do not bury it. Surface it in the next message.
If the sandbox boundary, the intent, or the safety of an action is unclear, ask the user before proceeding. A wrong assumption here is expensive.
Default: do not execute. Static triage is usually enough. Escalate to a sandboxed run only when the question cannot be answered statically, and get the user's explicit go-ahead before any Level-2 execution (step 3 below).
fs/env/network/child-process reach and scream on violations.| Level | Action | Safe on daily driver? |
|---|---|---|
| 0 | Metadata only (gh api, git log, sizes, dates) | yes |
| 1 | Read/triage files as plain text (no build, no eval) | yes |
| 2 | Execute in a throwaway sandbox: no network, no secrets, cleared env, non-root, fs allowlist | contained |
| 3 | Execute with host mounts / credentials / network | never for untrusted code |
git log --format='%h %ad %an <%ae> %s' --date=iso | head -40
git shortlog -sne
find . -type f -not -path './.git/*' -size +500k -printf '%s\t%p\n' | sort -rn
rg -l --hidden -g '!**/node_modules/**' 'eval\(|Function\(|atob\(|Buffer\.from\(|fromCharCode'
rg -n '(pre|post)?(install|prepare|pack|publish)' package.json **/package.json 2>/dev/null
rg -n 'require\(|import ' tailwind.config.js postcss.config.js babel.config.js webpack.config.js config-overrides.js 2>/dev/null
rg -n 'child_process|execSync|spawn|process\.env|os\.homedir|\.ssh|id_rsa|wallet|mnemonic|privateKey' -g '!**/node_modules/**'
npm view <pkg> repository dist.tarball time.modified
Other tells: a single giant line, rotated string arrays, hex/base64 blobs,
--no-save, npm install inside build scripts, curl|sh, config files that
require code, and lifecycle hooks (preinstall/install/postinstall/prepare).
npm ci --ignore-scripts (or npm install --ignore-scripts) — lifecycle hooks never run, for any untrusted dependency tree.npm config set ignore-scripts true for the session, and git config --global core.hooksPath /dev/null to neutralize repo hooks.HOME; never install with real credentials in scope.sha256sum <file> and compare against a trusted source.git verify-commit <sha> or git log --show-signature for signed history.npm audit signatures for registry provenance/attestations.gh attestation verify <artifact> --repo <owner>/<repo> for GitHub build attestations.git diff.Create the work dir first (mkdir -p /tmp/opencode/sbx/work), and adjust /usr, /bin, /lib*, and /etc/ld.so.cache for the distro — these bind paths are glibc/Arch-shaped.
bwrap --unshare-all --die-with-parent --new-session \
--ro-bind /usr /usr --ro-bind /bin /bin --ro-bind /lib /lib --ro-bind /lib64 /lib64 \
--ro-bind /etc/ld.so.cache /etc/ld.so.cache \
--proc /proc --dev /dev --tmpfs /tmp \
--bind /tmp/opencode/sbx/work /work \
--chdir /work --clearenv --setenv PATH /usr/bin --setenv HOME /work \
--uid 65534 --gid 65534 \
/usr/bin/bash -c 'your-harness'
--unshare-all gives no network interface and no DNS; --clearenv drops all secrets; nobody drops privilege; only the sandbox dir is mounted.--permission --allow-fs-read=/work --allow-fs-write=/work as a second, kernel-enforced layer.getent hosts github.com returns no DNS, and id shows nobody.socket.io-client / axios / sql.js / form-data modules that only log their arguments, to reveal C2 targets without real network.Minimal interception skeleton (run inside the sandbox, before loading the payload):
const Module = require("module");
const realLoad = Module._load;
const noop = (name) => new Proxy({}, { get: (_, p) => (...a) => console.log("[hit]", name, String(p), a[0] ?? "") });
Module._load = function (req) {
if (["child_process", "net", "tls", "http", "https", "dns", "http2", "dgram"].includes(req)) return noop(req);
return realLoad.apply(this, arguments);
};
child_process, net, tls, http, https, dns, http2, dgram, worker_threads, and global fetch with logging no-ops.fs and process.env; log every path and sensitive key; hard-alarm on any access outside the allowlist root.tcpdump, ss -tp, lsof -i); if absent, say the containment of record is the namespace + Node-permission pairing.process.env is not proxied or only some fs functions are wrapped, say so explicitly — "no egress" is not "provably could not read local data". UNTRUSTED INPUT (repo · package · invite · script · config)
▼
RULE 1 — DETECT (static, no execution)
▼
RULE 2 — BE SENSITIVE (data inventory)
▼
RULE 3 — BE ALERTED (contain + instrument; raise hands on violation)
▼
VERDICT: MALICIOUS → quarantine · rotate · report · never run
▼
RULE 4 — NEVER TRUST (a pass at level N never grants level N+1)
GitHub has no abuse email — use the web form: https://support.github.com/contact/report-abuse?category=report-abuse&report=other&report_type=unspecified (or the repo's About sidebar → Report repository). Category: Malware (AUP §5, Active Malware or Exploits) — not Phishing (AUP §4, deceiving a person into revealing information). GitHub's own security.txt points only to https://hackerone.com/github, which is for bugs in GitHub's products, not for third-party malicious repos.
See ai-thoughts/docs/260929-brisova-malware-analysis.md — a private repo invite (zignaly-open-projects/Brisova) whose obfuscated Tailwind plugin ran npm install sql.js socket.io-client form-data axios --no-save at build time. Verdict: malicious build-time payload; no egress occurred; clone deleted.