Commit Graph

5990 Commits

Author SHA1 Message Date
Capa Bot
82de4ef56b Sync capa rules submodule 2026-03-27 17:03:38 +00:00
Mike Hunhoff
a6ac839eea fix mypy formatting (#2973) 2026-03-27 10:54:28 -06:00
dependabot[bot]
4ba1b5d233 build(deps): bump bump-my-version from 1.2.4 to 1.3.0 (#2963)
* build(deps): bump bump-my-version from 1.2.4 to 1.3.0

Bumps [bump-my-version](https://github.com/callowayproject/bump-my-version) from 1.2.4 to 1.3.0.
- [Release notes](https://github.com/callowayproject/bump-my-version/releases)
- [Changelog](https://github.com/callowayproject/bump-my-version/blob/master/CHANGELOG.md)
- [Commits](https://github.com/callowayproject/bump-my-version/compare/1.2.4...v1.3)

---
updated-dependencies:
- dependency-name: bump-my-version
  dependency-version: 1.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* style: auto-format with black and isort

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-26 15:30:46 -06:00
dependabot[bot]
f694c2ae5e build(deps): bump picomatch in /web/explorer (#2967)
Bumps  and [picomatch](https://github.com/micromatch/picomatch). These dependencies needed to be updated together.

Updates `picomatch` from 4.0.2 to 4.0.4
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.2...4.0.4)

Updates `picomatch` from 2.3.1 to 2.3.2
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.2...4.0.4)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-26 15:09:15 -06:00
devs6186
c930891c21 rules: address code review feedback for bytes prefix index
- remove bytes_rules from _RuleFeatureIndex; bytes_prefix_index is the
  only structure needed for candidate selection
- build bytes_prefix_index directly in _index_rules_by_feature() instead
  of building bytes_rules then converting, removing one full pass
- add if -1 in bytes_prefix_index guard to avoid temporary object
  creation for the short-pattern fallback (almost never taken)
- remove assert isinstance(feature.value, bytes) checks in _match();
  add Bytes.value: bytes class-level annotation so mypy narrows the
  type without the runtime check
- remove cache structure compatibility block from cache.py per reviewer
  request to handle in a separate PR
- update test assertions from bytes_rules to bytes_prefix_index
2026-03-20 21:37:04 +01:00
devs6186
f572c01d10 rules: clarify bytes_prefix_index guard and add mixed-pattern test
- Change _match() guard from bytes_rules to bytes_prefix_index
  so the guard references the field actually used for candidate selection.
- Update stale comment to describe the prefix-bucket strategy.
- Clarify bytes_rules dataclass comment (retained for logging only).
- Add test_bytes_prefix_index_mixed_short_and_long_patterns covering
  rules with both short (<4B) and long (>=4B) patterns exercised together.
2026-03-20 21:37:04 +01:00
devs6186
2673590370 rules: validate _RuleFeatureIndex structure when loading from cache
When _RuleFeatureIndex gains a new field, pickle.loads() on an older
cached ruleset succeeds but the resulting objects silently lack the new
field — causing an AttributeError deep in _match() at runtime.

Extend load_cached_ruleset() to walk every _RuleFeatureIndex in the
loaded ruleset and verify each dataclass field is present on the
instance. On mismatch, delete the stale cache and return None so the
caller rebuilds from scratch. Production users are unaffected (the
version hash in the cache key already invalidates caches across
releases); this guard covers developer switching between branches.
2026-03-20 21:37:04 +01:00
devs6186
5e19574ba9 rules: build bytes prefix index once at construction, not per _match() call
The previous implementation rebuilt a `defaultdict` mapping byte prefixes
to extracted feature values inside `_match()`, which is called per
function/basic-block/instruction. Moving the rule-side index build to
`_index_rules_by_feature()` (called once at RuleSet construction) eliminates
this per-call allocation and O(R) rule iteration from the hot path.

`_match()` now looks up candidate rules via the pre-built `bytes_prefix_index`
stored in `_RuleFeatureIndex`, iterating only extracted byte features to
compute their prefixes.
2026-03-20 21:37:04 +01:00
devs6186
b868be55b8 rules: simplify bytes prefix indexing and add collision tests 2026-03-20 21:37:04 +01:00
devs6186
501ee0656a rules: index extracted bytes by length prefix for O(1) candidate selection
Closes #2128
2026-03-20 21:37:04 +01:00
devs6186
ed256d2416 rules: index extracted bytes by length prefix for O(1) candidate selection
Instead of iterating all extracted Bytes features for every bytes-based rule,
build a prefix index keyed by fixed bucket sizes (4, 8, 16, 32, 64, 128, 256)
once per scope evaluation.  Each bytes pattern is looked up in the largest
bucket that fits its length, then only candidates sharing that prefix are
compared, replacing the previous O(n) linear scan with an O(1) hash lookup.
Patterns shorter than the minimum bucket still fall back to the full scan.
Adds a test to verify correctness for exact match, startswith match, mismatch,
and short-bytes cases.

Closes: https://github.com/mandiant/capa/issues/2128
2026-03-20 21:37:04 +01:00
Harshit
01c5602bb1 tests: import capa.render.default in test_render (#2938)
* tests: import capa.render.default in test_render

Signed-off-by: blenbot <harshitiszz23@gmail.com>

* tests: import capa.render.default in test_render

Signed-off-by: blenbot <harshitiszz23@gmail.com>

---------

Signed-off-by: blenbot <harshitiszz23@gmail.com>
2026-03-20 13:52:48 -06:00
dependabot[bot]
d73c76a87b build(deps-dev): bump flatted from 3.3.1 to 3.4.2 in /web/explorer (#2948)
Bumps [flatted](https://github.com/WebReflection/flatted) from 3.3.1 to 3.4.2.
- [Commits](https://github.com/WebReflection/flatted/compare/v3.3.1...v3.4.2)

---
updated-dependencies:
- dependency-name: flatted
  dependency-version: 3.4.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-20 13:52:03 -06:00
Willi Ballenthin
0b1e3bfbdf cache: support *BSD (#2949)
* cache: support *BSD

closes #2930 

thanks @res2500

* changelog
2026-03-20 13:51:10 -06:00
blenbot
6579e01d15 fix(freeze): use get_base_address in dumps_dynamic
Signed-off-by: blenbot <harshitiszz23@gmail.com>
2026-03-18 19:23:06 +01:00
blenbot
7090aa9c37 fix(range): correct unbounded max sentinel precedence
Signed-off-by: blenbot <harshitiszz23@gmail.com>
2026-03-18 12:47:31 +01:00
EdoardoAllegrini
30d9989538 fix: resolve mypy type error in dumps_dynamic by using actual field name 2026-03-17 07:22:05 +01:00
dependabot[bot]
7b23834d8e build(deps-dev): bump black from 25.12.0 to 26.3.0 (#2902)
* build(deps-dev): bump black from 25.12.0 to 26.3.0

Bumps [black](https://github.com/psf/black) from 25.12.0 to 26.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/25.12.0...26.3.0)

---
updated-dependencies:
- dependency-name: black
  dependency-version: 26.3.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* style: auto-format with black and isort

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
Co-authored-by: Capa Bot <capa-dev@mandiant.com>
2026-03-13 15:46:13 +01:00
Capa Bot
f1800b5eb4 Sync capa rules submodule 2026-03-12 17:41:51 +00:00
Capa Bot
43f556caf9 Sync capa rules submodule 2026-03-12 17:08:39 +00:00
Capa Bot
5f8c06c650 Sync capa rules submodule 2026-03-12 17:04:53 +00:00
Devyansh Somvanshi
ceaa3b6d03 webui: include feature type in global search (match, regex, api, …) (#2906)
* webui: include feature type in global search (match, regex, etc.)

Searching for "match" or "regex" in the capa Explorer web UI produced
no results because PrimeVue's globalFilterFields only included the
name field, while the feature kind (e.g. "match", "regex", "api") is
stored in the separate typeValue field.

Add 'typeValue' to globalFilterFields so that the global search box
matches nodes by both their value (name) and their kind (typeValue).
No change to rendering or data structure; only the set of fields
consulted during filtering is widened.

Fixes #2349.

* changelog: add entry for #2349 webui global search fix
2026-03-12 10:43:49 -06:00
Devyansh Somvanshi
c03d833a84 rules: handle empty or invalid YAML documents in Rule.from_yaml (#2903)
* rules: handle empty or invalid YAML documents in Rule.from_yaml

Empty or whitespace-only .yml files caused a cryptic TypeError in
Rule.from_dict (NoneType not subscriptable) when yaml.load returned None.
This made lint.py abort with a stack trace instead of a clear message.

Add an early guard in Rule.from_yaml that raises InvalidRule with a
descriptive message when the parsed document is None or structurally
invalid.  get_rules() now logs a warning and skips such files so that
scripts/lint.py completes cleanly even when placeholder .yml files
exist in the rules/ or rules/nursery/ directories.

Fixes #2900.

* changelog: add entry for #2900 empty YAML handling

* rules: fix exception check and add get_rules skip test

- Use e.args[0] instead of str(e) to check the error message.
  InvalidRule.__str__ prepends "invalid rule: " so str(e) never
  matched the bare message, causing every InvalidRule to be re-raised.
- Add test_get_rules_skips_empty_yaml to cover the get_rules skip path,
  confirming that an empty file is warned-and-skipped while a valid
  sibling rule is still loaded.

* fix: correct isort import ordering in tests/test_rules.py

Move capa.engine import before capa.rules.cache to satisfy
isort --length-sort ordering.
2026-03-10 15:04:11 -06:00
Devyansh Somvanshi
1f4a16cbcc loader: skip PE files with unrealistically large section virtual sizes (#2905)
* loader: skip PE files with unrealistically large section virtual sizes

Some malformed PE samples declare section virtual sizes orders of
magnitude larger than the file itself (e.g. a ~400 KB file with a
900 MB section).  vivisect attempts to map these regions, causing
unbounded CPU and memory consumption (see #1989).

Add _is_probably_corrupt_pe() which uses pefile (fast_load=True) to
check whether any section's Misc_VirtualSize exceeds
max(file_size * 128, 512 MB).  If the check fires, get_workspace()
raises CorruptFile before vivisect is invoked, keeping the existing
exception handling path consistent.

Thresholds are intentionally conservative to avoid false positives on
large but legitimate binaries.  When pefile is unavailable the helper
returns False and behaviour is unchanged.

Fixes #1989.

* changelog: add entry for #1989 corrupt PE large sections

* loader: apply Gemini review improvements

- Extend corrupt-PE check to FORMAT_AUTO so malformed PE files
  cannot bypass the guard when format is auto-detected (the helper
  returns False for non-PE files so there is no false-positive risk).
- Replace magic literals 128 and 512*1024*1024 with named constants
  _VSIZE_FILE_RATIO and _MAX_REASONABLE_VSIZE for clarity.
- Remove redundant int() cast around getattr(Misc_VirtualSize); keep
  the `or 0` guard for corrupt files where pefile may return None.
- Extend test to cover FORMAT_AUTO path alongside FORMAT_PE.

* tests: remove mock-only corrupt PE test per maintainer request

williballenthin noted the test doesn't add real value since it only
exercises the mock, not the actual heuristic. Removing it per feedback.

* fix: resolve flake8 NIC002 implicit string concat and add missing test

Fix the implicit string concatenation across multiple lines that caused
code_style CI to fail. Also add the test_corrupt_pe_with_unrealistic_section_size_short_circuits
test that was described in the PR body but not committed.
2026-03-10 15:03:35 -06:00
Devyansh Somvanshi
2c9e30c3e1 perf: eliminate O(n²) tuple growth and reduce per-match overhead (#2890)
* perf: eliminate O(n²) tuple growth and reduce per-match overhead

Four data-driven performance improvements identified by profiling
the hot paths in capa's rule-matching and capability-finding pipeline:

1. find_static_capabilities / find_dynamic_capabilities (O(n²) → O(n))
   Tuple concatenation with `t += (item,)` copies the entire tuple on
   every iteration. For a binary with N functions this allocates O(N²)
   total objects. Replace with list accumulation and a single
   `tuple(list)` conversion at the end.

2. RuleSet._match: pre-compute rule_index_by_rule_name (O(n) → O(1))
   `_match` is called once per instruction / basic-block / function scope
   (potentially millions of times). Previously it rebuilt the name→index
   dict on every call. The dict is now computed once in `__init__` and
   stored as `_rule_index_by_scope`, reducing each call to a dict lookup.

3. RuleSet._match: candidate_rules.pop(0) → deque.popleft() (O(n) → O(1))
   `list.pop(0)` is O(n) because it shifts every remaining element.
   Switch to `collections.deque` for O(1) left-side consumption.

4. RuleSet._extract_subscope_rules: list.pop(0) → deque.popleft() (O(n²) → O(n))
   Same issue: BFS over rules used list.pop(0), making the whole loop
   quadratic. Changed to a deque queue for linear-time processing.

Fixes #2880

* perf: use sorted merge instead of full re-sort for new rule candidates

When a rule matches and introduces new dependent candidates into
_match's work queue, the previous approach converted the deque to a
list, extended it with the new items, and re-sorted the whole
collection — O((k+m) log(k+m)).

Because the existing deque is already topologically sorted, we only
need to sort the new additions — O(m log m) — and then merge the two
sorted sequences in O(k+m) using heapq.merge.

Also adds a CHANGELOG entry for the performance improvements in #2890.

* perf: simplify candidate_rules to LIFO list, revert heapq.merge

Address reviewer feedback:
- Replace deque+popleft with list+pop (LIFO stack) in _extract_subscope_rules;
  processing order doesn't affect correctness, and list.pop() is O(1).
- Replace deque+popleft with list+pop (LIFO stack) in _match; sort candidate
  rules descending so pop() from the end yields the topologically-first rule.
- Revert heapq.merge back to the simpler extend+re-sort pattern; the added
  complexity wasn't justified given the typically small candidate set.
- Remove now-unused `import heapq`.
2026-03-10 14:21:48 -06:00
Devyansh Somvanshi
8c138e3d22 loader: handle struct.error from dnfile and raise CorruptFile with a clear message (#2872)
* loader: handle struct.error from dnfile and show clear CorruptFile message

When .NET metadata is truncated or invalid, dnfile can raise struct.error.
Catch it in DnfileFeatureExtractor and DotnetFileFeatureExtractor and
re-raise as CorruptFile with a user-friendly message.

Fixes #2442

* dnfile: centralize dnPE() loading in load_dotnet_image helper

Add load_dotnet_image() to dnfile/helpers.py that calls dnfile.dnPE()
and catches struct.error, raising CorruptFile with the original error
message included (f"Invalid or truncated .NET metadata: {e}").

Both DnfileFeatureExtractor and DotnetFileFeatureExtractor now call the
helper instead of duplicating the try/except block, and their direct
import of struct is removed.

Addresses review feedback on #2872.

* style: reformat dnfile files with black --line-length=120

Fixes CI code_style failure by applying the project's configured
line length (120) instead of black's default (88).

---------

Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
Co-authored-by: Mike Hunhoff <mike.hunhoff@gmail.com>
2026-03-10 14:20:48 -06:00
Moritz
a11a03bc30 build(deps): bump minimatch and editorconfig in /web/explorer (#2892)
Bumps [minimatch](https://github.com/isaacs/minimatch) and [editorconfig](https://github.com/editorconfig/editorconfig-core-js). These dependencies needed to be updated together.

Updates `minimatch` from 3.1.2 to 3.1.5
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5)

Updates `minimatch` from 9.0.5 to 9.0.9
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5)

Updates `editorconfig` from 1.0.4 to 1.0.7
- [Release notes](https://github.com/editorconfig/editorconfig-core-js/releases)
- [Changelog](https://github.com/editorconfig/editorconfig-core-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/editorconfig/editorconfig-core-js/compare/v1.0.4...v1.0.7)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-version: 3.1.5
  dependency-type: indirect
- dependency-name: minimatch
  dependency-version: 9.0.9
  dependency-type: indirect
- dependency-name: editorconfig
  dependency-version: 1.0.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-10 12:14:56 +01:00
dependabot[bot]
1173dc5fa5 build(deps): bump protobuf from 6.33.5 to 7.34.0 (#2891)
Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from 6.33.5 to 7.34.0.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Commits](https://github.com/protocolbuffers/protobuf/commits)

---
updated-dependencies:
- dependency-name: protobuf
  dependency-version: 7.34.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mike Hunhoff <mike.hunhoff@gmail.com>
2026-03-05 15:23:16 +01:00
Priyank Patel
e53f6abc1e ci: add black auto-format workflow (#2827) (#2883)
* ci: add black auto-format workflow (#2827)

Signed-off-by: priyank <priyank8445@gmail.com>

* ci: use pre-commit to run black and isort (#2827)

* ci: fix install dependencies to include dev extras

---------

Signed-off-by: priyank <priyank8445@gmail.com>
2026-03-05 12:29:33 +01:00
Aditya Pandey
038c46da16 features: fix Regex.get_value_str() returning escaped pattern, breaking capa2yara #1909 (#2886)
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2026-03-05 12:14:27 +01:00
Capa Bot
563071349f Sync capa rules submodule 2026-03-04 20:30:04 +00:00
Capa Bot
517dfe154a Sync capa rules submodule 2026-03-03 07:48:23 +00:00
Devyansh Somvanshi
2e36f67e11 doc: add table comparing ways to consume capa output (#2874)
* doc: add table comparing ways to consume capa output

Add a short table to usage.md for CLI, IDA, Ghidra, CAPE, and web.

Fixes #2273

* doc: add links to each option in the ways-to-consume table

Addresses reviewer feedback to provide a link to learn more for each
consumption method (IDA Pro, Ghidra, CAPE, Web/capa Explorer).

Refs #2273

* doc: add Binary Ninja to ways-to-consume table

Fixes #2273
2026-03-02 10:17:53 -07:00
dependabot[bot]
7bd04fe297 build(deps): bump minimatch and editorconfig in /web/explorer
Bumps [minimatch](https://github.com/isaacs/minimatch) and [editorconfig](https://github.com/editorconfig/editorconfig-core-js). These dependencies needed to be updated together.

Updates `minimatch` from 3.1.2 to 3.1.5
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5)

Updates `minimatch` from 9.0.5 to 9.0.9
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5)

Updates `editorconfig` from 1.0.4 to 1.0.7
- [Release notes](https://github.com/editorconfig/editorconfig-core-js/releases)
- [Changelog](https://github.com/editorconfig/editorconfig-core-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/editorconfig/editorconfig-core-js/compare/v1.0.4...v1.0.7)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-version: 3.1.5
  dependency-type: indirect
- dependency-name: minimatch
  dependency-version: 9.0.9
  dependency-type: indirect
- dependency-name: editorconfig
  dependency-version: 1.0.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-02 16:08:23 +00:00
dependabot[bot]
9f781ec21b build(deps): bump rollup from 4.36.0 to 4.59.0 in /web/explorer (#2885)
Bumps [rollup](https://github.com/rollup/rollup) from 4.36.0 to 4.59.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.36.0...v4.59.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-version: 4.59.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Moritz <mr-tz@users.noreply.github.com>
2026-03-02 17:07:20 +01:00
kamran ul haq
da1abed3f8 ci: pin pip-audit action SHAs and update to v1.1.0 (#2884)
* Fix conftest imports to use relative imports

After adding tests/__init__.py, conftest.py needs relative imports

* ci: pin pip-audit action SHAs and update to v1.1.0

* revert: remove unrelated conftest.py changes
2026-02-27 17:36:28 +01:00
Capa Bot
3bce2a9b62 Sync capa rules submodule 2026-02-26 16:44:29 +00:00
Devyansh Somvanshi
d97b61551d webui: show error when JSON does not follow expected result document schema (#2871)
* webui: show error when JSON does not follow expected schema

Validate result document has required fields (meta, meta.version,
meta.analysis, meta.analysis.layout, rules) after parse. Show
user-friendly error; for URL loads suggest reanalyzing (e.g. VT).

Fixes #2363

* webui: fix array validation bug and deduplicate VT suggestion string

- introduce isInvalidObject() helper (checks !v || typeof !== "object" || Array.isArray)
  so that arrays are correctly rejected in schema validation
- extract VT_REANALYZE_SUGGESTION constant to eliminate the duplicated string
  in loadRdoc()

Addresses review feedback on #2871

* webui: address review - validate feature_counts, hoist VT_REANALYZE_SUGGESTION

- Add validation for meta.analysis.feature_counts in validateRdocSchema()
  so parseFunctionCapabilities and other consumers do not hit missing/invalid
  feature_counts at runtime.
- Require feature_counts to have either 'functions' or 'processes' array
  (static vs dynamic result documents).
- Move VT_REANALYZE_SUGGESTION to module top level to avoid redefining
  on every loadRdoc call.

* webui: allow file-scoped-only result documents in schema validation

- Validation: allow feature_counts without functions/processes arrays; if
  present they must be arrays.
- rdocParser: default feature_counts.functions to [] when missing so
  file-scoped-only docs do not throw.

* webui: remove leading space from VT_REANALYZE_SUGGESTION constant

Per review feedback: the concatenation at call sites handles spacing,
so the constant should not carry a leading space.
2026-02-26 09:35:24 -07:00
Devyansh Somvanshi
e1ffa1dd09 ida-explorer: fix TypeError when sorting locations with mixed address types (#2867)
* ida-explorer: fix TypeError when sorting mixed address types

When a feature has multiple locations and those locations contain a mix
of integer-based addresses (e.g. AbsoluteVirtualAddress) and non-integer
addresses (e.g. _NoAddress), calling sorted() raises a TypeError because
Python falls back to the reflected comparison (__gt__) which is not
defined on _NoAddress.

Add a sort key to sorted() that places integer-based addresses first
(sorted by value) and non-integer addresses last, avoiding the
cross-type comparison.

Fixes #2195

* ida-explorer: fix comparison at source so sorted(locations) works everywhere

Implement the gt solution per review: fix comparison for all addresses
so we can use sorted(locations) / sorted(addrs) consistently without
per-call-site sort keys.

- Add _NoAddress.__gt__ so mixed-type comparison works: (real_address <
  NO_ADDRESS) invokes it and NoAddress sorts last. Avoids TypeError
  when sorting AbsoluteVirtualAddress with _NoAddress.
- In ida/plugin/model.py, use sorted(locations) instead of a custom
  key. view.py (lines 1054, 1077) already use sorted(); they now work
  with mixed address types without change.

Fixes #2195

* changelog: move address sort fix to Bug Fixes section

Per maintainer feedback: fix applies beyond ida-explorer.
2026-02-26 09:33:05 -07:00
kamran ul haq
10dfd287b4 ci: cache vivisect workspaces between CI runs to speed up tests (#2881) 2026-02-25 23:15:13 +01:00
Devyansh Somvanshi
e9b3311338 binja: add mypy config for top-level binaryninja module (#2877)
Allow mypy to skip missing 'binaryninja' (not just binaryninja.*)
when the Binary Ninja API is not installed.

Fixes #2399
2026-02-24 08:57:46 -07:00
Moritz
54cc4ee7a3 Merge pull request #2873 from devs6186/fix/1865-vv-api-color 2026-02-23 23:01:39 +01:00
Capa Bot
12863ab4f2 Sync capa rules submodule 2026-02-23 20:52:03 +00:00
Devyansh Somvanshi
e41b5fb150 webui: fix 404 for "View rule in capa-rules" by using proper URL encoding (#2868)
* webui: fix 404 for \"View rule in capa-rules\" links

The createCapaRulesUrl function was constructing URLs by lowercasing
the rule name and replacing spaces with hyphens, which produced URLs
like /rules/packaged-as-single-file-.net-application/ (404).

The capa-rules website uses the original rule name with URL encoding
(e.g. /rules/packaged%20as%20single-file%20.NET%20application/).

Use encodeURIComponent() on the rule name to produce correct URLs.

Fixes #2482

* refactor: extract baseUrl constant in createCapaRulesUrl per code review
2026-02-23 13:10:31 -07:00
dependabot[bot]
4697902310 build(deps-dev): bump isort from 7.0.0 to 8.0.0 (#2879)
Bumps [isort](https://github.com/PyCQA/isort) from 7.0.0 to 8.0.0.
- [Release notes](https://github.com/PyCQA/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PyCQA/isort/compare/7.0.0...8.0.0)

---
updated-dependencies:
- dependency-name: isort
  dependency-version: 8.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 12:50:28 -07:00
Capa Bot
ed0783c31e Sync capa rules submodule 2026-02-23 16:33:25 +00:00
devs6186
f03ee75d69 doc: document that default output shows top-level matches only; -v/-vv show nested matches (#2875) 2026-02-22 07:41:15 +01:00
devs6186
f526357def main: suggest --os flag when ELF OS detection fails (#2869)
* main: suggest --os flag when OS detection fails for ELF files

When capa cannot detect the target OS of an ELF file, it exits with an
error. Some ELF files lack the standard metadata capa uses for OS
detection (GNU ABI tag, OSABI field, library dependencies, etc.) even
though they do target a valid OS (e.g. a stripped Linux binary using
only raw syscalls).

Add a hint to the unsupported-OS error message telling users they can
specify the OS explicitly with the --os flag, matching the workaround
recommended in the issue.

Fixes #2577
2026-02-20 14:28:43 +01:00
Moritz
c1ec826a9f Merge pull request #2866 from devs6186/fix/2699-rich-markup-escape
render: escape sample-controlled strings to prevent rich MarkupError
2026-02-20 14:06:45 +01:00
devs6186
5ef4ad96ee doc: fix typo and add documentation links in README
- usage.md: fix 'occurance' -> 'occurrence'
- README: add short doc links (usage, installation, limitations, FAQ)

Fixes #2274
2026-02-20 11:15:01 +01:00