diff --git a/capa/ida/plugin/view.py b/capa/ida/plugin/view.py index 3a1d324d..e76cc265 100644 --- a/capa/ida/plugin/view.py +++ b/capa/ida/plugin/view.py @@ -196,7 +196,8 @@ class CapaExplorerRulgenPreview(QtWidgets.QTextEdit): " meta:", " name: ", " namespace: ", - " author: %s" % author, + " authors:", + " - %s" % author, " scope: %s" % scope, " references: ", " examples:", diff --git a/capa/rules.py b/capa/rules.py index ca824728..9ca630ff 100644 --- a/capa/rules.py +++ b/capa/rules.py @@ -54,7 +54,7 @@ META_KEYS = ( "maec/malware-family", "maec/malware-category", "maec/malware-category-ov", - "author", + "authors", "description", "lib", "scope", @@ -1298,6 +1298,12 @@ class RuleSet: logger.debug('using rule "%s" and dependencies, found tag in meta.%s: %s', rule.name, k, v) rules_filtered.update(set(capa.rules.get_rules_and_dependencies(rules, rule.name))) break + if isinstance(v, list): + for vv in v: + if tag in vv: + logger.debug('using rule "%s" and dependencies, found tag in meta.%s: %s', rule.name, k, vv) + rules_filtered.update(set(capa.rules.get_rules_and_dependencies(rules, rule.name))) + break return RuleSet(list(rules_filtered)) def match(self, scope: Scope, features: FeatureSet, va: int) -> Tuple[FeatureSet, ceng.MatchResults]: diff --git a/scripts/lint.py b/scripts/lint.py index 553e9f2e..56dbec2e 100644 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -43,9 +43,8 @@ import capa.rules import capa.engine import capa.helpers import capa.features.insn -import capa.features.common from capa.rules import Rule, RuleSet -from capa.features.common import Feature +from capa.features.common import String, Feature, Substring logger = logging.getLogger("lint") @@ -168,12 +167,12 @@ class InvalidScope(Lint): return rule.meta.get("scope") not in ("file", "function", "basic block", "instruction") -class MissingAuthor(Lint): - name = "missing author" - recommendation = "Add meta.author so that users know who to contact with questions" +class MissingAuthors(Lint): + name = "missing authors" + recommendation = "Add meta.authors so that users know who to contact with questions" def check_rule(self, ctx: Context, rule: Rule): - return "author" not in rule.meta + return "authors" not in rule.meta class MissingExamples(Lint): @@ -490,7 +489,7 @@ class FeatureStringTooShort(Lint): def check_features(self, ctx: Context, features: List[Feature]): for feature in features: - if isinstance(feature, (capa.features.common.String, capa.features.common.Substring)): + if isinstance(feature, (String, Substring)): assert isinstance(feature.value, str) if len(feature.value) < 4: self.recommendation = self.recommendation.format(feature.value) @@ -697,7 +696,7 @@ def lint_scope(ctx: Context, rule: Rule): META_LINTS = ( MissingNamespace(), NamespaceDoesntMatchRulePath(), - MissingAuthor(), + MissingAuthors(), MissingExamples(), MissingExampleOffset(), ExampleFileDNE(), diff --git a/tests/test_fmt.py b/tests/test_fmt.py index 92bd4ffa..de96a1f4 100644 --- a/tests/test_fmt.py +++ b/tests/test_fmt.py @@ -15,7 +15,8 @@ EXPECTED = textwrap.dedent( rule: meta: name: test rule - author: user@domain.com + authors: + - user@domain.com scope: function examples: - foo1234 @@ -38,7 +39,8 @@ def test_rule_reformat_top_level_elements(): - number: 2 meta: name: test rule - author: user@domain.com + authors: + - user@domain.com scope: function examples: - foo1234 @@ -55,7 +57,8 @@ def test_rule_reformat_indentation(): rule: meta: name: test rule - author: user@domain.com + authors: + - user@domain.com scope: function examples: - foo1234 @@ -75,7 +78,8 @@ def test_rule_reformat_order(): """ rule: meta: - author: user@domain.com + authors: + - user@domain.com examples: - foo1234 - bar5678 @@ -98,7 +102,8 @@ def test_rule_reformat_meta_update(): """ rule: meta: - author: user@domain.com + authors: + - user@domain.com examples: - foo1234 - bar5678 @@ -124,7 +129,8 @@ def test_rule_reformat_string_description(): rule: meta: name: test rule - author: user@domain.com + authors: + - user@domain.com scope: function features: - and: diff --git a/tests/test_rules.py b/tests/test_rules.py index 68afea7d..1f221e45 100644 --- a/tests/test_rules.py +++ b/tests/test_rules.py @@ -42,7 +42,8 @@ def test_rule_yaml(): rule: meta: name: test rule - author: user@domain.com + authors: + - user@domain.com scope: function examples: - foo1234 @@ -724,7 +725,8 @@ def test_filter_rules(): rule: meta: name: rule 1 - author: joe + authors: + - joe features: - api: CreateFile """ @@ -803,7 +805,8 @@ def test_filter_rules_missing_dependency(): rule: meta: name: rule 1 - author: joe + authors: + - joe features: - match: rule 2 """