{"version":"1.182.1","results":[{"check_id":"bash.curl.security.curl-pipe-bash.curl-pipe-bash","path":"host/30-agent.sh","start":{"line":14,"col":1,"offset":653},"end":{"line":14,"col":58,"offset":710},"extra":{"message":"Data is being piped into `bash` from a `curl` command. An attacker with control of the server in the `curl` command could inject malicious code into the pipe, resulting in a system compromise. Avoid piping untrusted data into `bash` or any other shell if you can. If you must do this, consider checking the SHA sum of the content returned by the server to verify its integrity.","metadata":{"owasp":["A03:2021 - Injection","A05:2025 - Injection"],"cwe":["CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')"],"category":"security","technology":["bash","curl"],"confidence":"LOW","references":["https://owasp.org/Top10/A03_2021-Injection"],"subcategory":["audit"],"likelihood":"LOW","impact":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Code Injection"],"source":"https://semgrep.dev/r/bash.curl.security.curl-pipe-bash.curl-pipe-bash","shortlink":"https://sg.run/KXz6"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"python.lang.security.audit.dynamic-urllib-use-detected.dynamic-urllib-use-detected","path":"pipeline/balance.py","start":{"line":12,"col":19,"offset":619},"end":{"line":12,"col":56,"offset":656},"extra":{"message":"Detected a dynamic value being used with urllib. urllib supports 'file://' schemes, so a dynamic value controlled by a malicious actor may allow them to read arbitrary files. Audit uses of urllib calls to ensure user data cannot control the URLs, or consider using the 'requests' library instead.","metadata":{"cwe":["CWE-939: Improper Authorization in Handler for Custom URL Scheme"],"owasp":"A01:2017 - Injection","source-rule-url":"https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/bandit/blacklists/calls.py#L163","bandit-code":"B310","asvs":{"control_id":"5.2.4 Dynamic Code Execution Features","control_url":"https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing-requirements","section":"V5: Validation, Sanitization and Encoding Verification Requirements","version":"4"},"category":"security","technology":["python"],"references":["https://cwe.mitre.org/data/definitions/939.html"],"subcategory":["audit"],"likelihood":"LOW","impact":"LOW","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Improper Authorization"],"source":"https://semgrep.dev/r/python.lang.security.audit.dynamic-urllib-use-detected.dynamic-urllib-use-detected","shortlink":"https://sg.run/dKZZ"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"python.lang.security.audit.dynamic-urllib-use-detected.dynamic-urllib-use-detected","path":"pipeline/fetch_deps.py","start":{"line":16,"col":10,"offset":713},"end":{"line":16,"col":50,"offset":753},"extra":{"message":"Detected a dynamic value being used with urllib. urllib supports 'file://' schemes, so a dynamic value controlled by a malicious actor may allow them to read arbitrary files. Audit uses of urllib calls to ensure user data cannot control the URLs, or consider using the 'requests' library instead.","metadata":{"cwe":["CWE-939: Improper Authorization in Handler for Custom URL Scheme"],"owasp":"A01:2017 - Injection","source-rule-url":"https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/bandit/blacklists/calls.py#L163","bandit-code":"B310","asvs":{"control_id":"5.2.4 Dynamic Code Execution Features","control_url":"https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing-requirements","section":"V5: Validation, Sanitization and Encoding Verification Requirements","version":"4"},"category":"security","technology":["python"],"references":["https://cwe.mitre.org/data/definitions/939.html"],"subcategory":["audit"],"likelihood":"LOW","impact":"LOW","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Improper Authorization"],"source":"https://semgrep.dev/r/python.lang.security.audit.dynamic-urllib-use-detected.dynamic-urllib-use-detected","shortlink":"https://sg.run/dKZZ"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"python.lang.security.audit.dynamic-urllib-use-detected.dynamic-urllib-use-detected","path":"pipeline/gateway.py","start":{"line":103,"col":22,"offset":6439},"end":{"line":103,"col":59,"offset":6476},"extra":{"message":"Detected a dynamic value being used with urllib. urllib supports 'file://' schemes, so a dynamic value controlled by a malicious actor may allow them to read arbitrary files. Audit uses of urllib calls to ensure user data cannot control the URLs, or consider using the 'requests' library instead.","metadata":{"cwe":["CWE-939: Improper Authorization in Handler for Custom URL Scheme"],"owasp":"A01:2017 - Injection","source-rule-url":"https://github.com/PyCQA/bandit/blob/b1411bfb43795d3ffd268bef17a839dee954c2b1/bandit/blacklists/calls.py#L163","bandit-code":"B310","asvs":{"control_id":"5.2.4 Dynamic Code Execution Features","control_url":"https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing-requirements","section":"V5: Validation, Sanitization and Encoding Verification Requirements","version":"4"},"category":"security","technology":["python"],"references":["https://cwe.mitre.org/data/definitions/939.html"],"subcategory":["audit"],"likelihood":"LOW","impact":"LOW","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Improper Authorization"],"source":"https://semgrep.dev/r/python.lang.security.audit.dynamic-urllib-use-detected.dynamic-urllib-use-detected","shortlink":"https://sg.run/dKZZ"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}}],"errors":[{"code":3,"level":"warn","type":["PartialParsing",[{"path":"pipeline/desk.sh","start":{"line":48,"col":12,"offset":0},"end":{"line":148,"col":6,"offset":5362}}]],"message":"Syntax error at line pipeline/desk.sh:48:\n `() {  # unpack one .lgx the way lgpm does\n  local lgx=$1 t name type dest\n  t=$(mktemp -d)\n  tar xzf \"$lgx\" -C \"$t\" || { echo \"desk: $lgx is not an lgx (gzip tar)\"; rm -rf \"$t\"; return 1; }\n  name=$(jq -r .name \"$t/manifest.json\"); type=$(jq -r .type \"$t/manifest.json\")\n  case \"$type\" in ui_qml|ui) dest=\"$U/plugins/$name\";; *) dest=\"$U/modules/$name\";; esac\n  [ -d \"$t/variants/linux-amd64\" ] || { echo \"desk: no linux-amd64 variant in $lgx\"; rm -rf \"$t\"; return 1; }\n  rm -rf \"$dest\"; mkdir -p \"$dest\"\n  cp -a \"$t/variants/linux-amd64/.\" \"$dest/\"; cp \"$t/manifest.json\" \"$dest/\"\n  [ -d \"$t/assets\" ] && cp -an \"$t/assets/.\" \"$dest/\" 2>/dev/null\n  echo linux-amd64 > \"$dest/variant\"\n  echo \"desk: installed $name ($type) $(jq -r .version \"$t/manifest.json\"), sha256 $(sha256sum \"$lgx\" | cut -c1-16)…\"\n  rm -rf \"$t\"\n}\nclock() {  # time and budget used and left, from the limits the sandbox and gateway set\n  python3 - <<'PY' 2>/dev/null\nimport json\ntry:\n    d=json.load(open(\"/run/logs/spend.json\"))\n    s,t=d[\"spent\"],d[\"testing\"]\n    print(f\"[budget] {s:.2f} of {t:.2f} DIEM for testing used\" + (\"; STOP TESTING and write the report now\" if s>=0.85*t else \"\"))\nexcept Exception: pass\nPY\n  read -r t0 max < /run/logs/clock 2>/dev/null || return 0\n  used=$(( ($(date +%s)-t0)/60 )); left=$(( max-used )); by=$(( max-40 ))\n  if [ \"$used\" -ge \"$by\" ]; then\n    echo \"[clock] ${used} of ${max} min used, ${left} left: STOP TESTING and write the report now\"\n  else\n    echo \"[clock] ${used} of ${max} min used, ${left} left; start the report by minute ${by}\"\n  fi\n}\nnextshot() { n=$(ls \"$M\"/*.png 2>/dev/null | wc -l); printf '%02d' $((n+1)); }\nocr() {  # one line per text line on screen: \"x,y  text\" (x,y = its centre)\n  f=\"$S/ocr.png\"\n  ffmpeg -loglevel error -y -f x11grab -video_size \"${W}x${H}\" -i :99 -frames:v 1 \"$f\" || return 1\n  # Basecamp is light text on dark. Inverted grey alone gives tesseract\n  # nothing at all (tried 2026-10-27); tripled and contrast-stretched it reads\n  # every label but the smallest.\n  # Doubled reads as many ... (truncated 3331 more characters)","path":"pipeline/desk.sh","spans":[{"file":"pipeline/desk.sh","start":{"line":48,"col":12,"offset":0},"end":{"line":148,"col":6,"offset":5362}}]},{"code":3,"level":"warn","type":["PartialParsing",[{"path":"pipeline/review-in-sandbox.sh","start":{"line":8,"col":1,"offset":0},"end":{"line":103,"col":31,"offset":5931}}]],"message":"Syntax error at line pipeline/review-in-sandbox.sh:8:\n `set -uo pipefail\nREVIEW_MODEL=${REVIEW_MODEL:-deepseek-v4-1-flash-1017}\n# The tokens go into pi's models.json, not into the environment of what the\n# reviewer runs. (Root in the sandbox can still read /proc/1/environ; the\n# gateway's hard cap is what holds whatever is read.)\nB=/run/behaviour; mkdir -p \"$B\" /run/media\n/usr/local/sbin/disguise.sh /usr/local/sbin/profiles.json \"$B/disguise.json\" >/dev/null 2>&1 || true\n/usr/local/sbin/bait.sh /root \"$B/bait.json\" >/dev/null 2>&1 || true\npython3 /pipeline/dns_sink.py \"$B/dns.log\" & SINK=$!\n\n# The reviewer's desktop: a screen, Basecamp and a recorder (see desk.sh).\nln -sf /pipeline/desk.sh /usr/local/bin/desk\n\n# pi points at the host gateway; the key stays on the host, calls carry the token.\nGW=\"${GATEWAY_URL:-http://host.containers.internal:${GATEWAY_PORT}}\"\nif ! curl -s -m3 -o /dev/null \"$GW/\" 2>/dev/null; then\n  g=$(ip route 2>/dev/null | awk '/default/{print $3; exit}')\n  [ -n \"$g\" ] && GW=\"http://$g:${GATEWAY_PORT}\"\nfi\nexport HOME=/root\nmkdir -p /root/.pi/agent\ncat > /root/.pi/agent/models.json <<JSON\n{\"providers\":{\"venice\":{\"baseUrl\":\"${GW}\",\"api\":\"openai-completions\",\"apiKey\":\"${REVIEW_TOKEN}\",\n \"models\":[{\"id\":\"${REVIEW_MODEL}\",\"name\":\"DeepSeek\",\"contextWindow\":1000000,\"maxTokens\":131072}]}}}\nJSON\n\n# Nothing runs in a sandbox that fails its own checks.\nif ! bash /pipeline/sandbox-check.sh \"$GW\" \"$B/sandbox-check.txt\" >/dev/null; then\n  { echo \"The sandbox failed its own checks, so no review was run:\"; grep FAIL \"$B/sandbox-check.txt\"; } > /run/logs/sandbox-check-failed.txt\n  kill $SINK 2>/dev/null; exit 0\nfi\n\n# The whole reviewer session is straced: its builds, its probes and anything the\n# module does when the reviewer runs it all land in one capture.\ncd /run/src 2>/dev/null || { echo '{\"error\":\"no source\"}' > \"$B/summary.json\"; kill $SINK 2>/dev/null; exit 0; }\n# A hard cap on the review's time (the proposal's promise); a run that hits\n# it is published with what it has and says so.\nMAX_MIN=${REVIEW_MAX_MIN:-150}\n# The reviewer's clock (desk time). Run 4 ne... (truncated 3900 more characters)","path":"pipeline/review-in-sandbox.sh","spans":[{"file":"pipeline/review-in-sandbox.sh","start":{"line":8,"col":1,"offset":0},"end":{"line":103,"col":31,"offset":5931}}]},{"code":3,"level":"warn","type":["PartialParsing",[{"path":"pipeline/review.sh","start":{"line":78,"col":47,"offset":0},"end":{"line":99,"col":57,"offset":1210}}]],"message":"Syntax error at line pipeline/review.sh:78:\n `' | while read l; do live \"  $l\"; done\nimport json,sys\ntry:\n d=json.load(open(sys.argv[1]))\n if d.get(\"bait_files_read\"): print(\"bait read during review: \"+\", \".join(d[\"bait_files_read\"]))\n if d.get(\"contacted_hosts\"): print(\"hosts contacted: \"+\", \".join(d[\"contacted_hosts\"]))\nexcept Exception: pass\nPY2\n\n# A review whose model failed, or that wrote no report, is a failed review,\n# never a quiet one: published as failed, with no verdict.\nif [ -s \"$RUN/logs/sandbox-check-failed.txt\" ]; then\n  cp \"$RUN/logs/sandbox-check-failed.txt\" \"$RUN/logs/failed.txt\"\nelif [ -s \"$RUN/logs/inference-failed.txt\" ]; then\n  { echo \"The model provider failed and kept failing, so the review could not be done:\"; cat \"$RUN/logs/inference-failed.txt\"; } > \"$RUN/logs/failed.txt\"\nelif [ ! -s \"$RUN/report.md\" ]; then\n  echo \"The reviewer wrote no report (see session.log for how it ended).\" > \"$RUN/logs/failed.txt\"\nfi\n[ -s \"$RUN/logs/failed.txt\" ] && { log \"FAILED: $(head -1 \"$RUN/logs/failed.txt\")\"; live \"## REVIEW FAILED\"; live \"$(cat \"$RUN/logs/failed.txt\")\"; }\n\nlog \"publish\"; \"$HERE/render.py\" \"$RUN\" \"$DEST\" \"$slug\" final 2>&1 | tee -a \"$RUN/logs/pipeline.log\"\nlog \"done -> ${REVIEW_BASE:-http://REVIEW-HOST}/$slug/\"\n` was unexpected","path":"pipeline/review.sh","spans":[{"file":"pipeline/review.sh","start":{"line":78,"col":47,"offset":0},"end":{"line":99,"col":57,"offset":1210}}]}],"paths":{"scanned":["BACKLOG.md","LICENSE","NOTES.md","README.md","docs/proposal.md","host/00-base.sh","host/10-shrooms.sh","host/20-web.sh","host/30-agent.sh","host/Caddyfile","host/models.json","pipeline/analyse.py","pipeline/balance.py","pipeline/desk.sh","pipeline/dns_sink.py","pipeline/fetch_deps.py","pipeline/gateway.py","pipeline/render.py","pipeline/review-in-sandbox.sh","pipeline/review-stop.sh","pipeline/review.sh","pipeline/reviewer-prompt.md","pipeline/reviewer.sh","pipeline/sandbox-check.sh","sandbox/bait.sh","sandbox/disguise.sh","sandbox/profiles.json","sandbox/record.sh","sandbox/reviewer.Containerfile","test-modules/README.md","test-modules/clean/Main.qml","test-modules/clean/README.md","test-modules/clean/metadata.json","test-modules/leaky-build/Main.qml","test-modules/leaky-build/README.md","test-modules/leaky-build/collect.js","test-modules/leaky-build/metadata.json","test-modules/leaky-build/package.json"]},"time":{"rules":[],"rules_parse_time":1.846134901046753,"profiling_times":{"config_time":4.421856164932251,"core_time":7.564779996871948,"ignores_time":0.007350921630859375,"total_time":12.03337574005127},"parsing_time":{"total_time":2.0758249759674072,"per_file_time":{"mean":0.014933992632859045,"std_dev":0.009303164707511118},"very_slow_stats":{"time_ratio":0.7511713185371948,"count_ratio":0.014388489208633094},"very_slow_files":[{"fpath":"pipeline/gateway.py","ftime":0.5671241283416748},{"fpath":"pipeline/render.py","ftime":0.9921760559082031}]},"scanning_time":{"total_time":12.028733491897583,"per_file_time":{"mean":0.11909637120690678,"std_dev":0.3060630086771222},"very_slow_stats":{"time_ratio":0.7699136003380628,"count_ratio":0.0297029702970297},"very_slow_files":[{"fpath":"pipeline/fetch_deps.py","ftime":1.8326771259307861},{"fpath":"pipeline/gateway.py","ftime":3.2317471504211426},{"fpath":"pipeline/render.py","ftime":4.1966612339019775}]},"matching_time":{"total_time":5.076853275299072,"per_file_and_rule_time":{"mean":0.036524124282727145,"std_dev":0.010275243944952724},"very_slow_stats":{"time_ratio":0.6879294722714983,"count_ratio":0.07913669064748201},"very_slow_rules_on_files":[{"fpath":"pipeline/render.py","rule_id":"python.django.security.injection.request-data-write.request-data-write","time":0.11304497718811035},{"fpath":"pipeline/render.py","rule_id":"python.django.security.injection.command.command-injection-os-system.command-injection-os-system","time":0.1309349536895752},{"fpath":"pipeline/render.py","rule_id":"python.django.security.injection.path-traversal.path-traversal-open.path-traversal-open","time":0.191864013671875},{"fpath":"pipeline/gateway.py","rule_id":"python.django.security.injection.path-traversal.path-traversal-open.path-traversal-open","time":0.228302001953125},{"fpath":"pipeline/gateway.py","rule_id":"python.flask.security.audit.directly-returned-format-string.directly-returned-format-string","time":0.29968905448913574},{"fpath":"pipeline/review.sh","rule_id":"bash.curl.security.curl-pipe-bash.curl-pipe-bash","time":0.3284139633178711},{"fpath":"pipeline/render.py","rule_id":"python.django.security.injection.raw-html-format.raw-html-format","time":0.34787988662719727},{"fpath":"pipeline/gateway.py","rule_id":"python.boto3.security.hardcoded-token.hardcoded-token","time":0.40032005310058594},{"fpath":"pipeline/render.py","rule_id":"python.lang.security.dangerous-system-call.dangerous-system-call","time":0.5306410789489746},{"fpath":"pipeline/fetch_deps.py","rule_id":"python.django.security.injection.ssrf.ssrf-injection-urllib.ssrf-injection-urllib","time":0.8095588684082031}]},"tainting_time":{"total_time":1.9215469360351562,"per_def_and_rule_time":{"mean":0.009956201741114799,"std_dev":0.0006763209454368657},"very_slow_stats":{"time_ratio":0.4478152135503313,"count_ratio":0.03626943005181347},"very_slow_rules_on_defs":[{"fpath":"pipeline/gateway.py","fline":71,"rule_id":"python.django.security.injection.raw-html-format.raw-html-format","time":0.05767703056335449},{"fpath":"pipeline/gateway.py","fline":41,"rule_id":"python.boto3.security.hardcoded-token.hardcoded-token","time":0.08417797088623047},{"fpath":"pipeline/fetch_deps.py","fline":1,"rule_id":"python.boto3.security.hardcoded-token.hardcoded-token","time":0.0966031551361084},{"fpath":"pipeline/render.py","fline":142,"rule_id":"python.boto3.security.hardcoded-token.hardcoded-token","time":0.1188650131225586},{"fpath":"pipeline/render.py","fline":1,"rule_id":"python.boto3.security.hardcoded-token.hardcoded-token","time":0.11925482749938965},{"fpath":"pipeline/gateway.py","fline":71,"rule_id":"python.boto3.security.hardcoded-token.hardcoded-token","time":0.1306629180908203},{"fpath":"pipeline/review.sh","fline":1,"rule_id":"bash.curl.security.curl-eval.curl-eval","time":0.25325703620910645}]},"fixpoint_timeouts":[{"error_type":"Fixpoint timeout","severity":"warn","message":"Fixpoint timeout while performing taint analysis at pipeline/fetch_deps.py:1:0 [rules: 1, first: python.boto3.security.hardcoded-token.hardcoded-token]","location":{"path":"pipeline/fetch_deps.py","start":{"line":1,"col":1,"offset":0},"end":{"line":1,"col":1,"offset":0}}},{"error_type":"Fixpoint timeout","severity":"warn","message":"Fixpoint timeout while performing taint analysis at pipeline/gateway.py:71:8 [rules: 1, first: python.boto3.security.hardcoded-token.hardcoded-token]","location":{"path":"pipeline/gateway.py","start":{"line":71,"col":9,"offset":4283},"end":{"line":71,"col":16,"offset":4290}}},{"error_type":"Fixpoint timeout","severity":"warn","message":"Fixpoint timeout while performing taint analysis at pipeline/render.py:142:4 [rules: 1, first: python.boto3.security.hardcoded-token.hardcoded-token]","location":{"path":"pipeline/render.py","start":{"line":142,"col":5,"offset":8503},"end":{"line":142,"col":22,"offset":8520}}},{"error_type":"Fixpoint timeout","severity":"warn","message":"Fixpoint timeout while performing taint analysis at pipeline/review.sh:1:0 [rules: 1, first: bash.curl.security.curl-eval.curl-eval]","location":{"path":"pipeline/review.sh","start":{"line":1,"col":1,"offset":0},"end":{"line":1,"col":1,"offset":0}}}],"prefiltering":{"project_level_time":0.0,"file_level_time":0.0,"rules_with_project_prefilters_ratio":0.0,"rules_with_file_prefilters_ratio":0.982400461627236,"rules_selected_ratio":0.0447201384881708,"rules_matched_ratio":0.0447201384881708},"targets":[],"total_bytes":0,"max_memory_bytes":779938432},"engine_requested":"OSS","skipped_rules":[],"profiling_results":[]}
