Skip to content
Agentmart
Submit a tool

fork

Fork the scanned repository into the configured GitHub organisation, enable private vulnerability reporting on the fork, record the scan as a git note, and…

Skill by lukehinds

IndexedMIT
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/lukehinds-fork

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Fork the scanned repository into the configured GitHub organisation, enable private vulnerability reporting on the fork, record the scan as a git note, and file each finding as a draft security advisory on the fork with a relevant org team invited as collaborator. Run after a scan has produced findings; the fork is the staging area for disclosure work.

Use cases: security, productivity

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/fork

What's inside

Skill name
fork
Description
Fork the scanned repository into the configured GitHub organisation, enable private vulnerability reporting on the fork, record the scan as a git note, and file each finding as a draft security advisory on the fork with a relevant org team invited as collaborator. Run after a scan has produced findings; the fork is the staging area for disclosure work.
License
MIT
Compatibility
Needs the gh CLI authenticated with a token that can create forks in the fork_org and manage repository settings and security advisories there. Needs network access to api.github.com and the scrutineer API. github.com upstreams only for now.
Metadata
scrutineer.version: 1 · scrutineer.output_file: report.json · scrutineer.output_kind: freeform
Instructions
239 lines in SKILL.md · view on GitHub

Before installing

  • Instructions call the network

Files (4)

  • SKILL.md
  • SKILL.md.bundle
  • schema.json
  • schema.json.bundle

SKILL.md (first lines)

# fork

Stage a scanned repository into the disclosure org. Forks the upstream into `fork_org`, turns on private vulnerability reporting on the fork, leaves a git note recording when scrutineer last scanned the upstream, and opens one draft advisory per finding on the fork so analysts and the relevant team can collaborate on the write-up before anything goes upstream.

## Workspace

- `./src` — the upstream clone at the commit that was scanned
- `./context.json` — has `repository.url`, `repository.full_name`, `scrutineer.api_base`, `scrutineer.token`, `scrutineer.repository_id`, `scrutineer.scan_id`, and `scrutineer.fork_org`
- `./report.json` — write what you did

Use the `gh` CLI for every GitHub call. Do not use curl against api.github.com.

## Preconditions

Read `./context.json`. Refuse to continue (write `{"error": "..."}` to `report.json` and exit 0) if:

- `scrutineer.fork_org` is missing or empty — the operator has not configured `fork_org` in scrutineer.yaml
- `repository.url` does not have host `github.com` — only GitHub upstreams are supported for now; non-GitHub hosts will get a create-in-org path later
- `gh auth status` fails — the runner has no GitHub credentials

Derive `{owner}/{repo}` from `repository.full_name` (fall back to parsing the path of `repository.url`, stripping a trailing `.git`).

## 1. Fork into the org

First check whether scrutineer already knows the fork: `GET {api_base}/repositories/{repository_id}` returns a `fork` field. If it is non-empty and `gh repo view {fork}` succeeds with `.parent` pointing at `{owner}/{repo}`, use it as `{fork_org}/{fork_name}`, record `"forked": "exists"`, and skip to step 2.

Otherwise the fork normally lives at `{fork_org}/{repo}`, but that slot may already be taken by an unrelated repository (e.g. forking `foo/redis` when `fork-central/redis` is already a fork of `bar/redis`). Resolve the fork name as follows.

For each candidate name, in order `{repo}` then `{owner}-{repo}`:

```
gh repo view {fork_org}/{candidate} --json name,parent
```

- not found — the slot is free; remember this candidate as `{fork_name}` and stop
- found and `.parent.owner.login == {owner}` and `.parent.name == {repo}` — this is already our fork; set `{fork_name}` to this candidate, record `"forked": "exists"`, and skip to step 2
- found but the parent is something else (or null) — the name is taken by an unrelated repo; move to the next candidate

If both candidates are taken by unrelated repositories, write `{"error": "no free fork name for {owner}/{repo} in {fork_org}"}` and exit 0.

If you found a free slot, create the fork there:

```
gh repo fork {owner}/{repo} --org {fork_org} --fork-name {fork_name} --clone=false --default-branch-only
```

`gh repo fork` is asynchronous on GitHub's side. Poll `gh repo view {fork_org}/{fork_name}` until it returns 0 (a few seconds is normal; give up after a minute and report `{"error": "fork did not become available"}`). Record `"forked": "created"`.

Whichever path you took, persist the resolved name back to scrutineer so the next run and the UI can find it without re-probing:

```
PATCH {api_base}/repositories/{repository_id}
Authorization: Bearer {token}
{"fork": "{fork_org}/{fork_name}"}
```

## 2. Enable private vulnerability reporting on the fork

Use the dedicated endpoint; the `security_and_analysis` block on `PATCH /repos/...` accepts the field but does not actually flip it.

```
gh api -X PUT repos/{fork_org}/{fork_name}/private-vulnerability-reporting
```

A 204 means it is on. Confirm with `gh api repos/{fork_org}/{fork_name}/private-vulnerability-reporting` which returns `{"enabled": true|false}`. A 422 usually means the org has it forced on or off at the org level; record that in `notes` and carry on.

## 3. Record the scan on the fork

Record when scrutineer last looked at this repository, regardless of whether there were findings, as a git note on the scanned commit and push it to the fork. The note lives under `refs/notes/scrutineer` so it does not collide with anything upstream uses.

```
HEAD=$(git -C ./src rev-parse HEAD)
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
git -C ./src notes --ref=scrutineer add -f -m "scrutineer: scanned $NOW at $HEAD (scan {scan_id})" "$HEAD"
git -C ./src push -f "https://github.com/{fork_org}/{fork_name}.git" refs/notes/scrutineer
```

If the workspace clone is shallow `git push` may need `git -C ./src fetch --unshallow` first; only do that if the push is rejected for shallow reasons. If the push fails for any other reason (branch protection on notes refs, auth), record the error in `notes` and carry on — the note is a convenience, not a hard requirement.

## 4. File draft advisories for findings

Fetch the repository's findings: `GET {api_base}/repositories/{repository_id}/findings` with `Authorization: Bearer {token}`. File an advisory for every finding whose `status` is one of `new`, `enriched`, `triaged`, or `ready` — that is, anything that has not already been reported upstream or closed out. Skip `reported`, `acknowledged`, `fixed`, `published`, `rejected`, and `duplicate`; record those under `"skipped_advisories"` with the status as the reason. If nothing is left, record `"advisories": []` and skip to step 5.

For each remaining finding fetch the full record (`GET {api_base}/findings/{id}`) so you have `disclosure_draft`, `cvss_vector`, `cwe`, `affected`, and `title`.

Before filing, list the advisories already on the fork so re-runs do not duplicate:

```
gh api repos/{fork_org}/{fork_name}/security-advisories --paginate --jq '.[].description'
```

Every advisory this skill files carries a `[scrutineer-finding:{finding_id}]` marker on its last line (see below). Skip a finding whose marker already appears in any existing description; record it under `"skipped_advisories"` with reason `"already filed"`. Do not dedup on summary/title — distinct findings can share a title.

For each remaining finding, build the request body and create a draft repository security advisory on the fork. Use the admin create endpoint, not `/reports` — `/reports` is for external reporters and is rejected when the caller is a repo admin, which we are.

```
gh api -X POST repos/{fork_org}/{fork_name}/security-advisories --input ./advisory-{finding_id}.json
```

The body shape is the GHSA create schema:

```json
{
  "summary": "<finding.title>",
  "description": "<finding.disclosure_draft>",
  "severity": "<critical|high|medium|low, lowercased from finding.severity>",
  "cvss_vector_string": "<finding.cvss_vector, omit severity if this is set>",
  "cwe_ids": ["CWE-79"],
  "vulnerabilities": [
    {"package": {"ecosystem": "<ghsa enum>", "name": "<pkg>"}, "vulnerable_version_range": "<finding.affected>"}
  ]
}
```

Build `vulnerabilities` from `GET {api_base}/repositories/{repository_id}/packages` using the same ecosystem mapping the disclose skill uses (rubygems, npm, pip, maven, nuget, composer, go, rust, erlang, actions, pub, other). If the repository has no packages, send `"vulnerabilities": [{"package": {"ecosystem": "other", "name": "{owner}/{repo}"}}]` — the endpoint requires at least one entry.

`vulnerable_version_range` must be a bare constraint string. `finding.affected` is analyst prose; normalise it before sending:

- drop anything in parentheses and any repeated package name

From lukehinds/scrutineer-attest-test, MIT.

More from lukehinds/scrutineer-attest-test

Signals

Stars
0
Forks
0
Open issues
0
Last commit (this folder)
Jun 11, 2026 (4 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from lukehinds

Cite this page

fork skill. Agent Mart. https://agentmart.dev/skills/lukehinds-fork (last updated 2026-10-24)