Appeng 5612 and 5613#284
Conversation
APPENG-5612: Add argument-count pre-filter to C parser - _count_call_site_args now correctly skips commas inside string/char literals - search_for_called_function checks ALL call sites, accepts if any matches - Adds helper functions _extract_call_site_args_str, _count_args_in_str, _count_all_call_site_args APPENG-5613: Add Go sub-package awareness and filtering - resolve_subpackage_to_module in Go parser for sub-package resolution - _go_subpackage_flow_control with try/except ValueError guard - _extract_go_subpackage for extracting full import paths - extract_go_subpackages_from_patch in intel_utils - Fixed module_path to use resolved full path instead of short name Bug fixes from PR RHEcosystemAppEng#261 review: - C: Fixed string literal handling in argument counting - C: Now checks all call sites instead of only the first - Go: Added missing ValueError catch in _go_subpackage_flow_control - Go: module_path now receives resolved full module path Split from: RHEcosystemAppEng#261 Signed-off-by: Stanny <stanny@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
- Fix type mixing in _go_subpackage_flow_control: guidance now single-line, placed first in result list, detailed info logged for debugging - Fix is_package_imported regex: remove trailing .* that matched identifier anywhere in import path instead of at the end Addresses review comments from PR RHEcosystemAppEng#261 split (APPENG-5612-5613) Signed-off-by: Stanny <stanny@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
…d modules The trailing .* in the regex is intentional to match identifiers in: - Versioned module paths (e.g., 'jwt' in 'github.com/golang-jwt/jwt/v5') - Hyphenated package names (e.g., 'jose' in 'gopkg.in/go-jose/go-jose.v2') Removing it breaks legitimate use cases. False positives only add extra candidates to verify, not incorrect final results. Fixes CI test failures in test_go_parser.py Signed-off-by: Stanny <stanny@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…ting Cherry-pick from PR RHEcosystemAppEng#261 inadvertently reverted the parse_cpe fix from PR RHEcosystemAppEng#276. This restores the proper implementation that: - Validates CPE 2.3 format (rejects invalid prefixes/field counts) - Handles escaped colons in product names (e.g., bar\:mumble) - Returns (None, None, None, None) for malformed input Co-authored-by: Cursor <cursoragent@cursor.com>
|
/test-heavy |
|
Hi @RedTanny There is a go dataset item regression in the confusion matrix, was identified correctly before as not exploitable, and now it's wrongly identifies it as exploitable, After discussing it with claude code and investigation, this is what we have found: Regression: CVE-2022-24769 false positive in openshift/oc (Go Confusion Matrix)After this PR, the agent incorrectly classifies CVE-2022-24769 as exploitable in Root CauseThe The problem is that CVE-2022-24769 is about containerd's container creation and capability-setting code (in Suggested Fix: Narrow Go candidates to patch-derived sub-packagesPR #284 already added File 1: Add async def enrich_vulnerable_functions_from_patch(
cve_intel_list,
critical_context: list[str],
vulnerable_functions: set[str],
ecosystem: str = "",
patch_result=None,
candidate_packages: list[dict] | None = None, # ADD
) -> set[str] | None: # CHANGE from -> NoneAt each return point inside the function where # Pre-fetched patch path:
if patch_result and patch_result.parsed_patch:
all_funcs = extract_functions_from_parsed_patch(patch_result.parsed_patch, ecosystem)
if all_funcs:
go_subpkgs = _extract_go_subpackages_from_result(
patch_result.parsed_patch, candidate_packages)
_append_enrichment_to_context(all_funcs, critical_context,
f"pre-fetched patch ({patch_result.source})",
go_subpackages=go_subpkgs)
return go_subpkgs # was: bare return
# Same pattern for the fetched-patch path (~line 613).File 2: In go_subpackages = None
if not vulnerable_functions:
vf_set: set[str] = set()
pre_fetched_patch = workflow_state.patch_results.get(vuln_id)
go_subpackages = await enrich_vulnerable_functions_from_patch(
workflow_state.cve_intel, critical_context, vf_set, ecosystem,
patch_result=pre_fetched_patch,
candidate_packages=candidate_packages,
)
if vf_set:
vulnerable_functions = sorted(vf_set)
# When patch data identifies specific Go sub-packages, narrow candidates
# so CCA targets the actual vulnerable sub-package (e.g. containerd/oci)
# instead of the entire module (e.g. containerd/containerd), which would
# false-match unrelated utility sub-packages like containerd/sys.
if go_subpackages and ecosystem == "go":
go_modules = {
cp["name"] for cp in candidate_packages
if cp.get("ecosystem", "").lower() == "go"
}
sub_candidates = []
for subpkg in go_subpackages:
for mod in go_modules:
if subpkg.startswith(mod + "/") or subpkg == mod:
sub_candidates.append({
"name": subpkg, "ecosystem": "go",
"source": "patch_subpackage",
})
break
if sub_candidates:
non_go = [cp for cp in candidate_packages
if cp.get("ecosystem", "").lower() != "go"]
candidate_packages = non_go + sub_candidates
precomputed_intel = (critical_context, candidate_packages, vulnerable_functions)How this fixes CVE-2022-24769
The @zvigrinbergHi — thanks for the detailed write-up. I re-ran CVE-2022-24769 on What this re-run actually produced
Ground truth in the
|
|
/test-heavy |
zvigrinberg
left a comment
There was a problem hiding this comment.
Hi @RedTanny
Please see my comments.
Thank you!.
| # --------------------------------------------------------------------------- | ||
| # __trace_down_package (tested indirectly via search_for_called_function) | ||
| # --------------------------------------------------------------------------- | ||
|
|
||
| class TestTraceDownPackage: | ||
| """Tests for __trace_down_package, exercised indirectly through | ||
| search_for_called_function. | ||
|
|
||
| When the caller has a local variable whose type belongs to the callee | ||
| package, __trace_down_package should resolve the type and return True.""" | ||
|
|
||
| def setup_method(self): | ||
| self.parser = GoLanguageFunctionsParser() | ||
|
|
||
| def _doc(self, content, source="test.go"): | ||
| return Document(page_content=content, metadata={"source": source}) | ||
|
|
||
| # Tested in TestGoIsTreeKeyMatch.test_both_empty_strings below |
There was a problem hiding this comment.
@RedTanny There is already TestTraceDownPackage class in this test module
| callee_function: Document, | ||
| callee_function_package: str, |
There was a problem hiding this comment.
@RedTanny Until now it was different then the signature of the Parent ABC huh?
But probably it wasn't mattered too much, as C using BFS instead of DFS in generic algorithm of CCA
| return counts[0] if counts else None | ||
|
|
||
| # Compile the function pattern with recursive param matching | ||
| _FUNCTION_PATTERN_REGEX = regex.compile(r''' |
There was a problem hiding this comment.
@RedTanny Better relocate this regex pattern to the top of the module, so it will be before the function that uses that, for a better readability of the logic and code.
| # Ubuntu's CVE API is often flaky (503/504); fail faster than other intel sources | ||
| self._ubuntu_client = UbuntuClient(session=self._session, | ||
| retry_count=max_retries, | ||
| retry_count=5, |
There was a problem hiding this comment.
@RedTanny Why not changing to 1 ? :)
Just kidding, maybe we should revert this to the parameter to dictates the max_retries parameter.
| from vuln_analysis.utils.prompt_factory import FL_EXAMPLES | ||
|
|
||
| logger = LoggingFactory.get_agent_logger(f"exploit-iq.{__name__}") | ||
| logger = LoggingFactory.get_agent_logger(f"morpheus.{__name__}") |
Summary
Split from PR #261
APPENG-5612: C CCA Argument-count Pre-filter
Add argument-count pre-filter to C parser's
search_for_called_functionto reject cross-package false positives where a same-named function has different arity.Example: rsync
read_byte(1 param)vs PostgreSQLread_byte(3 params)— without this filter, both would match incorrectly.Changes
_count_c_declared_params()to count declared parameters in C function definitions_count_all_call_site_args()to count arguments at ALL call sites (not just first)"a,b"not counted as separators)search_for_called_functionto reject mismatched arityAPPENG-5613: Go CCA Sub-package Awareness
Add Go sub-package awareness so
github.com/lib/foo/barcorrectly matches targetgithub.com/lib/foo.Changes
_extract_go_subpackage()and_go_subpackage_flow_control()to Function Locatorresolve_subpackage_to_module()in Go parser for CCA sub-package filteringextract_go_subpackages_from_patch()in intel_utils for patch enrichmentshort_namedict collision: store list of packages per short nameis_package_importedregex: remove trailing.*that matched identifier anywhere in pathReview Comments Addressed
All review comments from PR #261 relevant to these tasks have been addressed:
module_pathreceives unresolved short nameis_package_importedregex trailing.*ValueErrorguardTest Plan
pytest src/exploit_iq_commons/utils/functions_parsers/tests/test_c_parser.py -vpytest src/exploit_iq_commons/utils/functions_parsers/tests/test_go_parser.py -vpytest tests/test_go_subpackage_fixes.py -vpytest --tb=shortFiles Changed
c_lang_function_parsers.pygolang_functions_parsers.pyfunction_name_locator.pyintel_utils.pytest_c_parser.pytest_go_parser.pytest_go_subpackage_fixes.pyTotal: 7 files, ~3000 insertions
Jira