Skip to content

Releases: soemoescode/guardskill

Release list

v0.5.2

Choose a tag to compare

@soemoescode soemoescode released this 14 Sep 14:25
Immutable release. Only release title and notes can be modified.

Three findings from the fourth independent review, all of them in the code that the 0.5.1 fixes touched. None was blocking; all three are the kind of thing that makes a report worth less than the scan behind it.

  • R4-01 A hook produces one finding again. Reusing the MCP severity ladder for hooks was the right fix, but it emitted the MCP rule alongside the hook rule: two findings at the same severity for one hook, the second announcing an MCP server that did not exist. ruleId is also the field people suppress on in SARIF, so silencing a noisy MCP rule would have silenced hooks with it. The grading is unchanged; the reason now travels inside the hook finding — [runs from a temporary or hidden location] — instead of as a second line that says something untrue.
  • R4-02 A URL among the arguments only counts as an endpoint when the command is a known bridge (mcp-remote, mcp-proxy, supergateway). Taking every URL turned --registry https://registry.npmjs.org into a remote MCP server without authentication. "The last positional argument" does not separate the two either — in the counter-example the last argument is a documentation link. A hand-rolled bridge is missed now; that is the price of not crying wolf in the class that had just been calibrated.
  • R4-03 At most 50 findings per rule per file are listed, the rest counted in one summary finding, and the scan declares itself incomplete. A 964 KB .mcp.json with 15,000 shell servers produced 30,000 findings and a 21.8 MB SARIF document; GitHub refuses an upload above 25,000 results or 10 MB, so the Security tab showed nothing at all. That is the same shape as one file suppressing a whole scan, one surface further out: the finding existed and never reached anyone.

The review's headline — that 0.5.1 was tagged but not published — was already resolved when it was written: the release workflow succeeded at 15:02 UTC and npx guardskill@latest has reported 0.5.1 since. The failed run before it was the commit with a test that asserted the case-sensitive branch on every platform, which macOS caught.


Install: npx guardskill@0.5.2 .

In CI: uses: soemoescode/guardskill@v0.5.2

v0.4.1

Choose a tag to compare

@soemoescode soemoescode released this 09 Sep 15:46
Immutable release. Only release title and notes can be modified.

A repository can make your coding agent run code the moment it opens the folder. GuardSkill checks for that before you do.

npx guardskill .

Read-only. No network calls, no telemetry, no configuration, no account, no dependencies. It reads git configuration and hook scripts, prints what it found, and exits.

The problem

Coding agents gather context by running ordinary git commands — git status, git diff — as soon as they open a project. Git reads its settings from the repository's own .git/config, and roughly two dozen of those settings name a program for git to execute. Put a command in core.fsmonitor and it runs, with your privileges, outside any sandbox, before you have typed anything.

Two pieces of public research make this concrete. GitSpawn (Manifold Security) reported eight findings across seven coding agents, and their note on delivery matters: cloning a hostile URL does not trigger it, because .git/config is not transferred by a clone — the project has to arrive as files with its .git directory already inside, so a zip, a shared drive, a sync folder or an unpacked archive is the vector. CVE-2026-45033 (GitHub Copilot CLI, CVSS 8.5) shows a bare repository hidden anywhere in the tree is enough on its own, because git discovers it while walking directories.

The recommended user-side mitigation in both write-ups is the same: inspect the git configuration before you open the directory with an agent. That is tedious by hand across a tree.

What is in 0.4.1

No detection changes. This release exists so the published entry points are what the documentation says they are.

  • A GitHub Action, so the scan runs on every push instead of when someone remembers. Inputs are passed through the environment and read as shell variables rather than interpolated into the script — interpolating a workflow expression into a shell line is the class of bug this tool reports, and it would be a poor look here. It installs the published package with --ignore-scripts, because this action runs in other people's CI and a lifecycle script must never execute.
  • The action is named GuardSkill Scan. GuardSkill is an existing GitHub username, and the Marketplace requires a name that matches no existing action, user or organisation.
  • Three tests for the action itself, the first of which asserts that its default version input equals this package's version. Forget to bump it and every consumer keeps scanning with the old rules while the listing names the new tag — the same failure shape as the packaging bug closed in 0.4.0, one layer out.
  • Issue templates for false positives and for missing execution keys. The second requires a reference to the git documentation, so the coverage inventory stays checkable rather than becoming a list of opinions.
  • An English index to docs/, which holds the two independent security reviews this tool was put through and the acceptance gate they were judged against. Both rounds found a blocking defect; both are published unedited.

Using it

npx guardskill .                       # scan a project
npx guardskill . --json                # machine-readable, schemaVersion 1
npx skills add soemoescode/guardskill  # as an agent skill, so the agent runs it itself

In CI:

- uses: soemoescode/guardskill@v0.4.1
  with:
    fail-on: high          # critical, high, medium or low
    exclude: test/fixtures # comma-separated, optional

Exit codes: 0 nothing at or above the threshold and the whole tree inspected · 1 findings at or above it · 2 the scan could not run · 3 part of the tree was not inspected. An incomplete scan fails unless you pass --allow-incomplete, because "we did not look there" is not the same as "there is nothing there".

Verifying what you install

Published from the tag by GitHub Actions with npm provenance, through OIDC — there is no publish credential stored in a repository secret. The package on the registry is traceable to the workflow run and the commit that built it, and you can check that yourself rather than taking it on trust:

npm audit signatures

What it does not do

Detection stops at git level. Agent settings files, MCP server definitions and npm lifecycle scripts reach the same outcome by a different route and are not covered here — that class is 0.5.0, and unlike the git-level vectors it travels with an ordinary git clone. Four executing git keys are deliberately out of scope, listed with reasons in rules/git-exec-keys-inventory.md; the accepted residual risks are in SECURITY.md.

False positives are the most useful thing you can report: a scanner that cries wolf gets uninstalled, so a report there is worth more than a star. 86 tests, none skipped on Linux, no dependencies, no network, MIT.