* Use openlit <1.36.6
Openlit >=1.36.6 has a bug with langgraph instrumentation.
Also add a test to seed-gen for when openlit is enabled
* Link to issue
* Fix CoverageBot.run_task and add test cases
---------
Co-authored-by: Henrik Brodin <90325907+hbrodin@users.noreply.github.com>
Run `ruff check --fix` across all components to fix I001 import sorting
violations in src/ and test/ directories.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Apply automated fixes from ruff (import ordering, formatting) to all test
files across all components:
- Reorder imports according to isort/ruff rules
- Remove unnecessary imports
- Consistent formatting
Components affected:
- fuzzer/tests/
- orchestrator/test/
- patcher/tests/
- program-model/tests/
- seed-gen/test/
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Improve coverage tracking precision
Previously coverage tracking included all regions. This changes coverage tracking to be more precise.
Macros that result in code are represented as a single line in the function, and any executed line in the macro will make that line 'covered'. Beyound that, only CodeRegions will count. This will prevent code guarded by #if that aren't in the binary from being considered reachable for example. The idea is that seed-gen would have more accurate information when selecting functions to target.
I've done some testing and it appears as if the new implementation in general reaches more lines and covers more functions.
* Fix macro coverage leaking across files due to missing filename in key
The expansion_coverage map used (line, col) as key without filename,
causing coverage from one file to incorrectly appear in another when
macros were at the same coordinates.
* Recursively expand macros and add named types for coverage data
- Process ExpansionRegion target_regions recursively instead of counting
only the call site line
- Add coordinate index for O(1) expansion lookups
- Cache computed expansion lines to avoid recomputation across functions
- Use bulk set operations for better performance
- Prevent infinite loops with visited set for circular macro references
- Add named types for coverage data structures:
- RegionCoords, ExpansionKey, CachedExpansionLines
- Type aliases: ExpansionMap, CoordToFilenames, ExpansionLinesCache
- Add comprehensive tests for nested macros and edge cases
Before this commit, the fuzzer dependend on clusterfuzz, which uses
protobuf 3.20. Since fuzzer-bot depended on common subpackage as well
and also common (and the other packages) require protobuf, we had to use
protobuf 3.20 everywhere. This old dependency however means that a lot
of packages can't be used in their "newer" versions, because they depend
on newer protobuf versions.
This commit splits the fuzzer into a separate fuzzer-runner that is
executed in a separate process inside a separate venv. fuzzer-runner
executes the clusterfuzz-heavy operations (e.g. fuzzing) and isolates the
clusterfuzz dependency, so that the rest of the system can use newer
protobuf version.
* split `fuzzer-bot` in `fuzzer-runner` and `fuzzer-bot`
* have a "full" optional dependency group in `common`, including `openlit`
and `protobuf`, so that `fuzzer-runner` can use the lite version of `common`
without bringing those heavy deps
* move `FuzzConfiguration`/`BuildConfiguration` in a separate common file
that doesn't require to load all protobuf files. Again, in this way
other components can just depend on the `common` "lite" version and not
require protobuf stuff
* add `fuzzer-runner` as a separate venv inside the `fuzzer-bot` container
* add `RunnerProxy` class in fuzzer package to provide an interface to
interact with the fuzzer-runner binary.
* style: apply ruff auto-fixes and formatting across entire codebase
Applied safe auto-fixes from ruff v0.12.9 with --select ALL to improve code quality:
- Reorder imports (stdlib → third-party → local)
- Use modern type hints (collections.abc.Generator instead of typing.Generator)
- Add trailing commas for better diffs
- Format multi-line function parameters for readability
- Add strict=False to zip() calls for explicit behavior
- Simplify redundant elif to if after return statements
- Consistent code formatting with ruff format
These are all mechanical, non-controversial changes that improve code consistency
without altering functionality. Changes affect 180 files across all modules:
common, fuzzer, orchestrator, patcher, program-model, and seed-gen.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* re-applt ruff after merge
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Michael D Brown <michael.brown@trailofbits.com>
* refactor: standardize packaging across all components
- Standardize Python version to >=3.12,<3.13 for all components
- Migrate from [project.optional-dependencies] to modern [dependency-groups] (PEP 735)
- Standardize ruff line-length to 120 characters across all components
- Add consistent project metadata:
- AGPL-3.0 license field
- Repository and Issues URLs
- Improved, descriptive description fields
- Fix email addresses to include .com domain
This improves consistency, maintainability, and follows modern Python
packaging best practices with uv/pip standards.
* fix: address PR review comments
- Move requires-python field to standard position (after license) in seed-gen
- Update all components to use latest ruff version (>=0.12.8)
- Ensure consistent dependency ordering across all components
* refactor: standardize dependency pinning strategy
Apply consistent dependency versioning across all components:
- Use ~= (compatible release) for core dependencies:
- Infrastructure: redis, pydantic, fastapi, uvicorn, sqlalchemy
- AI/LLM: openai, langchain-community, langgraph-checkpoint
- Parsing: tree-sitter, tree-sitter-language-pack
- Web: requests, urllib3, pyyaml
- Utils: python-dotenv, unidiff, argon2-cffi, pymongo, six
- Keep >= for stable dev tools:
- pytest, mypy, ruff, flake8 (want latest versions)
- types-* packages (want latest type definitions)
- rich, beautifulsoup4 (stable, backwards compatible)
- Keep exact pins for known issues:
- protobuf (narrow range for compatibility)
- openlit==1.32.12 (documented issue with 1.33)
- clusterfuzz==2.6.0 (complex, version-sensitive)
This provides predictable builds with automatic patch updates while
preventing unexpected breaking changes from major/minor version bumps.
* feat: add project metadata for discoverability
Add comprehensive metadata to all components:
Keywords:
- common: cybersecurity, crs, utilities, protobuf, redis, telemetry
- fuzzer: fuzzing, oss-fuzz, libfuzzer, vulnerability-discovery, coverage
- orchestrator: orchestration, task-management, scheduler, api, fastapi
- patcher: patching, vulnerability-repair, llm, ai, code-generation
- program-model: static-analysis, codequery, tree-sitter, semantic-analysis
- seed-gen: test-generation, input-generation, fuzzing, seed-corpus, llm
Classifiers:
- Development Status :: 4 - Beta (all components)
- License :: OSI Approved :: GNU Affero General Public License v3
- Programming Language :: Python :: 3.12
- Topic :: Security (all components)
- Component-specific topics (Testing, AI, Distributed Computing, etc.)
- Operating System :: POSIX :: Linux
URLs:
- Added Documentation URL pointing to README for all components
This improves package discoverability, provides clear metadata for tools,
and gives the project a more professional appearance.
* Standardize tool configurations across all components
- Add pytest.ini_options configuration to all components
- Add coverage configuration with consistent exclude patterns
- Standardize ruff configuration with target-version and lint rules
- Fix missing readme field in fuzzer/pyproject.toml
- Fix python-dotenv spacing inconsistency in seed-gen
- Standardize all dev dependencies to use ~= operator for consistency
* Fix trailing whitespace and line length issues
- Remove trailing whitespace from tree-sitter query strings
- Remove trailing whitespace from test output strings
- Fix line length issues in logger.info() calls by splitting format strings
- Fix line length in datetime formatting by extracting variables
- Split long Pydantic Field descriptions and docstrings
- Leave test data strings unchanged to avoid breaking tests
* Fix dependency resolution issues
- Update argon2-cffi from ~=21.0.0 to ~=21.3.0 (21.0.x doesn't exist on PyPI)
- Update langgraph-checkpoint from ~=2.0.25 to ~=2.1.0 to match langgraph requirements
- Standardize spacing around ~= operators in all dependency specifications
- All components now successfully resolve dependencies with uv
* Apply ruff auto-fixes across project
- Fix import sorting (I001) in fuzzer, orchestrator, and patcher
- Update to PEP 585 type annotations (List->list, Dict->dict, etc.)
- Update to PEP 604 union syntax (Optional[X] -> X | None)
- Remove unnecessary UTF-8 encoding declarations
- Remove redundant file open modes
- Modernize type annotations throughout the codebase
Remaining issues are primarily line length (E501) which require manual review
* Fix line length issues in program-model component
- Break up long Java code strings in test assertions using implicit concatenation
- Split long constructor and method definitions across multiple lines
- Add noqa: E501 comment for 10,977 character struct definition test data
- All program-model line length issues resolved
* fix: revert protobuf enum type annotations to Optional
Protobuf enums (EnumTypeWrapper) don't support the | operator for type unions.
The ruff UP035 rule converted Optional[ProtobufEnum] to ProtobufEnum | None,
but this causes TypeError at runtime. Reverted these specific changes while
keeping the modern type union syntax for regular Python types.
* chore: add ruff protection for protobuf enum type annotations
- Configure ruff to ignore UP045 rule in test_submissions.py
- Add inline noqa comments to document why Optional is needed
- Protobuf enums (EnumTypeWrapper) don't support the | operator
- This prevents future automated fixes from breaking the code
* fix: modernize Python syntax and fix formatting issues
- Convert printf-style formatting to f-strings (UP031)
- Remove trailing whitespace from blank lines (W293)
- Use PEP 695 generic class syntax for Python 3.12+ (UP046)
- Use PEP 695 type alias syntax with 'type' keyword (UP040)
These changes modernize the codebase to use Python 3.12+ features
and fix formatting inconsistencies detected by ruff.
* fix: resolve undefined MsgType reference after PEP 695 conversion
When converting to PEP 695 generic class syntax, the MsgType TypeVar
was removed but was still referenced in overloaded method signatures.
Changed the generic fallback overload to use Message directly.
* fix: resolve line length violations across entire codebase
Applied Black formatter and manual fixes to resolve E501 line length violations:
- Fixed 178 line length issues across common, fuzzer, orchestrator, patcher, and program-model components
- Used Black formatter for automatic reformatting where possible
- Manually split long strings, function calls, and complex expressions
- All files now comply with 120-character line limit
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: revert PEP 695 type alias syntax in node_local.py
The PEP 695 syntax (type X = Y) creates TypeAliasType objects that cannot
be used as constructors at runtime. Since node_local.py uses NodeLocalPath
and RemotePath as constructors (e.g., NodeLocalPath(path)), we must use
the old TypeAlias syntax to maintain runtime functionality.
Added noqa comments to prevent ruff from attempting to modernize these
aliases in the future.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: configure ruff to ignore UP040 for node_local.py
Added per-file configuration to prevent ruff from attempting to convert
TypeAlias annotations to PEP 695 syntax in node_local.py. This protects
the runtime functionality that relies on these type aliases being usable
as constructors.
Also removed redundant inline noqa comments since the ignore is now
configured at the project level.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: correct MsgType reference in static method decorator
The _ensure_group_name static method decorator was incorrectly
referencing MsgType in the wrapper function signature. Since MsgType
is a class-level type parameter and not accessible in static method
scope, changed it to Message which is the appropriate bound type.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: add explanatory comment for Message type in decorator
Added a comment explaining why we must use Message instead of MsgType
in the _ensure_group_name decorator's wrapper function. This prevents
future confusion and protects against accidental "fixes" that would
break the code.
The MsgType parameter is a class-level type variable that's not in
scope within the static method decorator context.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Enforce mypy on fuzzer component
- Add mypy type checking enforcement for fuzzer component in Makefile
- Fix 39 type errors across 9 files in fuzzer component:
- Add missing return type annotations (-> None, -> bool, -> int)
- Fix Beautiful Soup union type issues with proper casting and None checks
- Fix TemporaryDirectory path usage by using .name attribute
- Add type annotations for function parameters and variables
- Handle potential None values in registry and XML parsing
All fuzzer component files now pass strict mypy type checking.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Brad Swain <BradSwain@users.noreply.github.com>
* fix tests
* Update fuzzer/src/buttercup/fuzzing_infra/builder_bot.py
Co-authored-by: Riccardo Schirone <562321+ret2libc@users.noreply.github.com>
* Update fuzzer/src/buttercup/fuzzing_infra/builder_bot.py
Co-authored-by: Riccardo Schirone <562321+ret2libc@users.noreply.github.com>
* use pathlike[str] instead of tmpdir
* update test to use Path directly
* fix type annotation
---------
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Brad Swain <BradSwain@users.noreply.github.com>
Co-authored-by: Riccardo Schirone <562321+ret2libc@users.noreply.github.com>
* Fix integration-test run
* use the proper oss-fuzz-aixcc commit to run integration-test
* determine OSS_FUZZ_CONTAINER_ORG at runtime
* use `git diff` in the patcher to create the patch to fix a problem
with patches affecting non-newline terminated files
* fix parsing
* fix program-model lint
* Use an internal_patch_id instead of indices
This is the first step in being able to merge sets of PoVs and test
patches against all PoVs within a task.
* Discard redundant builds
* Compare relevant fields
* Make builder-bot build patched versions
* orchestrator: test new build outputs
* address review
* builder-bot: use times_delivered logic in case of failures
* Force fuzzer to use a node_local temp
Occasionally the fuzzer code would do a rename from a tempdir to our
node_local dirs. This caused cross-device link errors. This pr ensures
the function used to get a tempdirectory can be controlled when needed.
* More robust copying of live corpus
As the corpus might change due to fuzzers modifying it, the merger bot
can occasionally fail due to missing local files, or files that where
copied from remote that no longer exists in local. For the merger to
operate ideally, we want be sure that the remote files are all included
in the merge, while local files we just take what we get. There will
be a next attempt soon.
* Sample the local files to merge to remote corpus (#691)
This is done to try and limit the time the merge takes. This will allow
for more parallel mergers making progress and not stalling each other on
the same harness.
* Merger-bot refactor
The merger is now combined with the corpus-sync. This allows us to push
only corpus that adds coverage to the remote store and only remove
locally what doesn't add coverage. No need for a redis set to track
which inputs shouldn't be added.
* Remove unintentnional debug code
* Dataclass fixes
* Local caching of already processed corpus
This implements a model for a local cache that ignores corpus that has
previously been processed for coverage.
* Deal with non-sampled case
* Make failed a set
---------
Co-authored-by: Michael D Brown <michael.brown.uc@gmail.com>