mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
feat(plane): memory store (file and MinIO) and the remember task (harnessx-removal task 2)
plane/memory.py: the MemoryStore interface with FileStore (index.jsonl, facts by content hash, repos/<host>__<owner>__<name>/<pin>.jsonl, idempotent ingest, deterministic row ids, refusal below 1 GiB free naming the path) and MinioStore (object metadata and tags, S3 Select pushdown probed once per process with a logged local fallback, object version ids on every row read, versioning and runs/ lifecycle helper, presigned URLs). OUSAST_MEMORY selects the backend; MINIO_* settings come from .env; the minio SDK is the optional extra `minio`. plane/tasks/remember.py: model-free rows (facts, verdict, unit_cost, alert) from a case's artifacts; remember_run computes them on the host for a recorded run without writing into it. reconciler.mark_done (477 lines total), seed before and ingest after `ousast plane run`, `ousast plane remember <run>`. The generator annotates each repo-facts Task with openultrasast.io/memory-key (repo, pin, candidates digest, image digest) and the Run with its population and split; plane/ regenerated. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d64ab2817e
commit
52d28b5121
+59
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"family": "untrusted_destination",
|
||||
"candidates": [
|
||||
{
|
||||
"candidate": "lmdeploy/vl/media/connection.py::_load_http_url",
|
||||
"site": "lmdeploy/vl/media/connection.py:68:_load_http_url",
|
||||
"a": true,
|
||||
"b": true,
|
||||
"agreed": true,
|
||||
"disputed": false,
|
||||
"site_match": true,
|
||||
"usd": 0.022175,
|
||||
"turns": 10,
|
||||
"finding": {
|
||||
"candidate": "lmdeploy/vl/media/connection.py::_load_http_url",
|
||||
"site": "lmdeploy/vl/media/connection.py:68:_load_http_url",
|
||||
"reported_at": "lmdeploy/vl/media/connection.py:68",
|
||||
"family": "untrusted_destination",
|
||||
"title": "SSRF guard bypass via HTTP redirect in _load_http_url",
|
||||
"witness": "Source: an attacker-controlled HTTP request to the OpenAI-compatible RESTful API whose `messages` contain a multimodal c"
|
||||
}
|
||||
}
|
||||
],
|
||||
"agreed": [
|
||||
{
|
||||
"candidate": "lmdeploy/vl/media/connection.py::_load_http_url",
|
||||
"site": "lmdeploy/vl/media/connection.py:68:_load_http_url",
|
||||
"reported_at": "lmdeploy/vl/media/connection.py:68",
|
||||
"family": "untrusted_destination",
|
||||
"title": "SSRF guard bypass via HTTP redirect in _load_http_url",
|
||||
"witness": "Source: an attacker-controlled HTTP request to the OpenAI-compatible RESTful API whose `messages` contain a multimodal c",
|
||||
"passes": 2
|
||||
}
|
||||
],
|
||||
"disputed": [],
|
||||
"metrics": {
|
||||
"candidates": 1,
|
||||
"candidates_before_triage": 1,
|
||||
"asked_in_both": 1,
|
||||
"flagged_a": 1,
|
||||
"flagged_b": 1,
|
||||
"agreed": 1,
|
||||
"disputed": 0,
|
||||
"hunts": 2,
|
||||
"declared_sites": 1,
|
||||
"declared_sites_in_set": 1,
|
||||
"declared_sites_matched": 1,
|
||||
"declared_sites_matched_agreed": 1,
|
||||
"site_matching": "assessed",
|
||||
"usd_total": 0.022175,
|
||||
"cost_per_candidate": 0.022175,
|
||||
"recorded_triage_usd": 0.000768,
|
||||
"recorded_triage_basis": "derived per file from the batched-check scans: recorded usd (triage + hunts) minus the recorded hunt usage priced at deepseek-flash list prices; the triage call's own usage was not recorded",
|
||||
"usd_total_with_recorded_triage": 0.022943,
|
||||
"cost_per_candidate_with_recorded_triage": 0.022943,
|
||||
"turns_per_hunt": 5.0,
|
||||
"calls_per_hunt": 7.0
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
[]
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"status": "done",
|
||||
"units_done": 1,
|
||||
"units_total": 1,
|
||||
"usd": 0,
|
||||
"calls": 0,
|
||||
"usage": {
|
||||
"prompt_tokens": 0,
|
||||
"prompt_cache_hit_tokens": 0,
|
||||
"completion_tokens": 0
|
||||
},
|
||||
"priced": true,
|
||||
"model": null,
|
||||
"pass": null,
|
||||
"metrics": {
|
||||
"candidates": 1,
|
||||
"candidates_before_triage": 1,
|
||||
"asked_in_both": 1,
|
||||
"flagged_a": 1,
|
||||
"flagged_b": 1,
|
||||
"agreed": 1,
|
||||
"disputed": 0,
|
||||
"hunts": 2,
|
||||
"declared_sites": 1,
|
||||
"declared_sites_in_set": 1,
|
||||
"declared_sites_matched": 1,
|
||||
"declared_sites_matched_agreed": 1,
|
||||
"site_matching": "assessed",
|
||||
"usd_total": 0.022175,
|
||||
"cost_per_candidate": 0.022175,
|
||||
"recorded_triage_usd": 0.000768,
|
||||
"recorded_triage_basis": "derived per file from the batched-check scans: recorded usd (triage + hunts) minus the recorded hunt usage priced at deepseek-flash list prices; the triage call's own usage was not recorded",
|
||||
"usd_total_with_recorded_triage": 0.022943,
|
||||
"cost_per_candidate_with_recorded_triage": 0.022943,
|
||||
"turns_per_hunt": 5.0,
|
||||
"calls_per_hunt": 7.0
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"callers": {
|
||||
"lmdeploy/vl/media/connection.py::_load_http_url": []
|
||||
},
|
||||
"counts": {
|
||||
"callers": 0,
|
||||
"candidates": 1,
|
||||
"files": 1,
|
||||
"functions": 4809
|
||||
},
|
||||
"files": {
|
||||
"lmdeploy/vl/media/connection.py": {
|
||||
"functions": [
|
||||
"_is_safe_url",
|
||||
"_load_http_url",
|
||||
"_load_data_url",
|
||||
"_load_file_url",
|
||||
"load_from_url"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"calls": 0,
|
||||
"model": null,
|
||||
"status": "done",
|
||||
"units_done": 608,
|
||||
"units_total": 608,
|
||||
"usage": {},
|
||||
"usd": null
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
apiVersion: ax.io/v1alpha1
|
||||
kind: Workspace
|
||||
metadata:
|
||||
name: lmdeploy-media-url-ssrf-vulnerable
|
||||
atespace: default
|
||||
spec:
|
||||
git:
|
||||
- name: repo
|
||||
repo: https://example.com/reserved/lmdeploy
|
||||
dir: repo
|
||||
depth: 1
|
||||
---
|
||||
apiVersion: ax.io/v1alpha1
|
||||
kind: Task
|
||||
metadata:
|
||||
name: validation-46-lmdeploy-media-url-ssrf-facts
|
||||
atespace: default
|
||||
spec:
|
||||
command:
|
||||
- repo-facts
|
||||
env:
|
||||
- name: OUSAST_RUN
|
||||
value: validation-46
|
||||
- name: OUSAST_TASK
|
||||
value: lmdeploy-media-url-ssrf-facts
|
||||
- name: OUSAST_GIT_PINS
|
||||
value: '{"lmdeploy-media-url-ssrf-vulnerable/repo": "71648d239c978452720a6d6692fe914efc8a7b94"}'
|
||||
image: localhost:5001/ousast-runner@sha256:200e335877b52d68ea0bc53b4c9ba49ef2ee19e8a5ec2c874148b969123ef7ab
|
||||
resources:
|
||||
requests:
|
||||
cpu: 250m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: '1'
|
||||
memory: 1280Mi
|
||||
workspaces:
|
||||
- name: lmdeploy-media-url-ssrf-vulnerable
|
||||
path: /workspace/case
|
||||
- name: lmdeploy-media-url-ssrf-inputs
|
||||
path: /workspace/inputs
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"family": "untrusted_destination",
|
||||
"candidates": [
|
||||
{
|
||||
"candidate": "lmdeploy/vl/media/connection.py::_load_http_url",
|
||||
"site": "lmdeploy/vl/media/connection.py:68:_load_http_url",
|
||||
"a": true,
|
||||
"b": true,
|
||||
"c": null,
|
||||
"agreed": true,
|
||||
"disputed": false,
|
||||
"site_match": true,
|
||||
"usd": 0.022175,
|
||||
"turns": 10,
|
||||
"finding": {
|
||||
"candidate": "lmdeploy/vl/media/connection.py::_load_http_url",
|
||||
"site": "lmdeploy/vl/media/connection.py:68:_load_http_url",
|
||||
"reported_at": "lmdeploy/vl/media/connection.py:68",
|
||||
"family": "untrusted_destination",
|
||||
"title": "SSRF guard bypass via HTTP redirect in _load_http_url",
|
||||
"witness": "Source: an attacker-controlled HTTP request to the OpenAI-compatible RESTful API whose `messages` contain a multimodal c"
|
||||
}
|
||||
}
|
||||
],
|
||||
"agreed": [
|
||||
{
|
||||
"candidate": "lmdeploy/vl/media/connection.py::_load_http_url",
|
||||
"site": "lmdeploy/vl/media/connection.py:68:_load_http_url",
|
||||
"reported_at": "lmdeploy/vl/media/connection.py:68",
|
||||
"family": "untrusted_destination",
|
||||
"title": "SSRF guard bypass via HTTP redirect in _load_http_url",
|
||||
"witness": "Source: an attacker-controlled HTTP request to the OpenAI-compatible RESTful API whose `messages` contain a multimodal c",
|
||||
"passes": 2
|
||||
}
|
||||
],
|
||||
"disputed": [],
|
||||
"metrics": {
|
||||
"candidates": 1,
|
||||
"candidates_before_triage": 1,
|
||||
"asked_in_both": 1,
|
||||
"flagged_a": 1,
|
||||
"flagged_b": 1,
|
||||
"agreed": 1,
|
||||
"disputed": 0,
|
||||
"hunts": 2,
|
||||
"declared_sites": 1,
|
||||
"declared_sites_in_set": 1,
|
||||
"declared_sites_matched": 1,
|
||||
"declared_sites_matched_agreed": 1,
|
||||
"site_matching": "assessed",
|
||||
"usd_total": 0.022175,
|
||||
"cost_per_candidate": 0.022175,
|
||||
"recorded_triage_usd": 0.000768,
|
||||
"recorded_triage_basis": "derived per file from the batched-check scans: recorded usd (triage + hunts) minus the recorded hunt usage priced at deepseek-flash list prices; the triage call's own usage was not recorded",
|
||||
"usd_total_with_recorded_triage": 0.022943,
|
||||
"cost_per_candidate_with_recorded_triage": 0.022943,
|
||||
"turns_per_hunt": 5.0,
|
||||
"calls_per_hunt": 7.0,
|
||||
"tiebreak": {
|
||||
"asked": 0,
|
||||
"flipped_to_agreed": 0,
|
||||
"flipped_to_rejected": 0,
|
||||
"rule": "a candidate asked in pass c is agreed when at least 2 of passes a, b, c flagged it; a candidate not asked in pass c is agreed when passes a and b both flagged it (pass c alone never decides)"
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
[]
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"status": "done",
|
||||
"units_done": 1,
|
||||
"units_total": 1,
|
||||
"usd": 0,
|
||||
"calls": 0,
|
||||
"usage": {
|
||||
"prompt_tokens": 0,
|
||||
"prompt_cache_hit_tokens": 0,
|
||||
"completion_tokens": 0
|
||||
},
|
||||
"priced": true,
|
||||
"model": null,
|
||||
"pass": null,
|
||||
"metrics": {
|
||||
"candidates": 1,
|
||||
"candidates_before_triage": 1,
|
||||
"asked_in_both": 1,
|
||||
"flagged_a": 1,
|
||||
"flagged_b": 1,
|
||||
"agreed": 1,
|
||||
"disputed": 0,
|
||||
"hunts": 2,
|
||||
"declared_sites": 1,
|
||||
"declared_sites_in_set": 1,
|
||||
"declared_sites_matched": 1,
|
||||
"declared_sites_matched_agreed": 1,
|
||||
"site_matching": "assessed",
|
||||
"usd_total": 0.022175,
|
||||
"cost_per_candidate": 0.022175,
|
||||
"recorded_triage_usd": 0.000768,
|
||||
"recorded_triage_basis": "derived per file from the batched-check scans: recorded usd (triage + hunts) minus the recorded hunt usage priced at deepseek-flash list prices; the triage call's own usage was not recorded",
|
||||
"usd_total_with_recorded_triage": 0.022943,
|
||||
"cost_per_candidate_with_recorded_triage": 0.022943,
|
||||
"turns_per_hunt": 5.0,
|
||||
"calls_per_hunt": 7.0,
|
||||
"tiebreak": {
|
||||
"asked": 0,
|
||||
"flipped_to_agreed": 0,
|
||||
"flipped_to_rejected": 0,
|
||||
"rule": "a candidate asked in pass c is agreed when at least 2 of passes a, b, c flagged it; a candidate not asked in pass c is agreed when passes a and b both flagged it (pass c alone never decides)"
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"status": "done",
|
||||
"units_done": 1,
|
||||
"units_total": 1,
|
||||
"usd": 0.012376,
|
||||
"calls": 7,
|
||||
"usage": {
|
||||
"prompt_tokens": 68714,
|
||||
"prompt_cache_hit_tokens": 48512,
|
||||
"completion_tokens": 2127
|
||||
},
|
||||
"priced": true,
|
||||
"model": "deepseek-flash",
|
||||
"pass": "a",
|
||||
"family": "untrusted_destination"
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"path": "lmdeploy/vl/media/connection.py", "candidates": [["lmdeploy/vl/media/connection.py", "_load_http_url", 68]], "pass": "a", "flagged": [{"candidate": "lmdeploy/vl/media/connection.py::_load_http_url", "site": "lmdeploy/vl/media/connection.py:68:_load_http_url", "reported_at": "lmdeploy/vl/media/connection.py:68", "family": "untrusted_destination", "title": "SSRF guard bypass via HTTP redirect in _load_http_url", "witness": "Source: an attacker-controlled HTTP request to the OpenAI-compatible RESTful API whose `messages` contain a multimodal c"}], "turns": 5, "usage": {"prompt_tokens": 68714, "prompt_cache_hit_tokens": 48512, "completion_tokens": 2127, "calls": 7}, "usd": 0.01237569}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"status": "done",
|
||||
"units_done": 1,
|
||||
"units_total": 1,
|
||||
"usd": 0.009799,
|
||||
"calls": 7,
|
||||
"usage": {
|
||||
"prompt_tokens": 61163,
|
||||
"prompt_cache_hit_tokens": 46464,
|
||||
"completion_tokens": 2031
|
||||
},
|
||||
"priced": true,
|
||||
"model": "deepseek-flash",
|
||||
"pass": "b",
|
||||
"family": "untrusted_destination"
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"path": "lmdeploy/vl/media/connection.py", "candidates": [["lmdeploy/vl/media/connection.py", "_load_http_url", 68]], "pass": "b", "flagged": [{"candidate": "lmdeploy/vl/media/connection.py::_load_http_url", "site": "lmdeploy/vl/media/connection.py:68:_load_http_url", "reported_at": "lmdeploy/vl/media/connection.py:68", "family": "untrusted_destination", "title": "SSRF via unvalidated HTTP redirects in media URL fetch", "witness": "Source: an HTTP client submits a chat request whose multimodal content contains an attacker-controlled URL, e.g. {'type'"}], "turns": 5, "usage": {"prompt_tokens": 61163, "prompt_cache_hit_tokens": 46464, "completion_tokens": 2031, "calls": 7}, "usd": 0.00979898}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"status": "done",
|
||||
"units_done": 0,
|
||||
"units_total": 0,
|
||||
"usd": 0.0,
|
||||
"calls": 0,
|
||||
"usage": {
|
||||
"prompt_tokens": 0,
|
||||
"prompt_cache_hit_tokens": 0,
|
||||
"completion_tokens": 0
|
||||
},
|
||||
"priced": true,
|
||||
"model": "deepseek-flash",
|
||||
"pass": "c",
|
||||
"family": "untrusted_destination",
|
||||
"only": 0
|
||||
}
|
||||
Reference in New Issue
Block a user