diff --git a/CHANGELOG.md b/CHANGELOG.md index 401e4144..73d80eb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## master (unreleased) ### New Features +- verify rule metadata format on load #1160 @mr-tz ### Breaking Changes diff --git a/capa/rules.py b/capa/rules.py index 02399d36..d72ff1f4 100644 --- a/capa/rules.py +++ b/capa/rules.py @@ -27,6 +27,7 @@ except ImportError: from typing import Any, Set, Dict, List, Tuple, Union, Iterator import yaml +import pydantic import ruamel.yaml import capa.perf @@ -800,9 +801,17 @@ class Rule: def from_yaml_file(cls, path, use_ruamel=False): with open(path, "rb") as f: try: - return cls.from_yaml(f.read().decode("utf-8"), use_ruamel=use_ruamel) + rule = cls.from_yaml(f.read().decode("utf-8"), use_ruamel=use_ruamel) + # import here to avoid circular dependency + from capa.render.result_document import RuleMetadata + + # validate meta data fields + _ = RuleMetadata.from_capa(rule) + return rule except InvalidRule as e: raise InvalidRuleWithPath(path, str(e)) + except pydantic.ValidationError as e: + raise InvalidRuleWithPath(path, str(e)) def to_yaml(self): # reformat the yaml document with a common style. diff --git a/tests/test_main.py b/tests/test_main.py index ebbf8b86..b6aa72a8 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -38,6 +38,8 @@ def test_main_single_rule(z9324d_extractor, tmpdir): meta: name: test rule scope: file + authors: + - test features: - string: test """