consume only artifacts the runtime produced
tile_manifest_path arrives in the detection and segmentation request and was read straight off disk, and a manifest entry may name an absolute tile path. That makes an API field an unbounded reference to the host filesystem, and it contradicts the rule the persistence model rests on: only a governed, runtime-produced artifact may be consumed, and a file outside the storage root is not one. Both the manifest and every tile it names now resolve under STORAGE_ROOT. Resolution happens before the comparison, so ".." cannot climb out and a sibling that merely shares a name prefix does not pass. GEOINTEL_ALLOW_EXTERNAL_ARTIFACT_PATHS opts out for provisioning workflows that stage tiles before ingest. The check honours the Settings the caller is operating under rather than the process-wide ones, because every analysis path already threads its own. The affected tests write manifests into tmp_path, so they now declare tmp_path as the storage root — which is what a deployment does, and makes the fixtures more honest than they were. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -380,7 +380,10 @@ class SegmentationService:
|
||||
manifest_path = DetectionQaService.tile_manifest_path(run_parameters)
|
||||
coverage = None
|
||||
if manifest_path:
|
||||
manifest = DetectionService._load_tile_manifest(manifest_path, get_settings().yolo_max_tiles)
|
||||
settings_for_qa = get_settings()
|
||||
manifest = DetectionService._load_tile_manifest(
|
||||
manifest_path, settings_for_qa.yolo_max_tiles, settings_for_qa
|
||||
)
|
||||
coverage = DetectionQaService.build_tile_coverage(
|
||||
manifest,
|
||||
manifest_path=manifest_path,
|
||||
@@ -700,7 +703,7 @@ class SegmentationService:
|
||||
yolo_seg_adapter_class: type[YoloSegmentationAdapter],
|
||||
sam_adapter_class: type[SamSegmentationAdapter],
|
||||
) -> tuple[list[Segmentation], dict[str, Any]]:
|
||||
manifest = DetectionService._load_tile_manifest(tile_manifest_path, settings.yolo_max_tiles)
|
||||
manifest = DetectionService._load_tile_manifest(tile_manifest_path, settings.yolo_max_tiles, settings)
|
||||
if model_name == settings.sam_model_id:
|
||||
model_path = Path(settings.sam_model_path or "").expanduser()
|
||||
allowed_frameworks = ("ultralytics/sam", "sam", "ultralytics", "pytorch")
|
||||
@@ -728,7 +731,7 @@ class SegmentationService:
|
||||
manifest_crs = DetectionService._require_manifest_crs(manifest)
|
||||
candidates: list[dict[str, Any]] = []
|
||||
for tile in manifest["tiles"]:
|
||||
tile_path = DetectionService._resolve_tile_path(tile, Path(tile_manifest_path or "").expanduser())
|
||||
tile_path = DetectionService._resolve_tile_path(tile, Path(tile_manifest_path or "").expanduser(), settings)
|
||||
for raw in adapter.predict_tile(model, tile_path, confidence_threshold):
|
||||
model_class_name = str(raw.get("class_name") or "").strip()
|
||||
class_name = DetectionService._canonical_class_name(model_class_name)
|
||||
|
||||
Reference in New Issue
Block a user