Announcing Beacon: Self-improving memory for coding agents
← All MCP servers
MCP server

SysKnife

mcp:lacs-project/sysknife

Administers Linux via typed, approval-gated actions with an Ed25519-signed audit trail.

Verdict
Not analyzed

Indexed from the registries, but not analyzed yet. Lineage and listings below are current.

Package advisories 4

Known vulnerabilities and malicious-package reports (OSV) that reach the versions of the packages it installs or runs.

criticalGHSA-3pqx-4fqf-j49fPyPI/pyyaml
Deserialization of Untrusted Data in PyYAML
No version pinned, and the newest release may be affected · fixed in 5.2 · CONTRIBUTING.md:130
criticalGHSA-6757-jp84-gxfxPyPI/pyyaml
Improper Input Validation in PyYAML
No version pinned, and the newest release may be affected · fixed in 5.3.1 · CONTRIBUTING.md:130
criticalGHSA-8q59-q68h-6hv4PyPI/pyyaml
Improper Input Validation in PyYAML
No version pinned, and the newest release may be affected · fixed in 5.4 · CONTRIBUTING.md:130
criticalGHSA-rprw-h62v-c2w7PyPI/pyyaml
PyYAML insecurely deserializes YAML strings leading to arbitrary code execution
No version pinned, and the newest release may be affected · fixed in 5.1 · CONTRIBUTING.md:130

Execution chain 500

What it calls, runs, installs, reads and writes, with the line that does it.

Environment variables 150

ANTHROPIC_API_KEY
ANTHROPIC_API_KEY
ANTHROPIC_API_KEY
ANTHROPIC_API_KEY
CRATES_IO_CURL
CRATES_IO_POLL_INTERVAL
CRATES_IO_POLL_TIMEOUT
CRATES_IO_SLEEP
DEEPSEEK_API_KEY
DEEPSEEK_API_KEY
GEMINI_API_KEY
GEMINI_API_KEY
GEMINI_API_KEY
GROQ_API_KEY
GROQ_API_KEY
MISTRAL_API_KEY
MISTRAL_API_KEY
OPENAI_API_KEY
OPENAI_API_KEY
STORY_FAMILY
STORY_FAMILY
STORY_FAMILY
STORY_NAMES
STORY_NAMES
STORY_NAMES
STORY_NAMES
STORY_NAMES
STORY_NAMES
SYSKNIFE_BINARY
SYSKNIFE_CASSETTE
SYSKNIFE_CASSETTE
SYSKNIFE_CASSETTE
SYSKNIFE_CASSETTE
SYSKNIFE_CASSETTE
SYSKNIFE_LLM_MODEL
SYSKNIFE_PINNED_SHA256SUMS
SYSKNIFE_RESULTS_JSON
SYSKNIFE_RESULTS_JSON
SYSKNIFE_RESULTS_JSON
SYSKNIFE_RESULTS_JSON
SYSKNIFE_RESULTS_JSON
SYSKNIFE_STORY_DELAY_SECS
SYSKNIFE_STORY_TIMEOUT
SYSKNIFE_STORY_TIMEOUT
SYSKNIFE_STORY_TIMEOUT
SYSKNIFE_TEST_MODEL
SYSKNIFE_TEST_MODEL
SYSKNIFE_TEST_MODEL
SYSKNIFE_TEST_MODEL
SYSKNIFE_VM_CPUS
SYSKNIFE_VM_DIR
SYSKNIFE_VM_DISK
SYSKNIFE_VM_MEM
SYSKNIFE_VM_RELEASE
SYSKNIFE_VM_SSH_KEY
SYSKNIFE_VM_SSH_KEY
SYSKNIFE_VM_USER
UBUNTU_CLOUD_IMG_URL
UBUNTU_CLOUD_IMG_URL
UBUNTU_CLOUD_IMG_URL
UBUNTU_CLOUD_IMG_URL
UBUNTU_VM_BASE_IMAGE
UBUNTU_VM_CPUS
UBUNTU_VM_DIR
UBUNTU_VM_DISK
UBUNTU_VM_IMAGE_CACHE
UBUNTU_VM_MEM
UBUNTU_VM_SSH_PORT
UBUNTU_VM_USER
XAI_API_KEY
XAI_API_KEY
XDG_RUNTIME_DIR

Commands run 107

"true && sudo nohup git push origin v9.9.9",
{"nftables":{}}
/sbin/augenrules --load
/usr/bin/dd if=/dev/zero of=/proc/self/fd/{…} conv=nocreat,notrunc bs=1M count={…}
/usr/bin/env DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a /usr/bin/apt-get install -y unattended-upgrades
/usr/bin/fail2ban-client -t
/usr/bin/fail2ban-client reload
/usr/bin/firewall-cmd --reload
/usr/bin/gpasswd --delete {…} {…}
/usr/bin/mount -t {…} -o {…} {…} /proc/self/fd/{…}
/usr/bin/snap install --channel={…} {…}
/usr/bin/snap refresh --hold {…}
/usr/bin/systemctl {…} {…}
/usr/bin/systemctl daemon-reload
/usr/bin/systemctl enable --now {…}
/usr/bin/systemctl reload {…}
/usr/bin/systemctl restart rsyslog
/usr/bin/systemctl restart rsyslog
/usr/bin/systemd-analyze calendar {…}
/usr/bin/umount {…}
/usr/sbin/sshd -t
/usr/sbin/swapoff {…}
/usr/sbin/swapoff {…}
/usr/sbin/sysctl -w -- {…}
/usr/sbin/update-grub
/usr/sbin/usermod --append --groups {…} {…}
/usr/sbin/usermod {…} {…}
/usr/sbin/visudo -cf {…}
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
baseline="$(python3 -c "
bash {…} --metadata
cargo metadata --offline --format-version 1
cmd_ssh "cd /home/${VM_USER}/sysknife && sudo bash -c 'set -e; trap \"rm -f ${GUEST_ENV_FILE}\" EXIT; set -a; . ${GUEST_ENV_FILE}; set +a; rm -f ${GUEST_ENV_FILE}; trap - EXIT; exec bash tests/e2e/provision.sh'"
cmd_ssh "cd /home/${VM_USER}/sysknife && sudo bash -c 'set -e; trap \"rm -f ${GUEST_ENV_FILE}\" EXIT; set -a; . ${GUEST_ENV_FILE}; set +a; rm -f ${GUEST_ENV_FILE}; trap - EXIT; exec bash tests/e2e/provision.sh'"
cmd_ssh "cd /home/${VM_USER}/sysknife && sudo bash -c 'set -e; trap \"rm -f ${GUEST_ENV_FILE}\" EXIT; set -a; . ${GUEST_ENV_FILE}; set +a; rm -f ${GUEST_ENV_FILE}; trap - EXIT; exec bash tests/e2e/run-stories.sh${story_args}'"
cmd_ssh "cd /home/${VM_USER}/sysknife && sudo bash -c 'set -e; trap \"rm -f ${GUEST_ENV_FILE}\" EXIT; set -a; . ${GUEST_ENV_FILE}; set +a; rm -f ${GUEST_ENV_FILE}; trap - EXIT; exec bash tests/e2e/run-stories.sh${story_args}'"
cmd_ssh "cd /home/${VM_USER}/sysknife && sudo bash -c 'set -e; trap \"rm -f ${GUEST_ENV_FILE}\" EXIT; set -a; . ${GUEST_ENV_FILE}; set +a; rm -f ${GUEST_ENV_FILE}; trap - EXIT; exec bash tests/e2e/run-stories.sh${story_args}'"
cmd_ssh "cd /home/${VM_USER}/sysknife && sudo bash -c 'set -e; trap \"rm -f ${GUEST_ENV_FILE}\" EXIT; set -a; . ${GUEST_ENV_FILE}; set +a; rm -f ${GUEST_ENV_FILE}; trap - EXIT; exec bash tests/e2e/run-stories.sh${story_args}'"
cmd_ssh "cd /home/${VM_USER}/sysknife && sudo bash -c 'set -e; trap \"rm -f ${GUEST_ENV_FILE}\" EXIT; set -a; . ${GUEST_ENV_FILE}; set +a; rm -f ${GUEST_ENV_FILE}; trap - EXIT; exec bash tests/e2e/ubuntu-provision.sh'"
cmd_ssh "cd /home/${VM_USER}/sysknife && sudo bash -c 'set -e; trap \"rm -f ${GUEST_ENV_FILE}\" EXIT; set -a; . ${GUEST_ENV_FILE}; set +a; rm -f ${GUEST_ENV_FILE}; trap - EXIT; exec bash tests/e2e/ubuntu-provision.sh'"
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable || fail "Install Rust"
tests/e2e/provision.sh:89 · pipe_to_shell
curl -fsSL https://ollama.com/install.sh | sh || fail "Ollama install"
echo " Run stories: cd $REPO_DIR && sudo -E tests/e2e/run-stories.sh"
echo " Run stories: cd $REPO_DIR && sudo -E tests/e2e/run-stories.sh"
eval "$old_nullglob"
eval "val=\${$var:-}"
eval "value=\${$var-}"
eval "value=\${$var-}"
firewall-cmd --list-all
frontend_count="$(python3 -c "import json,sys; print(json.load(open(sys.argv[1]))['frontend_tests'])" "$repo_root/tests/evidence/workspace-tests.json")"
git ls-files -z
grep -Fq "| cmd_ssh \"sudo sh -c 'rm -f \${GUEST_ENV_FILE} && umask 077 && cat > \${GUEST_ENV_FILE}'\"" "$harness" || report "$rel does not transfer the environment over SSH stdin into a fresh 0600 file"
if grep -nE 'cmd_ssh[^#]*sudo *[$"]?\$\{?[A-Za-z_]' "$harness" | grep -vE 'sudo (sh|bash) -c' >/dev/null; then
if node -e "
js_path="$(HOME=/home/testuser node -e "
loginctl enable-linger
nc -zU {…}
not json
public (active) services: ssh
python3 -c 'import json, sys; print("\n".join(p["name"] for p in json.load(sys.stdin)["packages"]))'); then
runpy.run_path(str(staged_root / "scripts" / "release_versions.py"))
rust_count="$(python3 -c "import json,sys; print(json.load(open(sys.argv[1]))['tests'])" "$repo_root/tests/evidence/workspace-tests.json")"
self.assertIsNone(re.search(r'/(?:sh|bash|dash|runuser)(?:\s|$)', grant), grant)
ssh "${SSH_OPTIONS[@]}" -p "$SSH_PORT" "${VM_USER}@127.0.0.1" 'sudo cat /var/lib/sysknife-e2e/cloud-init-failed; sudo cloud-init status --long || true; sudo journalctl -u cloud-final --no-pager -n 100 || true' >&2
ssh "${SSH_OPTIONS[@]}" -p "$SSH_PORT" "${VM_USER}@127.0.0.1" 'sudo cloud-init status --long || true; sudo journalctl -u cloud-final --no-pager -n 100 || true' >&2
ssh "${SSH_OPTIONS[@]}" -p "$SSH_PORT" "${VM_USER}@127.0.0.1" 'sudo cloud-init status --long; sudo journalctl -u cloud-final --no-pager -n 100 || true' >&2
Status: active To Action From
Status: inactive
Status: inactive
Status: inactive
Status: inactive
Status: inactive
status="$(curl --retry 3 --silent --show-error --output /dev/null --user-agent 'sysknife-release-preflight/1.0 (https://github.com/lacs-project/sysknife)' --write-out '%{http_code}' "$url")"
su - "$VM_USER" -c 'curl --proto "=https" --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable' || fail "Install Rust"
sudo -n nft -j list ruleset
sudo -n nft -j list ruleset
sudo -n ufw status verbose
sudo -n ufw status verbose
sudo install -o root -g root -m 755 {…} {…}
sudo install -o root -g root -m 755 {…} {…}
which {…}
which sysknife
which sysknife
which sysknife

Files read 115

--- bootstrapped /etc/passwd ${VM_USER} entry ---
.claude/*.local.md
.cursor/mcp.json
packages/setup/index.js:755 · via:mergeMcpServers
.gitignore
.mcp.json
packages/setup/index.js:754 · via:mergeMcpServers
/etc/default/grub.sysknife.bak
/etc/default/grub.sysknife.bak
/etc/os-release
/etc/rsyslog.d/60-sysknife-forward.conf
packaging/sysknife-log-edit:161 · via:write_validated
/etc/security/faillock.conf
/etc/shadow
/etc/shadow
/etc/ssh/sshd_config.d/60-sysknife-{…}
/etc/sudoers.d
/etc/sudoers.d
/etc/sysctl.d/60-sysknife.conf
/home/{test_user}/.ssh/authorized_keys
/home/{username}/.ssh/authorized_keys
/home/${VM_USER}/.ssh
/home/${VM_USER}/.ssh
/home/${VM_USER}/.ssh
/home/${VM_USER}/.ssh/authorized_keys
/home/${VM_USER}/.ssh/authorized_keys
/home/${VM_USER}/.ssh/authorized_keys
/home/lacsdev/.ssh
/root/.ssh/authorized_keys
/root/.ssh/authorized_keys
<dynamic>
<dynamic>
packaging/sysknife-log-edit:137 · via:write_validated
<dynamic>
scripts/release_versions.py:108 · via:package_version
<dynamic>
scripts/release_versions.py:109 · via:internal_pins
<dynamic>
scripts/release_versions.py:117 · via:package_version
<dynamic>
<dynamic>
scripts/release_versions.py:186 · via:internal_pins
<dynamic>
scripts/release_versions.py:289 · via:package_version
<dynamic>
scripts/release_versions.py:307 · via:internal_pins
~/.codex/config.toml
${SYSKNIFE_VM_SSH_KEY:-$HOME/.ssh/sysknife-vm}
${SYSKNIFE_VM_SSH_KEY:-$HOME/.ssh/sysknife-vm}
$LACSDEV_SSH_DIR/authorized_keys
$LACSDEV_SSH_DIR/authorized_keys
authorized_keys
authorized_keys
authorized_keys
authorized_keys
authorized_keys exceeds size limit
authorized_keys updated, fingerprint: SHA256:abc
cannot read /etc/passwd: {e}
cannot read /etc/passwd: {e}
op_logrotate did NOT refuse '/etc/shadow
op_logrotate exited 0 on '/etc/shadow
who can read /etc/passwd

Files written 128

/etc/apt/apt.conf.d/20auto-upgrades
/etc/apt/preferences.d
/etc/default/grub
/etc/default/grub
/etc/default/grub
/etc/default/grub.sysknife.bak
/etc/rsyslog.d/60-sysknife-forward.conf
/etc/security/faillock.conf
/etc/security/pwquality.conf.d/60-sysknife.conf
packaging/sysknife-pam-edit:90 · via:atomic_write
/etc/ssh/sshd_config.d
/etc/ssh/sshd_config.d/60-sysknife-{…}
/etc/ssh/sshd_config.d/60-sysknife-{…}
/etc/ssh/sshd_config.d/60-sysknife-{…}
/etc/subgid
/etc/subuid
/etc/sysctl.d/60-sysknife.conf
/tmp/group
/tmp/group
/tmp/passwd
/tmp/passwd
/tmp/selinux-config
/tmp/shadow
/tmp/shadow
/usr/lib/sysknife/action-steps
/usr/lib/sysknife/apt-pin-edit
/usr/lib/sysknife/audit-edit
/usr/lib/sysknife/fail2ban-ban
/usr/lib/sysknife/fail2ban-jail-edit
/usr/lib/sysknife/grub-kargs-edit
/usr/lib/sysknife/log-edit
/usr/lib/sysknife/mount-edit
/usr/lib/sysknife/pam-edit
/usr/lib/sysknife/scheduled-job-edit
/usr/lib/sysknife/sshd-option-edit
/usr/lib/sysknife/sudoers-edit
/usr/lib/sysknife/sysctl-edit
/usr/lib/sysknife/unattended-upgrades-edit
/var/lib/ollama
\${GUEST_ENV_FILE}'\
\$state_dir/cloud-init-done
\$state_dir/cloud-init-failed
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>
<dynamic>

Linked repositories 21

GitHub repositories it links to or installs from, and whether their names can be taken over.

chalk/ansi-styles
url · not tracked
charmbracelet/vhs
url · not tracked
fb55/entities
url · not tracked
gitleaks/gitleaks
url · not tracked
inikulin/parse5
url · not tracked
lacs-project/specification
url · not tracked
linuxmint/linuxmint
url · not tracked
mozilla/diversity
url · not tracked
nektos/act
url · not tracked
nodejs/release
url · not tracked
openai/codex
url · not tracked
pop-os/pop
url · not tracked
pre-commit/pre-commit-hooks
url · not tracked
quickemu-project/quickemu
url · not tracked
rust-lang/crates.io-index
url · not tracked
rust-lang/mdbook
url · not tracked
tommilligan/mdbook-admonish
url · not tracked
vitejs/vite
url · not tracked