Grades are a hygiene check, not a security guarantee.

Claude Code, Skill

Thesis Proposal Skills

Write a convincing Bachelor's or Master's thesis proposal with the help of an AI agent, in English or German.

Compatibility: Not stated.

Grade C

One Medium finding. Read the findings before installing.

Graded by PlugVetRubric v2

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

Rescanned at commit 1666e690e7b2, unchanged since the check below.

SECRETS_PATH_CREDENTIAL

Why this grade

  • SECRETS_PATH_CREDENTIAL Medium

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

    harness/host_login.py, line 6 `~/.claude/.credentials.json`, so the harness and the operator shared one

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.

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

    install.py, line 262

    done = subprocess.run(

    install.py, line 549

    shutil.rmtree(path)

    harness/audit_llm_preflight.py, line 101

    proc = subprocess.Popen(

    Show more

    harness/claude_runner.py, line 1090

    done = subprocess.run([shell, "-l", "-i", "-c", script], env=dict(env),

    harness/claude_runner.py, line 1218

    shutil.rmtree(base, ignore_errors=True)

    harness/claude_runner.py, line 1672

    result = subprocess.run(

    harness/claude_runner.py, line 1908

    result = subprocess.run(

    harness/claude_runner.py, line 2610

    shutil.rmtree(ws, ignore_errors=True)

    harness/claude_runner.py, line 2652

    shutil.rmtree(ws, ignore_errors=True)

    harness/claude_runner.py, line 2742

    shutil.rmtree(ws, ignore_errors=True)

    harness/codex_cli.py, line 268

    stdin: int = subprocess.DEVNULL, pass_fds: Sequence[int] = ()) -> subprocess.Popen:

    harness/codex_cli.py, line 275

    return subprocess.Popen(list(argv), cwd=cwd, env=dict(env), stdin=stdin,

    harness/codex_cli.py, line 283

    stdin: int = subprocess.DEVNULL, pass_fds: Sequence[int] = ()) -> subprocess.Popen:

    harness/codex_cli.py, line 806

    shutil.rmtree(sessions, ignore_errors=True)

    harness/codex_cli.py, line 1379

    shutil.rmtree(home / SESSIONS, ignore_errors=True) # a crashed run's record is not this one

    harness/codex_cli.py, line 1396

    shutil.rmtree(scratch, ignore_errors=True)

  • Install and update

    Pass

    No install-time script found, and dependencies are pinned or absent.

  • Network

    Concern

    can reach a host that is not written as a fixed address.

    NETWORK_NO_FIXED_HOST

    install.py, line 207

    with urllib.request.urlopen(request, timeout=TIMEOUT, context=context) as response:

    install.py, line 215

    def fetch(url: str) -> bytes:

    install.py, line 254

    curl = system_curl()

    Show more

    install.py, line 255

    if curl is None:

    install.py, line 257

    "this Python cannot verify https certificates and no curl was found. "

    install.py, line 325

    source = read_zip(fetch(DEFAULT_SOURCE), "default-branch")

    install.py, line 327

    source = read_zip(fetch(spec), "url")

    harness/model_currency.py, line 147

    with urllib.request.urlopen(request, timeout=timeout) as response:

  • Secrets

    Concern

    reads a credential or environment file.

    SECRETS_PATH_CREDENTIAL SECRETS_PATH_DOTENV

    harness/host_login.py, line 6

    `~/.claude/.credentials.json`, so the harness and the operator shared one

    harness/host_login.py, line 117

    `.credentials.json` it uses: the harness home's by default, the directory

    harness/host_login.py, line 182

    CREDENTIALS = ".credentials.json"

    Show more

    harness/host_login.py, line 470

    forbidden=("AGENTS.md", "AGENTS.override.md", ".env", "hooks.json", "skills/*",

    harness/routing.py, line 802

    """The `.credentials.json` an isolated configuration links: the directory

    .env.example, line 2

    # Setup: cp .env.example .env, then fill in the values you need. `.env` is

    .gitignore, line 13

    # Local developer credentials (template: .env.example)

    AGENTS.md, line 7

    `thesis-proposal-skills`: eleven `proposal-*` agent skills (under `skills/`) that help students write thesis proposals - ten student-side, plus the supervisor-side `proposal-superv

  • 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

    uv.lock, line 1

    version = 1

    harness/copilot_cli.py, line 1

    """The GitHub Copilot host of the dev runner: invocation, plan billing guard, readers.

    openspec/changes/archive/2026-08-10-skill-routing-rig/design.md, line 1

    ## Context

  • Licence

    Pass

    A licence file is present (LICENSE.txt).

  • Maintainer activity

    Pass

    The latest commit is within the last 365 days.

Note

Hygiene check of commit 1666e690e7b2. can delete files. can reach a host that is not written as a fixed address. 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.

Date and source

Date checked:

View source

github.com

Commit graded: 1666e690e7b2f0659531253d319d41ebf0a310d7

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