rule_remote_staging_then_execute has two branches. The docstring describes the first and the guarantee it makes:
Requiring the fetched basename to be the executed basename is what makes host-agnostic safe: it is not "you downloaded something and later ran something", it is "you ran the thing you just downloaded".
That is true of branch one, which intersects _fetched_files with _executed_files.
Branch two drops the requirement entirely:
https://github.com/blitzcrieg1/agentmetry/blob/master/apps/orchestrator/agentmetry/core/audit/detection/rules.py#L1032
fetch_idx = next((i for i, e in enumerate(events) if _is_staging_fetch(e)), None)
...
for event in events[fetch_idx + 1:]:
if _is_staging_fetch(event):
continue
if not _is_risky_exec_after_staging(event):
continue
Any fetch from a _STAGING_HOST, followed anywhere later in the session by anything matching RISKY_EXEC_AFTER_STAGING, returns critical. The two events are never compared. It is precisely "you downloaded something and later ran something", which the docstring names as the thing to avoid.
The trade was deliberate: branch two narrows the host list instead of correlating artifacts. The problem is what is on the other list.
https://github.com/blitzcrieg1/agentmetry/blob/master/apps/orchestrator/agentmetry/core/audit/detection/traits.py#L309
RISKY_EXEC_AFTER_STAGING = re.compile(
r"\b(bash|sh|zsh|dash)\s+[\w./~-]+\.(?:sh|bash)\b|"
r"\bpython\d?\s+[\w./~-]+\.py\b|"
r"\bpython\d?\s+-c\b|" # <-- any inline python at all
...
python -c with no argument constraint. So the rule reduces to:
Read anything off raw.githubusercontent.com, then run python -c on anything, and get a critical.
That is a normal working day for anyone who reads a README from GitHub raw and parses JSON in the same session.
BENIGN_AFTER_STAGING does not help. It exempts npm|yarn|pnpm|pip|cargo|go with install|run|build, and nothing else.
Observed
Dispositioned false_positive today on correlation 716fbfb9-29ed-442a-bbaa-9f559faf582a:
curl -s https://raw.githubusercontent.com/ottosulin/awesome-ai-security/main/README.md | grep -n "^#\|^##" | head -25
# ... later, unrelated ...
cd /tmp/awesome-ai-security-tools && python -c "
import json
d=json.load(open('data/sections.json', encoding='utf-8'))"
Fired critical: "Staged download from public host followed by execution."
The fetched artifact was a README, and it went to grep. The python -c read data/sections.json out of a local git clone. The fetched bytes and the executed program have nothing to do with each other, and the rule had no way to notice because it never looks.
Direction
Carry the fetched artifact forward into the second half of the check, the way branch one already does. _fetched_files and _executed_files exist and are used a few lines above.
Where the later command references nothing that was fetched, either do not fire, or fire well below critical. A staging-host fetch followed by unrelated execution is weak circumstantial evidence, and pricing it the same as running the downloaded file is what makes the strong signal unreadable.
At minimum, python -c should not be a bare match. Requiring the inline script to reference something fetched, or a path under the fetch's download directory, would keep the technique covered without catching every JSON parse in the session.
Related to #50, which is the same confusion of proximity with causation on the single-command path.
Blocked
rules.py and traits.py are ruleset fingerprint inputs. Hold with #44, #49 and #50 until the dogfood gate closes.
rule_remote_staging_then_executehas two branches. The docstring describes the first and the guarantee it makes:That is true of branch one, which intersects
_fetched_fileswith_executed_files.Branch two drops the requirement entirely:
https://github.com/blitzcrieg1/agentmetry/blob/master/apps/orchestrator/agentmetry/core/audit/detection/rules.py#L1032
Any fetch from a
_STAGING_HOST, followed anywhere later in the session by anything matchingRISKY_EXEC_AFTER_STAGING, returns critical. The two events are never compared. It is precisely "you downloaded something and later ran something", which the docstring names as the thing to avoid.The trade was deliberate: branch two narrows the host list instead of correlating artifacts. The problem is what is on the other list.
https://github.com/blitzcrieg1/agentmetry/blob/master/apps/orchestrator/agentmetry/core/audit/detection/traits.py#L309
python -cwith no argument constraint. So the rule reduces to:That is a normal working day for anyone who reads a README from GitHub raw and parses JSON in the same session.
BENIGN_AFTER_STAGINGdoes not help. It exemptsnpm|yarn|pnpm|pip|cargo|gowithinstall|run|build, and nothing else.Observed
Dispositioned
false_positivetoday on correlation716fbfb9-29ed-442a-bbaa-9f559faf582a:Fired critical: "Staged download from public host followed by execution."
The fetched artifact was a README, and it went to
grep. Thepython -creaddata/sections.jsonout of a local git clone. The fetched bytes and the executed program have nothing to do with each other, and the rule had no way to notice because it never looks.Direction
Carry the fetched artifact forward into the second half of the check, the way branch one already does.
_fetched_filesand_executed_filesexist and are used a few lines above.Where the later command references nothing that was fetched, either do not fire, or fire well below critical. A staging-host fetch followed by unrelated execution is weak circumstantial evidence, and pricing it the same as running the downloaded file is what makes the strong signal unreadable.
At minimum,
python -cshould not be a bare match. Requiring the inline script to reference something fetched, or a path under the fetch's download directory, would keep the technique covered without catching every JSON parse in the session.Related to #50, which is the same confusion of proximity with causation on the single-command path.
Blocked
rules.pyandtraits.pyare ruleset fingerprint inputs. Hold with #44, #49 and #50 until the dogfood gate closes.