Grades are a hygiene check, not a security guarantee.

MCP, MCP server

clawops

MCP-native infrastructure ops for OpenClaw, with read-only mode, destructive-action confirmation, and audit logs built in.

Compatibility: Not stated.

Grade D

Two or more Medium findings, or a High. Only try it in a sandbox.

Graded by PlugVetRubric v2

Not a guarantee. A hygiene check of the source at the commit shown, not a security audit.

INSTALL_REMOTE_SCRIPT SECRETS_PATH_CREDENTIAL

Why this grade

  • INSTALL_REMOTE_SCRIPT Medium

    Fetches a script from the network and runs it (a pipe to a shell, or an install hook with a URL).

    src/harden/modules/tailscale.ts, line 192 const r = await exec('curl -fsSL https://tailscale.com/install.sh | sh')

  • SECRETS_PATH_CREDENTIAL Medium

    Mentions a credential store path (~/.ssh, id_rsa, .npmrc, .aws/credentials, credentials.json, .netrc).

    src/cli/commands/setup.ts, line 196 message: `SSH private key file: (the key file on your computer used to log in - e.g. ~/.ssh/id_ed25519)`,

Any High, or two or more Medium findings, give D. One Medium gives C. Low findings or a security Note give B. Each code names a finding behind the letter.

If you think this grade is wrong, email [email protected] with the entry link and your evidence. We aim to acknowledge within two working days and decide within seven. If we confirm an error, we aim to correct it within 24 hours of confirming it. These are aims, not guarantees.

Grades are a hygiene check of the source at the commit shown, on the date checked, not a security audit or a guarantee. The free directory grades are automated. Before release, a PlugVet engineer reviews every paid report and any grade we hold back, including all F grades, against the source code and the evidence we quote.

What was checked

Plain notes from the hygiene checks.

  • Permissions

    Concern

    can delete files.

    PERMISSION_DELETE_FILES

    src/hostagent/install.ts, line 180

    "for(const d of ['lib','spec'])fs.rmSync(p.join(root,d+'.new'),{recursive:true,force:true});",

    src/hostagent/install.ts, line 185

    "for(const d of ['lib','spec']){fs.rmSync(p.join(root,d),{recursive:true,force:true});",

    .claude/rules/ssh.md, line 9

    1. **Never shell out to /usr/bin/ssh:** All SSH operations use the `ssh2` npm library directly. No `child_process.exec('ssh ...')` or similar.

  • Install and update

    Serious

    install fetches a script from the network.

    INSTALL_REMOTE_SCRIPT

    docs/spikes/SP-16-container-egress.md, line 9

    den/modules/tailscale.ts` installs it (`curl -fsSL https://tailscale.com/install.sh | sh`). That installed **tailscaled 1.104.1*

    src/harden/modules/tailscale.ts, line 192

    const r = await exec('curl -fsSL https://tailscale.com/install.sh | sh')

  • Network

    Concern

    can reach a host that is not written as a fixed address. can reach local-tailscaled.sock. The description does not name that host. can reach nodejs.org. The description does not name that host. can reach download.docker.com. The description does not name that host. can reach login.microsoftonline.com. The description does not name that host. can reach storage.googleapis.com. The description does not name that host.

    NETWORK_NO_FIXED_HOST NETWORK_UNNAMED_HOST

    scripts/e2e/mcp-recovery-probe.mjs, line 47

    const started = () => /"status"\s*:\s*"started"/.test(onHost('curl -s --max-time 5 http://127.0.0.1:18789/startupz'))

    site/app/layout.tsx, line 78

    neither appears in server-rendered HTML. Verifying with `curl | grep` will

    site/app/opengraph-image.tsx, line 50

    const css = await fetch(api, { headers: { 'User-Agent': 'Mozilla/4.0' } }).then((r) => r.text())

    Show more

    site/app/opengraph-image.tsx, line 53

    return await fetch(url).then((r) => r.arrayBuffer())

    src/diagnostics/index.ts, line 483

    `curl -s --max-time 5 --unix-socket ${TAILSCALED_SOCKET} -H 'Host: local-tailscaled.sock' http://local-tailscaled.sock/localapi/v0/debug-packet-filter-rules 2>/dev/null || true`,

    src/harden/azure-api.ts, line 47

    res = await fetch(`${ARM}/subscriptions/${ctx.subscriptionId}${pathAndQuery}`, {

    src/harden/azure-api.ts, line 117

    const res = await fetch(`${ARM}${id}?api-version=${apiVersion}`, {

    src/harden/gcp-api.ts, line 38

    const res = await fetch(

    src/hostagent/install.ts, line 161

    `curl -fsSL --proto '=https' -o "$T/node.tgz" "https://nodejs.org/dist/${version}/node-${version}-linux-$A.tar.gz"`,

    src/openclaw/health.ts, line 41

    `${pathPrefix}curl -fsS -m 5 http://127.0.0.1:${port}${HEALTH_PATHS[kind]} 2>/dev/null || true`

  • Secrets

    Concern

    reads a credential or environment file.

    SECRETS_ENV_READ SECRETS_PATH_CREDENTIAL

    scripts/dev/mutation-check.mjs, line 547

    oviders/azure/preflight.ts', from: " process.env['AZURE_STORAGE_KEY'] ?? process.env['AZURE_STORAGE_SAS_TOK

    src/cli/commands/setup.ts, line 196

    message: `SSH private key file: (the key file on your computer used to log in - e.g. ~/.ssh/id_ed25519)`,

    src/cli/commands/setup.ts, line 1318

    info('\nConnecting to localhost requires your public key to be in ~/.ssh/authorized_keys.')

    Show more

    src/cli/commands/setup.ts, line 1322

    message: 'Add your public key to ~/.ssh/authorized_keys now? (required for SSH to work)',

    src/cli/commands/setup.ts, line 1331

    success('Public key added to ~/.ssh/authorized_keys.')

    src/cli/commands/setup.ts, line 1333

    info('SSH will likely fail. Add this line to ~/.ssh/authorized_keys manually:')

    src/cli/commands/setup.ts, line 1339

    info('Make sure this public key is in ~/.ssh/authorized_keys on your server:')

    src/cli/commands/setup.ts, line 1341

    info('(If you just created the server, paste the line above into the server\'s ~/.ssh/authorized_keys file.)\n')

    src/cli/commands/setup.ts, line 1355

    info(`Public key (add this to your server's ~/.ssh/authorized_keys if needed):\n ${readFileSync(`${keyPath}.pub`, 'utf-8').trim()}`)

    src/config/profiles.ts, line 42

    return process.env['GOOGLE_APPLICATION_CREDENTIALS']

    src/config/profiles.ts, line 43

    ? { GOOGLE_APPLICATION_CREDENTIALS: process.env['GOOGLE_APPLICATION_CREDENTIALS'] }

    src/mcp/server.ts, line 108

    const token = opts.token ?? process.env['CLAWOPS_MCP_TOKEN']

    src/providers/aws/index.ts, line 60

    const hasKeyId = Boolean(process.env['AWS_ACCESS_KEY_ID'])

    src/providers/aws/index.ts, line 61

    const hasOidc = Boolean(process.env['AWS_ROLE_ARN'] && process.env['AWS_WEB_IDENTITY_TOKEN_FILE'])

    src/providers/azure/index.ts, line 62

    const clientSecret = process.env['AZURE_CLIENT_SECRET']

    src/providers/azure/index.ts, line 63

    const federatedToken = process.env['AZURE_FEDERATED_TOKEN_FILE']

  • Agent instructions

    Pass

    No instruction to ignore earlier instructions or to hide a step.

  • Obfuscation

    Note

    a file was over the read cap and was not fully read. the file cap was reached before every file was read.

    OBFUSCATION_FILE_OVER_READ_CAP OBFUSCATION_FILE_CAP_REACHED

    pnpm-lock.yaml, line 1

    lockfileVersion: '9.0'

    spec/openclaw-2.0.config.schema.json, line 1

    {"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"$schema":{"type":"string"},"meta":{"type":"object","properties":{"lastTouchedVersion":{"type":"s

    src/transport/wait.ts, line 1

    // Waiting for a freshly created host to accept SSH.

  • Licence

    Pass

    A licence file is present (LICENSE).

  • Maintainer activity

    Pass

    The latest commit is within the last 365 days.

Note

Hygiene check of commit 0b1a9a3c6109. can delete files. install fetches a script from the network. can reach a host that is not written as a fixed address. can reach local-tailscaled.sock. The description does not name that host. can reach nodejs.org. The description does not name that host. can reach download.docker.com. The description does not name that host. can reach login.microsoftonline.com. The description does not name that host. can reach storage.googleapis.com. The description does not name that host. reads a credential or environment file. a file was over the read cap and was not fully read. the file cap was reached before every file was read. Grades are a hygiene c

Date and source

Date checked:

View source

github.com

Commit graded: 0b1a9a3c6109b5c2cea854b602042819666fe6b3

This link goes to the original host. PlugVet does not host or check what you download from there, and installing it is your own decision and risk.

Read how this letter is chosen