Commit Graph

142 Commits

Author SHA1 Message Date
kz-tob 82a77a25d9 Merge branch 'main' into kumarak/codeql-cpp-data-extensions 2026-08-03 12:16:19 -04:00
Eric Kilmer ec2450d05e Trim dwarf-expert: single-file skill, effort level, contract test (#223)
* Trim dwarf-expert: single-file skill, effort level, contract test

- Consolidate SKILL.md from four files into one (115 lines); delete
  reference/. Cut generic behavior rules, duplicate When-to-Use
  sections, a 9-line readelf reference hop, and an ASCII decision
  tree; fix five typos.
- Fix --lookup=<offset> misuse carried over from the original: DIE at
  a section offset is --debug-info=<offset>; --lookup takes a program
  address. Verified live against llvm-dwarfdump.
- Drop the invented v3-v5 version scoping from the skill, plugin.json,
  marketplace.json, and both READMEs. Version-specific judgment that
  earned its place (the -gdwarf-N pin inference, v2 surface forms)
  lives in the Verifying section.
- Frontmatter: add effort: medium, rewrite the trigger description,
  extend allowed-tools with Write/Edit/WebFetch.
- Add tests/test_skill_contract.py (stdlib + pytest): every dwarfdump
  flag documented in SKILL.md must exist in a live llvm-dwarfdump
  (>= 19, the verified floor for --error-display/--verify-json), plus
  a frontmatter contract check. Zero extracted flags or a missing
  tool fails rather than skips.
- CI: python-tests installs llvm-19, falling back to the default llvm
  on future runner images.
- Bump version 1.0.1 -> 1.1.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review: fence-aware extraction, capability-gated resolver

- body_sections() no longer strips fenced blocks from section text:
  fences are ignored only for heading detection, so flags documented
  inside examples are extracted and verified. New unit test covers
  both properties; a fenced --bogus-flag mutation now goes red.
- Replace the parsed-version LLVM floor with a capability gate: the
  resolver requires --error-display/--verify-json in --help, because
  Apple's LLVM numbering does not track upstream and a numeric major
  is not comparable across toolchains. Failure lists rejected tools
  with their version banners. README wording matches.
- Raise the extraction floor from 10 to 15 (21 flags documented).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: kz-tob <kara.zaffarano@trailofbits.com>
2026-08-03 11:45:58 -04:00
Clinton Thomas 696dee5717 Remove debug-buttercup, re-homed in trailofbits/buttercup (#221)
The skill only makes sense inside the codebase it debugs. It hardcodes
Buttercup's crs namespace, the 13 Redis stream names and 5 consumer groups
from common/queues.py, the app= label selectors from its Helm charts, and
its /tmp/health_check_alive liveness convention. None of that helps anyone
outside that repo, and all of it goes stale when that code changes with no
signal here.

It now lives at .claude/skills/debug-buttercup/ in trailofbits/buttercup,
next to the queue definitions and charts it documents, alongside the
existing buttercup-langfuse skill. Nothing is lost.

Also drops the Infrastructure section from the README, which this was the
only entry under.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Scott Arciszewski <147527775+tob-scott-a@users.noreply.github.com>
Co-authored-by: kz-tob <kara.zaffarano@trailofbits.com>
2026-08-03 10:52:44 -04:00
Eric Quintero 8071528176 Remove seatbelt-sandboxer plugin (#218)
* Remove seatbelt-sandboxer plugin

The skill's central justification was wrong: it taught that `file-read*`
reads from any path, when a filtered `file-read*` is bounded exactly like
`file-read-data`, and it never mentioned that SBPL applies the last
matching rule, so a deny placed above a broad allow silently enforces
nothing. Guidance that is wrong is worse than absent, because it replaces
a correct instinct with a false justification, and `sandbox-exec` settles
any SBPL question locally in seconds for anyone who needs one answered.
With no recorded production use to weigh against four defects found in a
single afternoon, the maintenance cost was not earning its keep.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Update marketplace.json

fix conflict resolution

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: kz-tob <kara.zaffarano@trailofbits.com>
2026-08-03 10:39:06 -04:00
Kevin Valerio 3742e65294 chore(ask-questions-if-underspecified): remove the plugin (#214)
The skill content is untouched since 2026-01-29. The only commits to the
directory since were repo-wide sweeps (formatting in #98, codex UI metadata
in #175), not maintenance.

It also spends a lot of context on something you can get from one English
sentence to Claude. Asking clarifying questions when a request is ambiguous
is native Claude Code behaviour now, through AskUserQuestion, so an 86-line
skill that mostly explains how to format multiple-choice options is paying
context for a built-in.

Knock-on edits: AGENTS.md used this plugin as its Basic reference example,
now git-cleanup, which is a better fit anyway at five files and one
self-contained SKILL.md. let-fate-decide pointed at the skill by name in its
description and its When NOT to Use list, now reworded to plain "ask
clarifying questions"; its description feeds skill triggering, so it gets a
patch bump to 1.2.2.

Co-authored-by: kevin-valerio <kevin-valerio@users.noreply.github.com>
Co-authored-by: kz-tob <kara.zaffarano@trailofbits.com>
2026-08-03 10:01:04 -04:00
kz-tob daa4ad03eb Update CODEOWNERS (#236) 2026-08-03 09:52:44 -04:00
Tarun Bansal 1256982d4d Remove workflow-skill-design plugin (#215)
Co-authored-by: Benjamin Samuels <1222451+bsamuels453@users.noreply.github.com>
2026-07-31 09:41:07 -07:00
AkshayK 7efe99be45 feat(codeql): add C/C++ data extension guidance
Document the C/C++ specifics that fail silently: column 1 is `namespace`
not `package`, pointer arguments need an indirection star, and the
consumed `kind` vocabulary is far smaller than validation accepts. Adds
the C/C++-only allocation/deallocation predicates and a pattern table
for the create-data-extensions workflow.

Verify kinds against both `cpp-all` and `cpp-queries` — scanning the
library pack alone returns only `remote-sink` and would condemn a
working `sql-injection` model as dead.
2026-07-30 17:01:17 -04:00
Samuel Moelius 09dfbd9153 Drop the "When to Use" / "When NOT to Use" requirement (#216)
* Drop the "When to Use" / "When NOT to Use" requirement

* Fix inconsistency in AGENTS.md

* Eliminate `REQUIRED_SKILL_SECTIONS` check in validate_plugin_metadata.py
2026-07-30 11:12:07 -04:00
Dan Guido ca08fc8a91 Commit plugin lockfiles; unblock Dependabot (#213)
* Commit plugin lockfiles so Dependabot can do something useful

The uv ecosystem config added in #206 pointed at four directories that declare
PEP 621 ranges and carry no lockfile. With nothing to pin, Dependabot's only
available action is raising the lower bound of an already-open range — which
changes nothing about what installs and only drops support for older versions.
It opened five such PRs within a minute of #206 merging (#208-#212), all no-ops:
the existing ranges already resolved to exactly the versions being proposed as
new floors. The one directory that did have a lockfile, constant-time-analysis,
produced no PR at all, because there was genuinely nothing to update. That is
the whole diagnosis.

Lockfiles committed for the other four. .gitignore ignored uv.lock globally,
which is why they were missing; constant-time-analysis's was tracked only
because it predates the rule. Now scoped to the root file (ephemeral — there is
no root pyproject.toml) with plugin lockfiles explicitly allowed, matching the
pattern already used for .mcp.json.

Also fixes two bugs #206 introduced:

- The version-increment check failed all five Dependabot PRs, and Dependabot can
  neither bump a plugin version nor label its own PR, so every future dependency
  PR would have been permanently red. Exempted by actor.
- The 'no-version-bump' label was documented in AGENTS.md and wired into
  validate.yml but never created, so the escape hatch did not exist. Created.

* Re-run CI with the no-version-bump label applied

The version-increment check fired on this PR: adding uv.lock under plugins/<name>/
counts as touching those plugins. Correct behaviour — the lockfiles pin exactly
what the existing ranges already resolve to, so nothing changes for anyone
installing these plugins, which is what the label is for. First real use of the
escape hatch created in this same PR.

* Fix the three findings from this PR's review

A local uv setting leaked into all four new lockfiles. /etc/uv/uv.toml on ToB
machine images sets exclude-newer = "1 week", so every lock carried an
[options] block with exclude-newer-span = "P1W" and pinned versions resolved a
week stale — diverging from constant-time-analysis/uv.lock, which predates this
PR and has no such block. Regenerated with UV_NO_CONFIG=1. That cooldown is the
org's supply-chain posture and it belongs in dependabot.yml's
'cooldown: default-days: 7', where it already is; baking it into committed
lockfiles was my environment leaking, not a decision.

"EVERY directory here must carry a committed uv.lock" was enforced by a comment,
which is precisely the anti-pattern AGENTS.md tells people to avoid. Now a
validator check: it parses the uv ecosystem block out of dependabot.yml and
asserts a uv.lock beside each listed directory. Scoped to that block rather than
grepping for '- /plugins/...' so a future ecosystem's paths are not swept in,
and it errors if the block exists but no directories parse out — otherwise the
checker could inspect zero items and report clean, which is the exact failure it
exists to prevent. Three self-test fixtures, and verified by deleting a real
lockfile and confirming CI would go red.

The Dependabot exemption keyed on github.actor, which on a synchronize event is
whoever pushed. A human adding one commit to a Dependabot branch would re-arm
the version check and turn the PR red — making the follow-up bump mandatory
exactly where the comment says it is discretionary. Keyed on PR authorship now.
2026-07-29 20:09:36 -04:00
Dan Guido 8ea3b6a700 Move the contribution checklist into machinery (#206)
* Add validator self-test, structural checks, and make check

The repo documented ~53 rules in AGENTS.md and machine-enforced 6 of them. This
closes the gap for the ones a machine can decide, and adds the guard that keeps
the checkers honest.

New error-level checks (all currently pass, so none of this blocks anyone today):
agent files must use `tools:` while skills use `allowed-tools:` (the loader
silently ignores the wrong key, so the restriction just does not apply);
subagent_type must be namespaced or the dispatch fails at runtime; plugin dir
names kebab-case and <=64 chars; plugin README present, listed rather than
stat'd so `Readme.md` fails on Linux CI the way it should; semver format; the
forbidden runtime sidecars AGENTS.md already banned but nothing checked; and
version-increment against the base branch, which is the gap that let debfb29
ship an allowed-tools fix across 25 plugins that no installed user received.

New warning-level checks, reported but not blocking: the two required SKILL.md
sections, the 500-line limit, and unresolved relative references. 55 warnings
across 40 plugins today, concentrated in testing-handbook-skills and
building-secure-contracts.

The point of the exercise is the three anti-vacuity guards. A checker that has
silently stopped matching reports a clean repo forever, and that failure mode
has shipped repeatedly: `--self-test` builds fixtures and asserts every checker
rejects a known-bad one; a full scan that resolves zero references exits 1
rather than declaring everything clean; and SELF_TEST_MINIMUM fails the
self-test if it runs fewer than 20 assertions, because the self-test is itself a
checker. It currently runs 26.

The reference extractor skips fenced and inline code so that skill-authoring
docs citing example paths do not generate warnings nobody reads.

Makefile mirrors CI as one `make check`. Its RUFF_VERSION must match the
ruff-pre-commit rev, and the self-test asserts that — verified by breaking it.

* Fix CI checks that could pass or fail without inspecting anything

Four of these are the same bug in different places: a check whose empty case is
indistinguishable from success.

- python-tests ran `python3 <file>` per file. A test file with no
  `if __name__ == "__main__"` block exits 0 having run nothing, which reads as
  a pass. All 10 current files happen to comply; nothing enforced it. Now pytest
  per directory, run via `python3 -m` from inside each one to preserve the
  sibling imports these suites rely on, with --import-mode=importlib because
  c-review and rust-review both ship scripts/test_split.py and the default
  import mode collides on the basename. 278 tests now run where the count was
  previously unknown.
- bats used --no-run-if-empty, so a broken glob was a silent pass. This repo
  ships bats suites; finding none is a failure.
- The SKILL.md frontmatter walk printed "All 0 SKILL.md files have valid
  frontmatter" if discovery broke. Now fails on zero.
- zeroize-audit's shell regression suites matched no CI glob and had never run.

Also: the validator self-test runs first, before validation. The hardcoded-path
grep now covers .sh, .bats, .yml and .toml — test fixtures and install scripts
are where absolute paths hide. The personal-email exclusion is anchored; an
unanchored '.git' also dropped any line containing '/github'. The two npm CLI
installs are pinned rather than @latest, which zizmor flagged and which made CI
able to break with no commit.

check_codex_loadability.py: tempdir cleanup raced the codex app-server and threw
`OSError: [Errno 39] Directory not empty: '.git'`, failing the job after every
loadability check had passed (seen on PR #148 today). A teardown race must not
be reported as a validation failure.

* Wire validators into pre-commit; fix two dead Dependabot entries

pre-commit: the three .github/scripts validators were CI-only, so the first
signal a contributor got was a red check after pushing — AGENTS.md asked people
to remember to run them by hand. Now they run locally, with the validator
self-test scoped to fire only when the validator itself changes. Adds
actionlint, zizmor, check-toml, check-merge-conflict, and detect-private-key.

detect-private-key earns its place: there is no secret scanning here at all,
which is how a live API key sat in an untracked config file in a working tree
this morning without anything noticing.

Markdown linting is deliberately absent, with the measurement recorded in the
config so the next person does not have to redo it: markdownlint reports ~12,400
violations across this repo (7,282 MD013 line-length alone). It would land
either permanently red or with so many rules disabled that it checks nothing.

Dependabot had two defects that made it quieter than it looked. The `pip` entry
at / had no manifest to resolve — there is no root pyproject.toml and uv.lock is
gitignored — so it reported nothing, indefinitely. And two script directories
with real dependencies were uncovered: trailmark's slicing-code-context
(trailmark>=0.5,<0.6) and yara-authoring's rule scripts (yara-x>=0.10.0).
Switched to the uv ecosystem per the house standard, grouped minor/patch so
majors still get their own CI run.

* Add automated PR review, inert until a key is configured

Two tiers: fast (effort low, every push, sticky comment) and deep (effort xhigh,
on a deep-review label). Per-job permissions with an empty workflow-level grant;
concurrency keyed per tier so a routine push cannot cancel an in-flight deep
review — GitHub will not re-fire `labeled` for a label already present, so that
would leave a PR sitting labeled with no review, looking reviewed.

The prompt is the substance. It forbids pre-filtering: current models follow
"only report high-severity issues" literally, investigating fully and then
declining to report what they judge below the bar, which reads as a capability
regression but is a prompt bug. It asks for everything ranked P1-P4 with a
concrete failure scenario each, and filters downstream. It also names the five
defect classes that actually reach main in a repo of markdown that instructs a
model, rather than asking for generic code review.

There is no ANTHROPIC_API_KEY secret on this repo, so every review step is gated
on the secret being present. Until someone adds it these workflows check out the
code and do nothing — they do not fail. A review workflow that goes red on every
PR for want of a credential teaches people to ignore red checks.

Fork review is a separate file with a separate decision attached. It needs
pull_request_target, because under `pull_request` a fork PR gets a read-only
token and the job could not post its comment at all. The usual exploit path is
closed by a maintainer-only label gate, a checkout pinned to the SHA as of the
labeling event (so a later force-push does not change what is reviewed), and a
tool allowlist with no general Bash, so fork code is read and never executed.
The residual prompt-injection risk is documented in the file header. Deleting
that one file costs nothing but fork review.

* Replace the PR checklist with make check

Deletes the 20-item PR checklist. Current model guidance is explicit that
verification scaffolding of that shape degrades output rather than improving it,
and that removing it costs no capability — so the response is to move each check
into machinery, not to restate it louder.

Every item that could be mechanized landed in the validator first, with a
fixture, before this prose was allowed to go. What replaces the checklist is two
lists: what the validator enforces so you do not have to, and what no tool can
check. The second list is the one that matters — whether the description
actually triggers, whether the version bump is the right size, whether the
README row is in the right section (the validator only checks the plugin appears
somewhere in that file).

Also corrects the frontmatter example, which showed `allowed-tools` as a YAML
list. Every SKILL.md in the repo uses the space-delimited form; debfb29
converted them deliberately. The doc was the outlier, and it caused a false
finding during review of #192. Agent files genuinely do use a YAML list, under
the `tools` key — both forms are now shown side by side with the reason the
distinction matters.

Two new sections. "Scripts a plugin ships" leads with the rule this whole change
is built around: a checker that inspects zero items must fail, not pass, with
the three worked examples. "Working effectively in this repo" covers effort
sweeps, a subagent cap (current models over-delegate, which is a reversal from
the previous generation), not adding verification scaffolding to prompts, and
not telling a reviewer to pre-filter — that last one reads as a capability
regression and is a prompt bug.

Scopes the claude-code-guide line to questions that cannot be answered by
reading this repo, and adds .opencode/ to the banned sidecar list now that the
validator enforces it.

* Fix three bugs CI caught in the guardrails themselves

All three were mine, and the first is the one that mattered.

1. The version-increment check ran against every plugin, not just the ones the
   branch touched — so it demanded a version bump from all 42 plugins on a PR
   that changed no plugin at all. Now scoped to plugins with file changes
   between the base ref and HEAD. Added three self-test assertions covering it
   (touched plugin errors, untouched plugin does not), and verified by reverting
   the fix and confirming the self-test goes red. The check had no coverage
   before, which is exactly why it shipped broken.

2. The new pre-commit hooks invoked `uv run`, which is not installed in the
   Pre-commit CI job. The validator declares no dependencies, so plain python3
   is correct and one less thing to install.

3. The review workflows called `claude` without installing it. Added a pinned
   install step, matching how validate.yml installs the same CLI.

Also corrects a factual claim in both review workflow headers. I wrote that they
were inert for want of an ANTHROPIC_API_KEY, based on `gh secret list` returning
empty — but that only lists repository secrets. An organization-level key is
visible here, so the fast tier is live on merge. The headers now say so. The
deep and fork tiers still cannot fire until their labels are created.

* Fix the findings from this PR's own automated review

The review posted on #206 found eight issues. Seven were real. Working through
them in severity order:

P1 — deleted claude-review-fork.yml. It checked out the fork tree and then ran
this repo's review script *from that tree*, so the script itself, and any
CLAUDE.md or .claude/hooks sitting beside it, was fork-authored and executed
with the org API key in the environment. My header claimed "fork code is read,
never executed" and that was simply wrong; the SHA pin and the tool allowlist do
not touch that path. Doing it safely means checking out base into the workspace
and the fork commit into a subdirectory, which is deliberate work rather than a
footnote to this change. Fork PRs get no automated review for now, and
claude-review.yml explains why.

P2 — the prompts instructed `gh pr comment --body-file <file>` while the tool
allowlist has no Write and no general Bash, so there was nowhere to put a file.
The reviewer hit this and fell back to `--body-file -`; since a give-up does not
fail the step, the failure mode was a green check with no review. Now uses a
heredoc on stdin. The deep tier also told the model to run the scripts a PR adds,
which its allowlist cannot do; it now says so explicitly.

While fixing that: both tier heredocs were unquoted so `${PR_NUMBER}` would
interpolate, which means backticks in the prompt body were command substitution.
Quoted them and moved substitution out to parameter expansion afterwards.
shellcheck caught this.

P2 — `no-version-bump` was a phantom feature: named in the validator's error
message and in AGENTS.md, read by nothing. Implemented via --allow-no-bump,
wired to the label through validate.yml.

P2 — AGENTS.md claimed both loadability checks run in `make check`. They do not
and cannot; they need two CLIs installed. It now says what runs locally, what is
CI-only, and how to run the loadability checks by hand.

P3 — the new shell-suites discovery reintroduced the exact bug this PR exists to
remove: it printed "No shell regression suites found" and exited 0, and used
`**` without globstar so it only ever matched one directory level. Now find-based
and fails on empty. It is a Makefile target but not part of `make check`,
because zeroize-audit's suite pipes to `python3 -` which the modern-python
shim rejects — filed as #207.

P3 — a failed `git diff` returned an empty changed-plugin set, silently
disarming the version check for every plugin. Now raises.

P3 — the `/home/user/` exclusion was a content filter applied across all of
plugins/, so a skill legitimately documenting that path would be dropped from
the results. Scoped to the shim bats fixtures that need it.

Not fixed, deliberately: the reviewer noted `_check_ruff_parity` covers one
pinned version. True, and it is the only version both files pin.

* Fix the second review pass: the review job could not detect its own silence

The marquee one: claude_review.sh ended with `claude --print` and nothing else,
so if the model finished without calling `gh pr comment` — a denied tool, a hit
timeout, or it simply summarising instead of posting — the script exited 0 and
the job went green with no review attached. That is defect class 1 from the
prompt this very script ships, in the script that ships it. It now timestamps
before the run and fails if no comment was created or updated since.

_check_ruff_parity returned None (= pass) when the Makefile or pre-commit config
was missing, while still counting toward SELF_TEST_MINIMUM. A vacuous pass
inside the anti-vacuity harness. Now returns an error string.

The scoping claim in AGENTS.md and the Makefile was backwards. I wrote that CI
scopes the validator to changed plugins while local scans everything, making
local a strict superset. Both scan everything; only the version-increment check
is scoped, and it is the one check CI runs that local cannot — so local is not a
superset at all. Corrected in both places.

README said `make check` "runs everything CI runs" and the Makefile echoed "this
is what CI will run". Neither is true: it omits both loadability checks, the
version-increment check, and every pre-commit hook except ruff/shellcheck/shfmt.
Both now say what they actually cover. AGENTS.md already had this right.

Stale count in a pre-commit comment ("these three" preceding two hooks).

Accepted without change, with reasoning: the reference resolver matches any file
in the plugin, so a link to a file that exists under a different skill resolves
when it should not — pinning a base directory produces a flood of false
positives, and the looser check is still worth having. The subagent-dispatch
check only knows its own plugin's agents, so a bare cross-plugin reference is
missed; catching that needs a repo-wide agent map, which is a larger change than
belongs here.

* Fix the third review pass, including two more silent-pass checks

The hardcoded-path step had the defect this PR exists to remove. It was written
as `if grep A | grep -v B | grep -v C`, so the exit status came from the last
`grep -v`. A first-stage failure — plugins/ renamed, a grep built without -P —
produced no output, exited 2, and the step printed "No hardcoded user paths
found" while inspecting nothing. Now counts the files it scanned, fails if that
is zero, and checks grep's own status via PIPESTATUS rather than the pipe's.

The self-test fixture named "empty scan returns non-zero" was passing for the
wrong reason: it deleted the plugin's files but left the directory, so
scan_plugins_directory still returned {"demo"} and the non-zero came from the
missing-README error. The guard it claimed to cover was never exercised. It now
rmtree's the directory and asserts the fixture actually emptied plugins/ before
relying on it. Same class of bug as everything else here, one level up.

Concurrency: every `labeled` event that was not `deep-review` resolved to the
`fast` key with cancel-in-progress. Adding `dependencies` mid-review cancelled
the running review and then skipped both jobs, leaving a cancelled check, no
review, and no event that would re-trigger one until the next push. Each label
now gets its own key.

The version-increment check read the old version at `base.sha` while
changed_plugins diffed `base...HEAD`. Those disagree once anything lands on main
after a branch forks, so a PR could fail for not out-bumping a sibling it never
saw. Both halves now use the merge base, and the error message says to rebase.

Smaller: the sidecar ban only matched `.agents/plugins/marketplace.json` while
AGENTS.md bans `.agents/` — widened, with fixtures for it and for
`plugins/*/.codex-plugin`, neither of which the harness covered. `make shell`
globbed only plugins/, so the one new shell script in this PR went unchecked
locally. The deep job's fork exclusion is now explicit rather than relying on
secrets being unavailable to fork events. changed_plugins' docstring said
working tree; it compares commits.
2026-07-29 19:52:28 -04:00
Evan Sultanik 0cb5f95840 Add open-sourcing plugin (#202)
* Add open-sourcing plugin

Skill for preparing a repository for public release, generalized from
the internal open-sourcing guide. Generic workflow (secrets audit,
licensing, docs, CI, release automation) with a Trail of Bits policy
overlay loaded via git-remote/committer-email detection. Includes
per-language packaging references and readiness-check scripts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Modernize open-sourcing skill to current toolchain practice

Align guidance with the current cookiecutter-python toolchain and 2026
ecosystem state, verified against primary sources: respect-existing-
tooling principle (warn on stale toolchains, adopt modern defaults only
when absent), SLSA provenance job in the PyPI release workflow, ty
pre-1.0 pinning caveat, uv audit/interrogate, rulesets wording,
Dependabot grouping and cooldown, and a new JavaScript/TypeScript
reference covering npm trusted publishing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-07-29 17:07:28 -04:00
Evan Sultanik 65ecafa7ec Add github-triage plugin (#192)
* Add github-triage plugin

Triages open GitHub issues for the current repository via the gh CLI:
closes already-resolved issues with comments citing the resolving PR or
commit, cross-links issues with pending fix PRs, and assigns local-only
priority and change-size (size/XS–XXL) estimates for everything else.

All GitHub writes are gated behind a single review-and-iterate approval;
priority/effort are never posted. Registers the plugin in the marketplace,
README, and CODEOWNERS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Add optional PR triage to github-triage skill

Before issue triage, optionally clear open PRs (so merges feed the
"already resolved" issue check):
- incrementally merge allowlisted bot PRs and maintainer-approved PRs,
  one at a time, re-verifying mergeability/CI before each and confirming
  each landed;
- spawn one read-only review subagent per never-reviewed PR, saving each
  review to github-pr-<number>-review.md locally (never posted).

PR readiness uses verified gh --json semantics: mergeStateStatus==CLEAN
(MERGEABLE alone is insufficient; UNKNOWN is never-merge), per-node
statusCheckRollup (CheckRun status+conclusion vs StatusContext state),
author.is_bot + trusted allowlist, and latestReviews state+authorAssociation
rather than the branch-protection-driven reviewDecision. All merges gated;
never --auto/--admin/force.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Fix github-triage bugs found in end-to-end dry run

Validated the skill against trailofbits/graphtage (real issues + PRs),
which surfaced four bugs:

- gh repo view takes the repo positionally, not -R; fixed the
  default-branch and merge-method lookups.
- CI readiness treated NEUTRAL/SKIPPED checks as failures, wrongly
  blocking mergeable Dependabot PRs (CLEAN with a NEUTRAL CodeQL run).
  Reworked to "CI not blocking" (hard failures + pending only), with
  mergeStateStatus==CLEAN as the authority.
- Not-ready bot PRs were routed to the review-subagent bucket; bots are
  now excluded so they fall to Needs work.
- Bot allowlist now normalizes gh's author.login renderings
  (app/dependabot and dependabot[bot]) so bot detection actually matches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-07-29 17:05:09 -04:00
Scott Arciszewski 841bffed0d trailmark: add v0.4/v0.5 support and graph-assisted security workflows (#183)
* trailmark: update skills to use v0.4.0 features

* fix: resolve code review findings for PR #183

Redraws the version boundary to match the actual Trailmark release
history, verified against the v0.2.0/v0.2.1/v0.2.2/v0.3.1/v0.4.0 tags
of trailofbits/trailmark:

P1 (misclassified APIs, fixed):
- ancestors_of(), reachable_from(), entrypoint_paths_to(),
  nodes_with_annotation(), clear_annotations() and the diff/entrypoints
  CLI exist since v0.2.0 — moved from the v0.4+ list to the v0.2-safe
  baseline; removed needless hasattr() gates and degraded fallbacks
- supported_languages()/detect_languages() (trailmark.parse) are 0.3+
  modules, not v0.2-safe — annotated as such
- CLI --version/version were added in 0.2.2, not 0.4 — documented as
  0.2.2+ and version-probe failure semantics clarified
- graph-evolution/SKILL.md reverted to main: native diff has existed
  since v0.2.0 with identical args, so the 0.2.x-fallback rewrite was
  built on a false premise (also resolves the quality-checklist
  contradiction flagged in review)

P3 (fixed): lexical version comparison hazard noted; stale
diagramming-code checklist label; README baseline list now defers to
the SKILL.md Version Gate instead of keeping a second divergent copy

Dismissed: 'diff CLI signatures contradict' (both forms valid — before/
after positionals accept paths or git refs, --repo/--json exist since
0.2.0); 'subgraph_edges has no edge_kinds param' (v0.4.0 signature has
edge_kinds keyword); 'diagram.py fallback broken on 0.2.x'
(trailmark.diagram module exists in 0.2.x; only the CLI subcommand is
new); 'phantom diff_against()' (real, v0.2-safe, now in baseline)

Verified: check_claude_loadability.py, check_codex_loadability.py,
pre-commit hooks pass; all SKILL.md files under 500 lines

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* trailmark: add assurance workflow skills (#187)

* trailmark: add assurance workflow skills

* fix: drop hasattr gates on v0.2-baseline query APIs

entrypoint_paths_to() and reachable_from() are in the v0.2-safe
baseline, so the hasattr fallbacks were dead code — and the
entrypoint_paths_to fallback indexed attack_surface() entries with
entry["name"] instead of node_id, which would raise KeyError.
Addresses PR #187 review feedback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* fix(trailmark): make detect_languages import v0.2-safe in operational skills

The trailmark-summary and trailmark-structural skills claimed v0.2-safe
workflows but unconditionally imported trailmark.parse, a 0.3+ module.
detect_languages() has existed in trailmark.query.api since v0.2.0 (kept
as a deprecated alias in 0.3+), so gate the import with a fallback
instead of relabeling the skills as 0.3+. Version Gate docs updated to
document the v0.2-safe import path; supported_languages() remains 0.3+
with no 0.2.x equivalent.

Verified against trailmark v0.2.0 source (fallback branch) and the
current 0.4 line (canonical branch).

Addresses review feedback on PR #183.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* trailmark: document and enable v0.5.0 features

Trailmark 0.5.0 adds a PostgreSQL-oriented sql parser (node kinds
schema/table/view/procedure), the stable .trailmark/links.toml
configuration for cross-language/FFI/RPC/external links, repository
links/proxies/type_uses edges on single-language parses, Solidity
entrypoints from parser metadata (visibility/mutability/overridden-by
attributes), node attributes in attack_surface() entries, TypeScript
constructed-receiver resolution, and C# file-scoped namespaces.

Updates the Version Gate with a v0.5+ section and a structural probe
('SCHEMA' in NodeKind.__members__ — 0.5.0 adds no new QueryEngine
methods, so hasattr() cannot detect it), adds a Repository Links
section and cross-boundary query recipe, extends the parser list and
graph model docs, notes the reachability-vs-taint limitation, and
threads the 0.5 output additions through trailmark-structural and
audit-augmentation. Plugin version 0.9.0 -> 0.10.0.

All version claims verified against trailofbits/trailmark v0.2.0 and
v0.5.0 builds, including a live links.toml materialization test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* trailmark: add slicing-code-context skill (#203)

Adds a skill for delegating focused code tasks to constrained or locally
hosted models using bounded, graph-informed Trailmark source packets:

- scripts/build_slice_packet.py: deterministic PEP 723 packet builder
  (Trailmark 0.5.x) with five selection modes, whole-unit budget admission,
  explicit omission accounting, path-traversal rejection, an embedded
  untrusted-source notice, and structured JSON errors (26 tests, including
  a real Trailmark integration test)
- agents/code-slice-worker.md: repository-tool-free Haiku worker returning
  a source-cited JSON contract
- SKILL.md + references/slice-packet.md: coordinator workflow, packet and
  worker response contracts, and validation rules

Reviewed with a multi-agent Claude pass and two Codex passes; fixes from
those reviews are included (doc/selection-order reconciliation, relationship
deduplication, line-range anchors no longer expand to full nodes in
path/entrypoint modes, background-safe worker toolset, structured io_error
handling, replacement-packet expansion semantics).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 16:51:40 -04:00
dm 101a102069 Add vulnerability triage brocards skill (#201)
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-07-29 16:49:29 -04:00
dependabot[bot] 587160fccc build(deps): Update opencv-python-headless requirement (#198)
Updates the requirements on [opencv-python-headless](https://github.com/opencv/opencv-python) to permit the latest version.

Updates `opencv-python-headless` to 5.0.0.93
- [Release notes](https://github.com/opencv/opencv-python/releases)
- [Commits](https://github.com/opencv/opencv-python/commits)

---
updated-dependencies:
- dependency-name: opencv-python-headless
  dependency-version: 5.0.0.93
  dependency-type: direct:production
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-07-29 16:26:42 -04:00
dependabot[bot] 83f9240beb build(deps): Bump the all group across 1 directory with 2 updates (#204)
Bumps the all group with 2 updates in the / directory: [actions/checkout](https://github.com/actions/checkout) and [actions/setup-python](https://github.com/actions/setup-python).


Updates `actions/checkout` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1)

Updates `actions/setup-python` from 6.2.0 to 7.0.0
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/a309ff8b426b58ec0e2a45f0f869d46889d02405...5fda3b95a4ea91299a34e894583c3862153e4b97)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
- dependency-name: actions/setup-python
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-07-29 16:26:22 -04:00
William Tan 3b316e6ac7 fix(modern-python): suggest exact uv run python so shim advice works outside projects (#196)
* fix(modern-python): suggest exact `uv run python` so the advice works outside projects

The python/python3 shim suggested `uv run $cmd ...`, echoing back whichever
name was invoked. For `python3` that advice is self-defeating on machines
with no uv-managed interpreters: uv resolves the `python3` command through
an ordinary PATH lookup, which hits the shim again and fails with the same
suggestion. uv special-cases the exact command name `python` (uv >= 0.4.0)
and executes its resolved interpreter directly, so always suggesting
`uv run python ...` works everywhere.

Reproduced on stock Debian + uv 0.11.27 (apt python3, zero managed
pythons, no project): `uv run python3 script.py` fails via the shim while
`uv run python script.py` succeeds, across script/-c/-m/REPL forms.

Reported in #195.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(modern-python): satisfy shellcheck SC2016 in new bats assertions

Escaped backticks in double quotes instead of literal backticks in
single quotes, which shellcheck flags as a possible unintended
non-expansion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(modern-python): requote shim suggestions and carry all arguments through

Review findings on #196: the -m branch interpolated only the module name,
so `python -m http.server 8000` suggested a command missing the port, and
`${*}` flattened arguments without quoting, so `python -c 'print(1+1)'`
suggested a command that is a bash syntax error if run verbatim (plus a
trailing space inside the backticks for bare invocations). Both branches
now build the suggestion from %q-requoted arguments, with regression tests
for each case.

Also consolidates the exact-`python` rationale into a single canonical
copy in the shim's header comment; README, setup-shims.sh, and the bats
file now point there instead of paraphrasing it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 15:16:05 -04:00
Andrea Cappa (zi0Black) cfe5d7b161 Rust review plugin (#178)
* rust-review: add Rust security review plugin

Add the rust-review plugin: a comprehensive Rust security review skill
with clustered finders covering memory safety, concurrency/data races,
panic-induced DoS, FFI/cross-language boundaries, error handling,
resource handling, async runtime, and static hygiene.

Includes worker, dedup-judge, fp-judge, and planner agents, SARIF
generation with rule descriptions and regression tests, deterministic
cluster chunking, and Codex skills mapping. Versioned at 1.0.0 and
registered in the marketplace, CODEOWNERS, and root README.

* c-review: backport rust-review protocol fixes and planner chunking

Port the language-agnostic fixes made while building rust-review (which
was ported from c-review) back into c-review:

- worker/fp-judge: force findings, coverage gate, and REPORT.md to disk
  via Write instead of returning content in the reply (orchestrator
  context-bloat hardening); add a pre-complete file-existence check.
- worker: move the cache-primer block below the normal self-check and
  pre-work budget so a non-primer worker does not start under a global
  "no tool calls" rule.
- planner: add --max-passes-per-worker (default 4) with deterministic
  split_oversized_clusters chunking; skill passes the flag and documents
  the chunked-subset worker rule.
- scripts: add test_split.py and test_generate_sarif.py regression
  tests. The SARIF test caught a missing RULE_DESCRIPTIONS entry for
  uninitialized-data, now added.

Bump c-review to 1.2.0.

* c-review/rust-review: validate artifacts, index-aware SARIF, protocol cleanups

- Add validate_artifacts.py (+ tests) to both plugins to check worker
  shard, coverage, and finding files before accepting completions.
- generate_sarif.py now reads the canonical findings-index.txt when
  present, falling back to findings/*.md only if the index is absent.
- Merge the worker step-6 verification paragraphs and drop orchestrator
  -internal Phase 7 / plan.json jargon in favor of worker-facing stakes.
- Tighten uninitialized-read-finder guidance: primitive integers still
  require initialization.

* rust-review/c-review: per-cluster max_passes_per_worker override

Lets output-heavy clusters declare a smaller manifest-level
max_passes_per_worker so each expensive pass group gets its own worker,
validated by a single shared cluster_max_passes_per_worker helper and
honored by split_oversized_clusters via an explicit override (0 is
rejected rather than silently falling back to the global cap). rust-review
opts in concurrency-locking and recursion-dos; c-review ports the
capability for parity. validate_artifacts now accepts grouped or repeated
--claimed-count values.

* rust-review: broaden bug-class coverage with capability-gated clusters

Add layout-safety, input-os-safety, and info-disclosure clusters behind new
has_packed_repr / has_fs_io capability gates so packed-repr, path, and
pointer-exposure passes only run where they apply, and gate unsafe-only passes
behind has_unsafe to cut noise on safe crates.

Extend existing clusters with new bug classes: RefCell double-borrow panics,
unflushed BufWriter, string-comparison bypasses, serialize_struct mismatches,
nondeterminism, in-collection key mutation, and destructor-skip cleanup leaks.

Fix detector regexes that missed or over-matched real Rust (packed-field
borrows, RefCell try_borrow_mut, HashMap substrings, path push, packed inner
attrs, fs/path probes) and add a regression test pinning them to snippets.

* fix dedup

* safety-net check for REPORT.md

* on-disk data -> shards reconciliation

* on-disk data -> shards reconciliation - v2

* ls -> glob

* memory-safety gate

* path validation

* fix numbers/counting

* rm PACKEDREF from FFI cluster prompt, it is in layout-safety

* fix unsafe-boundary count

* minor fixes for prompts

* do not filter unknown-severity findings, just mark them as such

* fix minor behavior changes in worker

* Correctness:
- generate_sarif: clamp startLine >=1 (`:0` produced schema-invalid SARIF)
- generate_sarif: don't drop a judged survivor with blank severity
- dedup-judge: Tier-2 carry-forward so a primary can't be demoted/orphaned
- dedup-judge: crash-recovery unions shards with findings/*.md (empty-shard trap)

Robustness:
- generate_sarif: skip frontmatter-less files; add originalUriBaseIds

Contracts:
- SKILL: gate dedup-judge before fp-judge (prevent concurrent-spawn race)
- worker: verbatim coverage cells; sub_prompt_paths omitted-not-empty;
  skip_subclasses reserved; Codebase comma format

* improve prompts regexes, add missing deconflictions

* prompt factual fixes

* fix dozen of small prompt inconsistencies and add missing sections

* more prompt fixes, fix retry guard in SKILL, small fixes in agents

* dozen more small fixes

* final regex fixes

* fixes from rust to c-review

* agents cannot use write tool for reports (strange cc limitation) - bypass via bash

* spawnings agents is capped to 20 - explicit handling for that

* fix glob -> read (glob is blocked for agents that has also bash)

* fix regex patterns to work with grep

* soften output requirements - they were violated anyway

* consolidated clusters are no longer chunked — one worker owns the whole cluster, builds its shared Phase-A inventory once, and runs every phase

* fix judge finding counting and low-severity guidance

* fix metadata

* small fix for skipped findings

* Carry forward guard for `also_known_as` bucket

* Gracefully handle parse_frontmatter error

* Extend has_ffi coverage

* Broader gate for has_concurrency

* Update FFI-safe layout regex to support C, C+packed, and C+u32 in unsafe-boundary and dyn-trait-ffi-finder prompts

* Small refine of regex patterns

* Improve regex patterns for recursive type detection to include Mutex and RwLock

* rm global .codex/rust-review

* backport fixes to c-review

* merge changes

* Backport SARIF merge-survivor + malformed-frontmatter guards to c-review, mark missing locations, fix prompt-regex test extractor, and harden planner/validator scripts across both review plugins

* fix pytest

* fix global gitignore, adds / and ruff_cache

* small fixes from pr-review

* small fixes from pr-review - 2

* fix copilot finding

---------

Co-authored-by: GrosQuildu <e2.8a.95@gmail.com>
2026-06-30 11:14:46 -04:00
dependabot[bot] 39e10bd31e build(deps): Bump actions/checkout from 6.0.3 to 7.0.0 in the all group (#191) 2026-06-24 14:00:52 -04:00
Jay Little ff4162dcb9 Update fp-check with links and best practices update (#189) 2026-06-21 22:28:34 -04:00
jonnydevs c070b9b588 fix(fp-check): use correct JSON response format in stop hooks (#129)
* fix(fp-check): use correct JSON response format in stop hooks

Prompt-type stop hooks must respond with JSON. The previous prompts
instructed Claude to return plain text ('block' or 'approve'), causing
'Stop hook error: JSON validation failed' on every session end.

Updated both Stop and SubagentStop hook prompts to respond with:
- {"decision": "block", "reason": "..."} to prevent stopping
- {} to allow stopping (omitting decision field per Claude Code docs)

Bug discovered by Claude while debugging the JSON validation error
during active use of the fp-check skill.

* fix: use documented ok/reason schema for prompt hooks, bump to 1.0.2

Per https://code.claude.com/docs/en/hooks.md (Prompt-based hooks >
Response schema), prompt hooks must respond {"ok": true} to allow or
{"ok": false, "reason": "..."} to block — not {"decision": "block"}
or {}. Also bump to 1.0.2 since main already shipped 1.0.1 without
this fix; clients only update when the version increases.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 15:41:52 -04:00
Matthew Kern 64a8c3f00b Update second-opinion Codex model to gpt-5.5 (#163)
* Update second-opinion Codex model to gpt-5.5-codex

Bump primary model from gpt-5.3-codex to gpt-5.5-codex and fallback
from gpt-5.2-codex to gpt-5.4-codex. Plugin version 1.6.0 → 1.7.0.

* fix: correct Codex model name from gpt-5.5-codex to gpt-5.5

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-06-10 15:41:40 -04:00
Jamie Reid 5577119331 fix(semgrep-rule-creator): correct 404ing semgrep-docs links (#179)
* fix(semgrep-rule-creator): correct 404ing semgrep-docs links

The semgrep-docs repo migrated these writing-rules pages from .md to
.mdx, so the WebFetch links in SKILL.md were returning 404. Update the
five affected links to their .mdx paths (pattern-syntax was already
.mdx). All seven links now return HTTP 200.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Bump version to 1.2.2 in plugin.json

* Update semgrep-rule-creator version to 1.2.2

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: ahpaleus <38883201+ahpaleus@users.noreply.github.com>
2026-06-10 15:34:58 -04:00
dependabot[bot] c910ecf739 Bump actions/checkout from 6.0.2 to 6.0.3 in the all group (#182)
Bumps the all group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 6.0.2 to 6.0.3
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/de0fac2e4500dabe0009e67214ff5f5447ce83dd...df4cb1c069e1874edd31b4311f1884172cec0e10)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-10 15:34:45 -04:00
Lixin2026 d5fe2e6a78 feat(codex): add UI metadata for skills (#175)
* feat(codex): add skill UI metadata

* Use official Trail of Bits logo

* fix: resolve code review findings for PR #175

Codex silently drops the icons as authored: its loader
(codex-rs/core-skills resolve_asset_path) requires icon paths
containing '..' to resolve under <plugin_root>/assets/, and the
repo-root .codex/assets location fails that containment check.
Verified empirically via codex app-server plugin/read: every
iconSmall/iconLarge came back null; only brand_color applied.

P1 fixed:
- Vendor trail-of-bits-mark.svg into plugins/<name>/assets/ for
  all 38 plugins with skills and point every openai.yaml at
  ../../assets/trail-of-bits-mark.svg (the supported plugin-level
  shared asset pattern). Icons now resolve for marketplace
  installs too, since nothing escapes the plugin root.
- Drop the .codex/ additions: .codex/skills/gh-cli/agents/
  openai.yaml resolved nowhere (.codex/skills is not a Codex
  discovery root) and PR #173 removes the whole .codex/ tree

P2 fixed:
- Patch-bump all 38 touched plugins in plugin.json and
  marketplace.json so installed clients pick up the metadata

Verified:
- Static check replicating Codex's resolution algorithm: all 73
  yaml files resolve under their plugin assets/ and exist
- Live codex app-server probe: 71/72 loadable skills report
  resolved iconSmall/iconLarge and brand_color #D83A34
  (claude-in-chrome-troubleshooting fails to load on main due to
  a pre-existing 64-char qualified-name limit, fixed by #173's
  rename; zeroize-audit's manifest mcpServers object is likewise
  a pre-existing Codex incompatibility fixed by #173)
- validate_codex_skills.py, validate_plugin_metadata.py, prek all
  pass

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(codex): use skill-local icon assets

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 12:28:41 -04:00
William Tan f09e5c729a Remove legacy codex compatiblity scripts/shims. (#173)
* Remove legacy codex compatiblity scripts/shims.

Codex supports claude plugins so this shouldn't be necessary.
Add a script to test the plugin loadablility in both claude and codex

* fix: resolve code review findings for PR #173

Review findings addressed (4 reviewers: pr-review-toolkit agents,
Codex gpt-5.3-codex, direct diff review):

P2 fixed:
- Bump versions for the 5 substantively changed plugins in both
  plugin.json and marketplace.json (gh-cli 1.5.0 new skill,
  claude-in-chrome-troubleshooting 1.1.0 skill rename,
  modern-python 1.5.1 / skill-improver 1.0.3 hooks change,
  zeroize-audit 0.1.1 MCP config relocation) so clients pick up
  the changes
- README Codex install: replace unpasteable /plugins slash-command
  block with verified CLI syntax (codex plugin marketplace add)
- check_claude_loadability: parse_json_output now fails fast with
  command context on empty CLI output instead of returning None
- check_codex_loadability: surface skipped RPC error messages in
  timeout failures instead of a bare TimeoutError

P3 fixed:
- Both checkers: error out when marketplace.json lists no plugins
  instead of passing vacuously

Dismissed:
- @latest CLI installs in validate.yml: deliberate; the check
  validates against the clients users actually run
- select.select portability: CI-only script on ubuntu-latest
- Divergent mcpServers validation between checkers: intentional;
  the Codex checker enforces the repo's .mcp.json convention

Verified: ruff, prek, validate_plugin_metadata.py, and both
loadability checks pass end-to-end (39 plugins, 74 skills, 2 MCP
servers load in Claude Code and Codex)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 12:18:09 -04:00
Tim Lander c94841be3d Fix for when CLAUDE_PLUGIN_ROOT contains spaces (#169)
* Fix for when CLAUDE_PLUGIN_ROOT contains spaces

* chore(skill-improver): bump version to 1.0.2 for hooks.json fix

The space-quoting fix to hooks.json is a behavioral change, but clients
only pull plugin updates when the version increases. Bump plugin.json and
the root marketplace.json from 1.0.1 to 1.0.2 (kept in sync) so existing
users actually receive the fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 15:53:26 -04:00
Scott Arciszewski 98b01ec8ff let-fate-decide: improved 12-card spread (100+ bits of entropy) (#166)
* Expand let-fate-decide zodiac spread

* let-fate-decide: address self-review nits

- Compute ENTROPY_BITS from math.log2(math.comb(...)) so the dict cannot
  silently drift if the spread shape changes; test now verifies the formula
  and asserts the 100-bit floor.
- Remove the ambiguous draw() wrapper (list-or-dict return); callers use
  explicit draw_zodiac_spread() / draw_cards() instead.
- Extract _build_house_record() helper to bring draw_zodiac_spread() under
  the 50-line guideline.
- Require --legacy explicitly for the positional count CLI; remove the
  implicit legacy flip when a bare integer was passed.
- Generalize the rank-format test to all four minor suits.
- Document test_reviewed_cards_avoid_unsafe_shortcuts as an exact-string
  regression guard rather than a semantic check.
- SKILL.md: reframe example session as an explicit house-level fragment
  and note the draw agent's bullet output format.
- README.md: correct the deck-shuffle description (two independent decks,
  not one 78-card shuffle); compute entropy text from formulas.
- marketplace.json + plugin.json: sync description to mention the 12
  Houses spread and the 100+ bit entropy budget.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* let-fate-decide: align SKILL.md description article with sibling surfaces

PR review flagged the SKILL.md frontmatter said "Draws a 12 Houses..." while
plugin.json, marketplace.json, and agents/draw.md all say "Draws the 12
Houses...". SPREAD_NAME is a single fixed spread, so "the" is correct.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* let-fate-decide: rename entropy_bits.minor_shuffle to minor_arcana

PR review flagged inconsistent naming in the entropy_bits dict: major_arcana
(deck-named) vs minor_shuffle (operation-named). The value is also
log2(C(56,24)), an unordered selection — not log2(56!), a full shuffle — and
every prose consumer (SKILL.md, README.md, the entropy_note f-string) already
calls it "Minor Arcana selection". Rename for parallel structure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* let-fate-decide: address PR follow-up nits

1. agents/draw.md: tighten portent template prose from "3-5 concise bullets"
   to "3 concise bullets" — the fenced template has exactly 3 placeholders,
   and a Haiku-class model will follow the template literally rather than
   the looser range. SKILL.md's example session synced to match.

2. references/INTERPRETATION_GUIDE.md: rewrite the Special Patterns section
   for the 12-house spread. The previous patterns were carried over from
   the 4-card hand and were broken in the new geometry: "Multiple Major
   Arcana" was guaranteed (12 Majors per draw), "All One Suit" was
   mathematically impossible (each Minor suit has only 14 cards vs. 24
   Minor draws), "All Reversed" dropped from 2^-4 to 2^-36, and "Court
   Card Progression in sequence" had no meaning across houses. Replaced
   with four patterns calibrated to the new baseline frequencies:
   heavy reversal count (>= 24 of 36), heavy single-suit concentration
   (>= 10 of 24 Minors), weighty Majors in critical houses (1/8/12), and
   court cards clustering in people houses (3/7/11).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* let-fate-decide: fix reversal percentile, focus/Domain drift, Step 1 heading

- Correct "Heavy Reversal Count": P(X>=24) for Binomial(36, 0.5) is ~3.26%,
  so "6th percentile" was wrong in both magnitude and direction. Reword to
  "roughly the top 3% of draws".
- Align each house focus string to its house file **Domain** line (Houses 6,
  7, 8, 9, 12 differed in content; House 8 dropped "secrets"). Both surfaces
  reach the interpreter on the default --content path.
- Add test_zodiac_focus_matches_house_domain to pin the two surfaces together.
- Fix Step 1 heading to "Read Each House and Card File" to match its body.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-05-27 15:31:44 -04:00
Leon.C a56045e9ae fix: correct duplicate section numbering in solana-vulnerability-scanner (#160)
* fix: correct duplicate section numbering in solana-vulnerability-scanner

Three sections shared number 5. Renumbered:
- Section 5: Vulnerability Patterns (unchanged)
- Section 6: Scanning Workflow (was 5)
- Section 7: Example Output (was 5)
- Section 8: Reporting Format (was 6)
- Section 9: Priority Guidelines (was 7)
- Section 10: Testing Recommendations (was 8)

* Renumber all H2 sections sequentially in document order

The earlier renumber attempt only addressed the three '## 5.' duplicates
flagged in #159, but introduced two new pairs ('## 9. Priority Guidelines' /
'## 9. Additional Resources' and '## 10. Testing Recommendations' /
'## 10. Quick Reference Checklist') and left the section numbers
non-monotonic ('7, 5, 6' in document order).

This commit renumbers all 12 H2 sections strictly in document order so the
numbers are unique AND increasing: 1..4 unchanged, Example Output now 5,
Vulnerability Patterns 6, Scanning Workflow 7, Reporting Format 8 (no
change), Priority Guidelines 9 (no change), Testing Recommendations 10
(no change), Additional Resources 11, Quick Reference Checklist 12.

Also adds the missing blank line before '## 7. Scanning Workflow' so the
heading does not abut the preceding paragraph.

Bumps building-secure-contracts plugin version 1.1.0 → 1.1.1 in both
plugin.json and marketplace.json so clients pick up the fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 17:36:48 -04:00
Paweł Płatek 870955f1af C review (#156)
* init c review

* lsp

* agents -> prompts

* wip

* add windows, update judges

* improve

* upgrade

* size update

* rm toon format, improve workflow, cluster agents/prompts by issue type, improve prompt cache

* improve general workflow, fix bugs

* sarif via script, cluster manifest

* fix bugs

* fix workflow2

* workflow updates

* more fixes

* more fixes

* improvements

* update readme

* update codeowners

* update codeowners2

* fix small inconsistencies

* Address review feedback on c-review plugin

Critical:
- Move SKILL.md into named skill subdirectory (plugins/c-review/skills/c-review/)
  so plugin discovery and the Codex validator find it; add .codex/skills/c-review
  symlink.
- Convert allowed-tools in SKILL.md from YAML list to space-delimited string
  (spec compliance per #139).
- Fix parse_scalar in generate_sarif.py to respect quoted strings when splitting
  inline lists; ["a,b", c] no longer corrupts to ['"a', 'b"', 'c'].
- Fix location_parts trailing-colon handling so 'src/foo.c:' resolves to
  ('src/foo.c', 1) instead of keeping the colon in the filename.

Important:
- Convert agent tools: from YAML list to comma-separated string in worker,
  dedup-judge, fp-judge.
- Refactor build_run_plan.py main() (131 → 77 lines) by extracting
  _validate_run_inputs / _render_workers / _print_summary helpers.
- Fix ty possibly-missing-attribute warning by typing workers list explicitly.
- Add PEP 723 inline metadata + plugins/c-review/scripts/pyproject.toml.
- Rewrite SKILL.md description as scenario-based; add When to Use /
  When NOT to Use section headers.
- Add Usage section to README.
- Resolve Tier 2 contradiction in dedup-judge: unparseable/multi findings
  now skip Tier 2 and go straight to Tier 3.
- Standardize placeholder convention in fp-judge ({var} not <var>).
- Fix "Widthness Overflows" → "Width Truncation" in integer-overflow-finder.
- Standardize "Bug Patterns to Find" heading in signal-handler and
  thread-safety finders.
- Replace ls -1 glob in worker shard-write with find for shell portability.
- Bump version 1.1.0 → 1.1.1 in plugin.json + marketplace.json.

Verification: codex validator passes (73 plugin skills); ruff + ty clean;
main() 77 lines (limit 100); SARIF generator runtime tests pass; end-to-end
build_run_plan.py produces all 11 clusters with cache primer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Address claude[bot] review feedback on c-review

- Phase 1 is_posix/is_windows probes in SKILL.md now include C++ extensions
  (.cpp, .cxx, .cc, .hpp, .hh) in their --include lists. A pure C++ POSIX
  daemon was silently dropping ~17 POSIX-gated passes plus all is_windows
  clusters because pthread.h / windows.h includes only in .cpp/.hpp files
  failed both --include='*.c' --include='*.h' filters.
- generate_sarif.py informationUri points at trailofbits/skills (the actual
  repo) instead of trailofbits/tob-skills (404).
- CODEOWNERS: add @dguido co-owner to /plugins/c-review/ and move it to the
  top of the c* alphabetical group (- < l < o < u under ASCII collation).
- README.md: move c-review row after burpsuite-project-parser (b < c).
- Bump version 1.1.1 → 1.1.2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 15:59:55 -04:00
Dan Guido 540111a52a Add adversarial-modeler agent to differential-review (#84)
* Add adversarial-modeler agent to differential-review plugin

Introduces a formal agent definition for adversarial threat modeling
on high-risk code changes. Updates SKILL.md to reference agent and
bumps version to 1.1.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix {baseDir} paths and bump marketplace.json version

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve code review findings for PR #84

- Fix decision tree formatting: use correct tree syntax (first
  child uses branch connector, last child uses end connector)
- Add "When NOT to Use" section to adversarial-modeler agent per
  contributing guidelines

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-28 21:12:06 -04:00
Dan Guido 5f0a765877 Add sharp-edges-analyzer agent to sharp-edges (#81)
* Add sharp-edges-analyzer agent to sharp-edges plugin

Introduces a formal agent definition for the sharp edges analysis
workflow. Updates SKILL.md to reference agent and bumps version
to 1.1.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Bump sharp-edges version to 1.1.0 in marketplace.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve code review findings for PR #81

- Add examples column to agent severity classification table
- Add language-specific.md combined quick reference to agent
- Document agent in plugin README.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-28 21:10:55 -04:00
Scott Arciszewski 48bd2626a1 Refresh trailmark skills for public Trailmark 0.2.x (#153)
* Refresh trailmark skills for public Trailmark 0.2.x

Aligns all skills with the now-public trailmark package
(pypi.org/project/trailmark, github.com/trailofbits/trailmark):

- Replace hardcoded language tables with runtime detection via
  trailmark.parse.detect_languages() and --language auto, so the
  skill never goes stale as Trailmark adds languages (21 supported
  as of 0.2.x: Python, JS/TS, PHP, Ruby, C/C++, C#, Java, Go, Rust,
  Solidity, Cairo, Circom, Haskell, Erlang, Miden Assembly, Swift,
  Objective-C, Kotlin, Dart)
- Remove phantom --passes CLI flag from trailmark-structural;
  pre-analysis is a QueryEngine.preanalysis() method, not a flag
- Use native trailmark diff --json in graph-evolution alongside the
  subgraph-diff helper script
- Add `finding` and `audit_note` annotation kinds to the documented
  list (set by augment_sarif / augment_weaudit)
- Document trailmark entrypoints and trailmark augment subcommands
  that exist in the public package
- Bump plugin to 0.8.1

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Address Trailmark skill review nits

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-04-28 21:04:14 -04:00
dm cad5abdc48 Sync skill with claude-code-devcontainer repo (#151)
* sync skill with claude-code-devcontainer repo

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* devcontainer-setup: apply ruff format and shfmt

The pre-commit hook was failing on these two files in CI: ruff joins
the multi-line f-strings in post_install.py, and shfmt with the repo's
'-i 2 -ci' flags adjusts case-body indentation in install.sh.
No behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-04-28 20:50:28 -04:00
Jonathan Hefner debfb29c8e Fix allowed-tools to use spec-compliant space-delimited strings (#139)
* Fix `allowed-tools` to use spec-compliant space-delimited strings

Per the agentskills.io specification, `allowed-tools` must be a single
string of space-delimited patterns, not a YAML list. Converted all 23
SKILL.md files from the `- Item` list format to the correct
`"Item1 Item2"` string format. Also updated the frontmatter examples in
CLAUDE.md and the workflow-skill-design skill template to match.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix remaining allowed-tools format in firebase-apk-scanner and workflow-skill-design docs

- Convert firebase-apk-scanner from comma-separated to space-delimited
- Update anti-patterns.md and tool-assignment-guide.md examples from YAML lists to space-delimited strings
- Remove unnecessary quotes from SKILL.md template placeholder

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Cover commands, new SKILL.md files, and fix template placeholder

Extends the previous spec-compliance fixes:

* Convert command frontmatter (commands/*.md) — per Claude Code
  docs, command files use the same frontmatter as skills, so the
  same space-delimited rule applies.
* Convert three SKILL.md files added since the original PR:
  mutation-testing, trailmark-structural, trailmark-summary.
* Fix the placeholder in the workflow-skill-design template.
  The previous "[minimum tools needed, space-delimited]" was YAML
  flow-sequence syntax, which parses as a list — the opposite of
  what the placeholder claims. Replaced with a concrete-looking
  space-delimited example plus a comment.

Zeroize-audit agent files still use `allowed-tools:` in YAML list
form. They are intentionally excluded: per the project's own docs
(workflow-skill-design references), agents declare tools with
`tools:` (not `allowed-tools:`). Fixing those requires changing
the field name as well as the format and is out of scope for this
PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* zeroize-audit agents: switch allowed-tools to tools

Subagents declare their tool allowlist via `tools:` (comma-separated),
not `allowed-tools:` — see Claude Code's subagent docs and this
repo's own designing-workflow-skills/SKILL.md:47:

> Skills use `allowed-tools:` in frontmatter. Agents use `tools:`
> in frontmatter.

Before this change, the zeroize-audit agents declared their tool list
under `allowed-tools:`, which Claude Code does not read for subagents.
The field was effectively a no-op; the spawned agents had no tool
restriction enforced.

Renames the field on all 11 agents to `tools:` and reformats the YAML
list as comma-separated to match the documented format and existing
agents elsewhere in the repo (e.g. function-analyzer.md,
spec-compliance-checker.md). Tool sets are unchanged.

Behavior change: tools now actually constrain what each spawned agent
can call. The lists are the ones the original author intended.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* skill-improver: convert command allowed-tools to space-delimited

The two command files in plugins/skill-improver/commands/ still used
the JSON flow-array format (`allowed-tools: ["..."]`), which the rest
of this PR converted everywhere else. Convert them to the spec-compliant
space-delimited string form for consistency.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-04-28 19:50:30 -04:00
David Maynor 38793f6757 fix(gh-cli): exit 0 when CLAUDE_ENV_FILE is unset (#135)
* fix(gh-cli): exit 0 when CLAUDE_ENV_FILE is unset in setup-shims.sh

When CLAUDE_ENV_FILE is not set by the runtime, setup-shims.sh exits 1,
causing a SessionStart hook error in Claude Code. This is a graceful
degradation case (shims simply won't be installed), not a fatal error.

The gh-not-found guard on line 10 already exits 0 for the same reason.
This change makes the CLAUDE_ENV_FILE guard consistent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(gh-cli): update bats test for exit 0 and bump version to 1.4.1

The bats test for the CLAUDE_ENV_FILE-unset guard still expected exit 1.
Update it to match the new graceful-degradation behavior, and bump the
plugin version so clients pick up the fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: David Maynor <dmaynor@Davids-MacBook-Air-2.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-04-28 19:28:59 -04:00
tob-joe e8cc5baf93 ci: run plugin Python test suites (catches the PR #125 regression) (#147)
* ci: add python-tests job to run plugin Python test suites

Discovers test_*.py / *_test.py files under plugins/ and executes
each one as a script. Matches the style of the existing bats job.

Works today for:
- plugins/constant-time-analysis/ct_analyzer/tests/test_analyzer.py
- plugins/let-fate-decide/.../scripts/test_draw_cards.py

Both test files already exist in the repo but no CI job invoked them.
As a result, PR #125 (which broke let-fate-decide by removing
`import os` while leaving `os.path` calls in draw()) merged with
green CI even though the existing `test_draw_*` / `test_cli_*`
tests would have caught it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* ci(python-tests): install aarch64 cross toolchain for constant-time-analysis

TestCrossArchitecture.test_cross_compile_arm64 invokes clang with
--target=aarch64-unknown-linux-gnu, which needs the aarch64 libc
headers. Without them clang fails with:
  fatal error: 'bits/libc-header-start.h' file not found

Install gcc-aarch64-linux-gnu + libc6-dev-arm64-cross so clang can
find the cross headers. Also install clang explicitly since the
runner may not have it preinstalled.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* ci: clarify python-tests workflow comments

Resolves code review findings on PR #147 (comment accuracy only —
no behavior change):

- Rewrite the toolchain dependencies comment. The previous wording
  ("aarch64 cross gcc pulls in libc6-dev-arm64-cross") implied a
  transitive dependency, but `--no-install-recommends` suppresses
  Recommends, so libc6-dev-arm64-cross is installed only because it
  is listed explicitly. New comment names what each package supplies.
- Document why `set -uo pipefail` deliberately omits -e (the loop
  collects per-file failures and exits with a combined code).

Reviewers (codex + gemini + pr-review-toolkit agents) flagged 13
findings total; 11 were dismissed (false positives, design choices
matching the bats job, or speculative). Quality pipeline (actionlint,
zizmor, shellcheck, pre-commit, plugin validators, both Python test
suites) all pass locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-04-16 18:15:04 -04:00
Scott Arciszewski 1efb11a08f let-fate-decide: add missing import (#144)
* let-fate-decide: add missing `import os` to draw_cards.py

The os module was used for path operations but never imported,
causing ruff F821 failures in CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* remove no import os assertion in test

* specify `uv run --no-config` to potential conflicts with project configs

* bump plugin version

* address remaining PR review comments

Add --no-project to uv run in agents/draw.md for consistency with
SKILL.md, and fix misleading test docstring to reflect the narrower
os.urandom check.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* use `--no-config` instead of `--no-project` to ignore config

* broaden card file error handler from FileNotFoundError to OSError

Prevents PermissionError and other OSError subclasses from propagating
to the misleading "failed to read system entropy source" handler in main().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: William Tan <1284324+Ninja3047@users.noreply.github.com>
2026-04-14 20:25:11 -04:00
Paweł Płatek d7f76b532d Cosmos improve (#127)
* cosmos update 1

* cosmos update 2

* cosmos update 3

* rm internal data

* renumber

* ibc

* bump cosmos skill version

* proper checklist with progressive disclosure

* rm duplicates

* workflow instaed of checklist

* better workflows

* correct version

* main skill saves findings
2026-04-01 10:50:10 -04:00
Paweł Płatek 17ba9fa3e9 Sast improve (#119)
* experimental rules in run all mode; more explicit gates/ask-user

* bump version
2026-04-01 10:49:33 -04:00
tob-joe 40f192b390 let-fate-decide: replace os.urandom with secrets.randbelow (#125)
* galvanize(iter1): replace os.urandom with secrets.randbelow, add tests

Switch card selection from hand-rolled secure_randbelow(os.urandom)
to stdlib secrets.randbelow(). Update all docstrings, SKILL.md, and
README.md references. Add 25-test suite covering deck construction,
shuffle invariants, CLI validation, and migration regression checks.

* Bump version to 1.1.0 and fix stale rejection sampling claim

- Bump version in plugin.json and marketplace.json (1.0.0 → 1.1.0)
- Update SKILL.md to say "via secrets.randbelow()" instead of claiming
  the script itself implements rejection sampling

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix ruff format: collapse line continuation in test assertion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Merge Scott's PR #128 improvements + vivisect fixes

Incorporates unique changes from Scott's closed PR #128:
- Broadened trigger patterns (casual delegation, YOLO, shrug-like
  brevity, expanded Yu-Gi-Oh references) in README.md and SKILL.md
- Improved SKILL.md frontmatter description with casual/playful
  tone guidance and prefer-over-ask-questions-if-underspecified note
- is_reversed() uses secrets.randbits(1) (more idiomatic coin flip)

Additional fixes from vivisect analysis:
- Converted MAJOR_ARCANA, RANKS, SUITS from lists to tuples
  (prevents silent deck corruption if imported as library)
- Added type guard in draw() rejecting non-int/bool inputs
- Added test_constants_are_immutable and test_draw_rejects_non_int

Co-Authored-By: Scott Arciszewski <scott.arciszewski@trailofbits.com>

* let-fate-decide: improve performance by avoiding text-only turns

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Scott Arciszewski <scott.arciszewski@trailofbits.com>
2026-04-01 10:49:10 -04:00
tob-joe 635e186d1d Add draw agent for let-fate-decide (#134)
* add draw agent for let-fate-decide (Haiku, named agent)

Adds agents/draw.md to the let-fate-decide plugin. This
lets callers dispatch tarot draws as a named agent:

  Agent(subagent_type="let-fate-decide:draw",
    prompt="What portent awaits?")

instead of the current Agent-wrapped-Skill pattern:

  Agent(prompt="Call Skill(let-fate-decide, ...)...")

Benefits:
- Runs on Haiku (model: haiku in frontmatter) -- cheaper
  than inheriting the parent model for card interpretation
- Card file content stays in agent context, not caller's
- Caches the draw logic across parallel tarot agents
  (shared prefix optimization)
- Simplifies dispatch from 4-line prompt to 1-line

The agent does exactly: Bash(draw_cards.py) -> Read(4
card files) -> return 1-2 sentence reading. Falls back
to "fate unavailable" if the script errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* draw agent: --content flag eliminates 4 sequential Read calls

draw_cards.py --content reads card .md files and includes
their text in the JSON output. The draw agent now needs
exactly 1 Bash call (was 1 Bash + 4 sequential Reads).

Saves 4 turns per tarot draw (~8-12 turns per vivisect run).
Haiku was ignoring <use_parallel_tool_calls> and reading
cards one at a time; this bypasses the issue entirely.

Removed Read from agent tools list (no longer needed).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix draw agent script discovery and bump version to 1.1.0

- Replace fragile `find ~/.claude/plugins` with `${CLAUDE_PLUGIN_ROOT}`
- Use context manager for file reads in draw_cards.py
- Bump version to 1.1.0 in plugin.json and marketplace.json

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-03-31 18:14:41 -04:00
bohendo af35cdeac9 init mutation-testing skill (#140)
* init mutation-testing skill

* fix metadata

* init codex symlink

* polish according to review feedback

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
2026-03-31 18:12:57 -04:00
Scott Arciszewski 6b79b5e879 feat(trailmark): skills that reason about code as graphs (#133)
* feat(trailmark): skills that reason about code as graphs

* Add Codex skill symlinks for trailmark plugin

The trailmark plugin's 10 skills were missing .codex/skills/ mappings,
which caused the validate_codex_skills CI check to fail.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address PR #133 review feedback

- Add Rationalizations (Do Not Skip) sections to 5 security skills:
  trailmark, audit-augmentation, crypto-protocol-diagram,
  mermaid-to-proverif, graph-evolution
- Fix requires-python: diagram.py >= 3.12 (was 3.13), protocol.py
  >= 3.12 (was 3.11) to match trailmark's actual requirement
- Rename diagram/ to diagramming-code/ to match SKILL.md frontmatter
  name and all cross-skill references; update Codex symlink

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix diagram skill to use uv run instead of plain python

The diagram.py script carries PEP 723 inline metadata declaring
trailmark as a dependency. Plain python ignores this metadata,
causing ImportError for users who haven't pre-installed trailmark.
uv run processes the metadata and handles dependency resolution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address second round of PR #133 review feedback

- Fix README directory tree: diagram/ -> diagramming-code/
- Fix diagram-types.md: python -> uv run for all script invocations
- Fix graph-evolution Phase 3: replace undefined shell variables
  ($BEFORE_JSON etc) with template substitutions ({before_json} etc)
- Fix vector-forge mutation-frameworks.md: replace cross-skill file
  link with prose reference to genotoxic skill (avoids reference chain)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Local skill-improver review pass across all 10 trailmark skills

diagramming-code:
- Fix arrow syntax inconsistency: uncertain edges use ..-> not -.->
- Fix extra closing paren in diagram-types.md
- Fix diagram.py docstring to match uv run invocation

crypto-protocol-diagram:
- Remove reference chain: spec-parsing-patterns.md no longer links to
  mermaid-sequence-syntax.md, inlines the arrow syntax instead
- Fix ProVerif example note: "Tamarin/ProVerif" -> "ProVerif"

trailmark:
- Replace "path/to/project" with {targetDir} in query-patterns.md
- Add uv run prefix to CLI examples in query-patterns.md
- Add circom to supported language list
- Add pre-analysis annotation kinds to annotation docs

genotoxic:
- Remove reference chains: triage-methodology.md and
  mutation-frameworks.md no longer link to graph-analysis.md

vector-forge:
- Add trailmark to Prerequisites section
- Fix bare trailmark commands to use uv run with {targetDir}

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address third round of PR #133 review feedback

mermaid-to-proverif:
- Fix ProVerif type error: verify(...) = true is a type mismatch
  since verify returns bitstring. Use let _ = verify(...) in instead,
  which aborts on destructor failure (correct ProVerif pattern)

trailmark-summary, trailmark-structural:
- Add 8 missing language extensions to find command (.rb, .php, .cs,
  .java, .hs, .erl, .cairo, .circom)
- Remove unsupported .lean extension
- Split .c -> --language c and .cpp -> --language cpp (separate parsers)

All 7 security skills:
- Rename "Rationalizations (Do Not Skip)" to "Rationalizations to
  Reject" per CLAUDE.md convention

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address fourth round of PR #133 review feedback

mermaid-to-proverif:
- Fix ProVerif type errors in process template: pkey values cannot
  appear in bitstring positions. Add pkey2bs() and concat() to the
  function declarations and rewrite the template to use them,
  matching the sample-output.pv example

trailmark-summary:
- Split .js/.ts mapping: .js -> --language javascript,
  .ts -> --language typescript (separate parsers)

graph-evolution:
- Replace bare python with python3 in graph_diff.py invocations
  (python does not exist on modern Ubuntu/Debian/macOS)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address fifth round of PR #133 review feedback

graph-evolution:
- Change python3 to uv run for graph_diff.py invocations to match
  ecosystem convention

trailmark-structural, trailmark-summary:
- Add Rationalizations to Reject sections (both are security skills
  running blast radius, taint, and privilege boundary analysis)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix ProVerif type consistency and graph-evolution template vars

mermaid-to-proverif:
- Rename senc/sdec to aead_enc/aead_dec in Step 3 preamble to match
  the process template and sample-output.pv
- Fix hkdf signature: hkdf(key, bitstring): key (first arg is DH
  shared secret which has type key, not bitstring)

crypto-to-proverif-mapping.md:
- Fix hkdf declaration and summary table to match corrected signature
- Fix example to use concat/pkey2bs for type-correct HKDF input

graph-evolution:
- Replace $BEFORE_DIR/$AFTER_DIR shell vars in Phase 5 with
  {before_dir}/{after_dir} template substitutions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Comprehensive vivisect-style review of all trailmark skills

ProVerif correctness (mermaid-to-proverif):
- Fix broken ForwardSecrecyTest pattern in security-properties.md:
  process waited on c_fs but nothing sent on it, past_session_key
  was never bound to any session. Replaced with working pattern
  that leaks long-term keys and checks session key secrecy.
- Fix hkdf(bitstring,bitstring) -> hkdf(key,bitstring) in
  proverif-syntax.md to match SKILL.md and sample-output.pv
- Fix type-incorrect example in proverif-syntax.md: tuple of
  (key,pkey,pkey) passed where bitstring expected. Now uses
  concat2/pkey2bs for type-correct serialization.
- Align senc/sdec -> aead_enc/aead_dec in proverif-syntax.md and
  crypto-to-proverif-mapping.md to match SKILL.md and example
- Fix auth query parameter count in security-properties.md:
  beginI fires before session key is known, so has fewer params

Cross-skill consistency:
- Fix 3 stale "diagram skill" references -> "diagramming-code"
  in trailmark/SKILL.md and preanalysis-passes.md
- Add PEP 723 header to graph_diff.py for convention consistency

README and helper skills:
- Add trailmark-summary and trailmark-structural to README skills
  table and directory tree
- Add secondary file extensions (.jsx, .tsx, .h, .hpp, .cc, .cxx)
  to language detection in summary and structural skills
- Inline language mapping in trailmark-structural (was deferred
  to trailmark-summary, violating one-level-deep rule)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix ProVerif type consistency and graph-evolution template vars

- Fix endInitiator -> endI in mermaid-to-proverif Step 6 template
  (endInitiator was never declared as an event)
- Add missing msg2_label constant to Step 3 constants block
- Add .hh/.hxx C++ header extensions to language detection in
  trailmark-summary and trailmark-structural

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix mermaid-to-proverif template: missing beginI event and secrecy witness

Step 6 Initiator template:
- Add missing event beginI(pk(sk_I), pk_R) before first out —
  without it, authentication queries always report false attacks
- Replace local new secret_I with free private_I [private] to
  match sample-output.pv's secrecy witness pattern

security-properties.md:
- Fix beginI/beginR from 3 args to 2 args in mutual auth section
  and query checklist (begin events fire before session key is
  known, so they only take the two public keys)
- Update "Placing Events" table to match 2-param form

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address sixth round of PR #133 review feedback

proverif-syntax.md Two-Party Process example:
- Fix type errors: pkey values passed directly to bitstring params
  in sign() and verify(). Now uses concat2(pkey2bs(...)) pattern.
- Add missing pkey2bs declaration to function list
- Add missing info_session constant declaration
- Fix msg2_label -> msg2 in verification check example to match
  the file's own constant declarations

trailmark-structural:
- Fix contradiction: Rationalizations table said "Install trailmark
  first" but Execution section forbids install commands. Changed
  to "Report not installed and return" to match execution policy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 17:31:30 -04:00
Tim Ren 4b9a4e9087 docs(aflpp): add opinionated environment variables guide (#130)
* docs(aflpp): add opinionated environment variables guide

Add a practical "Environment Variables That Matter" section covering:
- Always-set variables (AFL_TMPDIR, AFL_FAST_CAL) for free perf wins
- Multi-core campaign variables (AFL_FINAL_SYNC, AFL_TESTCACHE_SIZE)
- CI/automated fuzzing variables (AFL_EXIT_ON_TIME, AFL_NO_UI)
- Variables to avoid (AFL_NO_ARITH, AFL_SHUFFLE_QUEUE, AFL_DISABLE_TRIM)

Follow-up from PR #15 review feedback.

Closes #18

* docs(aflpp): address review feedback on env vars guide

- AFL_FAST_CAL: clarify it's recommended for slow targets, not universal
- AFL_FINAL_SYNC: correct scope to afl-cmin corpus minimization
- AFL_TESTCACHE_SIZE: add default (50 MB) and recommended range (50-250)
- AFL_NO_ARITH: note it may help for text-based formats

* fix: address review feedback on AFL env vars descriptions

- AFL_FAST_CAL: move to its own "Slow Targets" section to clarify it's
  specifically recommended for slow targets, not always
- AFL_FINAL_SYNC: clarify it only matters for afl-cmin corpus
  minimization, not for the fuzzing process itself
- AFL_TESTCACHE_SIZE: mention default is 50 MB and good range is 50-250 MB
- AFL_NO_ARITH: soften wording to note it may be useful for text-based targets

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:38:32 +01:00
Benjamin Samuels 9df47310d4 add dimensional analysis plugin (#132)
* add dimensional analysis plugin

* remove emails
2026-03-25 08:38:04 -04:00
Dan Guido 5c15f4f564 Add archetype deep profiles to culture-index skill (#126)
* Add 17 archetype deep profile references to culture-index skill

Convert Culture Index archetype PDFs into structured markdown reference
files with consistent format: core traits, strengths, challenges,
management approach, risk profile, FlashPoints, variations, and summary.

Add Influencer to the archetype summary table in patterns-archetypes.md
and register all archetype files in the SKILL.md reference index.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix review issues in archetype profiles

- Align patterns-archetypes.md table with authoritative archetype files
  for Technical Expert, Socializer, Philosopher, Debater, Administrator
- Standardize "Moderate" to "Mid" in Trailblazer H1
- Split merged Organization/Environment FlashPoints rows into separate
  rows in Facilitator, Socializer, Traditionalist
- Remove leaked PDF source references from Debater, Technical Expert,
  Traditionalist variations sections

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 13:50:09 -04:00
Artem Dinaburg aab484c5b7 Add Codex-native skill installation support (#123)
* Add Codex-native skill installation support

* Document Codex install commands in README

* Enforce Codex skill mappings in CI

* Fix review issues in Codex skill support

- Fix ruff line-length violations in validate_codex_skills.py
- Rewrite gh-cli SKILL.md description to third-person voice
- Fix misleading error messages: describe actual symlink fix
  instead of referencing the user-local installer script
- Add early check for missing .codex/skills/ directory
- Distinguish dangling symlinks from mismatched symlinks
- Add defensive ValueError handling in rel()
- Add PLUGINS_DIR existence guard
- Add install count and zero-install warning to installer
- Add SOURCE_DIR existence check to installer

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 14:29:40 -04:00
Tannr b1f2ed986b Improve skill-improver plugin's ability to locate skill-reviewer (#122)
* The pre-flight check for plugin-dev only searched sibling directories
   and flat plugin paths. When installed via marketplace, plugins live
   under ~/.claude/plugins/cache/<marketplace>/plugin-dev/<version>/,
   which none of the existing paths matched.

   Add glob patterns to search the marketplace cache directory structure.

* add alternative search path for skill-improver since .claude-plugin is stripped when plugins are installed through marketplace

* Bump skill-improver to 1.0.1 and document fallback check

- Bump version in plugin.json and marketplace.json so existing
  users receive the cache detection fix
- Document why the agents/skill-reviewer.md fallback exists
  (cached marketplace installs strip .claude-plugin/)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Dan Guido <dan@trailofbits.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 14:05:28 -04:00