mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-11-13 09:48:18 +00:00
feat(access-control-prover): 11.6 migrate the stapler recogniser through the registry
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
"""Entry-point mapping package: legacy recognisers plus the strategy registry."""
|
||||
|
||||
from . import stapler # noqa: F401 (registers the Stapler strategy at import)
|
||||
from .legacy import * # noqa: F401,F403
|
||||
from .legacy import _php_methods as _php_methods # re-exported internal helpers (enforcement adapter)
|
||||
from .legacy import _php_routes as _php_routes
|
||||
|
||||
@@ -186,7 +186,7 @@ def write_entry_points(entry_points: list[EntryPointRecord], path: Path) -> None
|
||||
|
||||
def _language_entry_points(target: FileTarget, text: str) -> list[EntryPointRecord]:
|
||||
if target.language == "java":
|
||||
return _stapler_entries(target, text) + _jetty_entries(target, text)
|
||||
return _jetty_entries(target, text)
|
||||
if target.language == "python":
|
||||
return _python_entry_points(target, text) + _tornado_entries(target, text)
|
||||
if target.language in {"javascript", "typescript"}:
|
||||
@@ -522,45 +522,6 @@ def _java_methods(target: FileTarget, text: str) -> list[tuple[object, str, str]
|
||||
return methods
|
||||
|
||||
|
||||
def _stapler_entries(target: FileTarget, text: str) -> list[EntryPointRecord]:
|
||||
exposed = re.compile(
|
||||
r"\b(?:extends|implements)\b[^\{]*\b(?:Descriptor|Action|RootAction|Plugin|UnprotectedRootAction|AbstractDescribableImpl)\b"
|
||||
)
|
||||
parameters = re.compile(r"\b(?:StaplerRequest2?|StaplerResponse2?)\b|@(?:QueryParameter|AncestorInPath)\b")
|
||||
records = []
|
||||
for raw_node, owner, header in _java_methods(target, text):
|
||||
node = cast(Any, raw_node)
|
||||
name_node = node.child_by_field_name("name")
|
||||
name = name_node.text.decode("utf-8")
|
||||
params = node.child_by_field_name("parameters").text.decode("utf-8")
|
||||
class_match = exposed.search(owner)
|
||||
param_match = parameters.search(params)
|
||||
if not re.search(r"\bpublic\b", header) or not re.match(r"^do[A-Z]", name) or not (class_match or param_match):
|
||||
continue
|
||||
public = bool(re.search(r"\bimplements\b[^\{]*\bUnprotectedRootAction\b", owner))
|
||||
evidence = ["Stapler public do method"]
|
||||
if class_match:
|
||||
evidence.append(class_match.group())
|
||||
if param_match:
|
||||
evidence.append("Stapler parameter: " + param_match.group())
|
||||
records.append(
|
||||
_entry(
|
||||
target,
|
||||
node.start_point[0] + 1,
|
||||
node.end_point[0] + 1,
|
||||
name,
|
||||
name,
|
||||
"route",
|
||||
"public" if public else "unknown",
|
||||
"http_request",
|
||||
evidence,
|
||||
[],
|
||||
access_declared=public,
|
||||
)
|
||||
)
|
||||
return records
|
||||
|
||||
|
||||
def _jetty_entries(target: FileTarget, text: str) -> list[EntryPointRecord]:
|
||||
records = []
|
||||
for raw_node, owner, header in _java_methods(target, text):
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
"""Task 11.6: the Stapler entry recogniser as a registered strategy.
|
||||
|
||||
This is a target-named strategy module: Stapler vocabulary is legitimate here
|
||||
(the engine never imports this module; only the registry dispatches it). The
|
||||
recognition body moved verbatim from ``mapping/legacy.py`` so existing entries
|
||||
stay byte-identical; the legacy inline dispatch no longer matches this family.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from .legacy import _entry, _java_methods
|
||||
from .registry import register
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .legacy import EntryPointRecord
|
||||
|
||||
|
||||
class StaplerStrategy:
|
||||
"""Recognise Jenkins Stapler ``do*`` handler methods on exposed types."""
|
||||
|
||||
identifier = "stapler"
|
||||
languages: tuple[str, ...] = ("java",)
|
||||
|
||||
def recognize(self, target: object, text: str) -> list[EntryPointRecord]:
|
||||
exposed = re.compile(
|
||||
r"\b(?:extends|implements)\b[^\{]*\b(?:Descriptor|Action|RootAction|Plugin|UnprotectedRootAction|AbstractDescribableImpl)\b"
|
||||
)
|
||||
parameters = re.compile(r"\b(?:StaplerRequest2?|StaplerResponse2?)\b|@(?:QueryParameter|AncestorInPath)\b")
|
||||
records: list[EntryPointRecord] = []
|
||||
for raw_node, owner, header in _java_methods(target, text): # type: ignore[arg-type]
|
||||
node = cast(Any, raw_node)
|
||||
name_node = node.child_by_field_name("name")
|
||||
name = name_node.text.decode("utf-8")
|
||||
params = node.child_by_field_name("parameters").text.decode("utf-8")
|
||||
class_match = exposed.search(owner)
|
||||
param_match = parameters.search(params)
|
||||
if not re.search(r"\bpublic\b", header) or not re.match(r"^do[A-Z]", name) or not (class_match or param_match):
|
||||
continue
|
||||
public = bool(re.search(r"\bimplements\b[^\{]*\bUnprotectedRootAction\b", owner))
|
||||
evidence = ["Stapler public do method"]
|
||||
if class_match:
|
||||
evidence.append(class_match.group())
|
||||
if param_match:
|
||||
evidence.append("Stapler parameter: " + param_match.group())
|
||||
records.append(
|
||||
_entry(
|
||||
target, # type: ignore[arg-type]
|
||||
node.start_point[0] + 1,
|
||||
node.end_point[0] + 1,
|
||||
name,
|
||||
name,
|
||||
"route",
|
||||
"public" if public else "unknown",
|
||||
"http_request",
|
||||
evidence,
|
||||
[],
|
||||
access_declared=public,
|
||||
)
|
||||
)
|
||||
return records
|
||||
|
||||
|
||||
register(StaplerStrategy())
|
||||
|
||||
__all__ = ["StaplerStrategy"]
|
||||
Reference in New Issue
Block a user