Skuld is the Expectation pipeline of the Asgard suite (Expectation dimension of the O/D/E framework): purpose-conditioned counterfactual analysis of an app's data practices, resulting in E claims.
Skuld compares what an app does in a baseline run with what it does in a counterfactual run in which a data flow is withheld or changed. Only Heimdall and Loki touch the device:
- Loki drives the app in both runs and applies the intervention from its configuration: it
controls Heimdall's capture (app scope, blocked hosts) and instruments the app with Frida
(a data source passed through or changed). Skuld reads the run folders Loki writes, and is to ask
Loki for runs through Loki's command line (
loki -c … replay …, with a configuration that differs in the one setting of the condition), which is not built yet. - Verðandi annotates the captured messages. The records pass between the components in the formats of Ratatoskr.
Skuld owns the vocabulary of interventions, Loki the mechanisms: Skuld's transformation "location
granularity, from precise to two decimals" becomes instrumentation.sources.location: "round:2"
in Loki's configuration. Verification is layered: Loki records whether the app was handed what
the settings say; Skuld decides whether the intervention held, which also needs the traffic and,
for a claim, the functional oracle. A run that Loki did not verify is invalid for Skuld.
Python 3.12 or newer.
pip install -e ".[dev]"Ratatoskr comes from its tag 0.3.0 over SSH. To work on both, install a checkout of it in editable
mode afterwards: pip install -e "../Ratatoskr[validate]".
from skuld.runs import RunRefused, load
run = load("../Loki/runs/com.example.app/<run id>") # RunRefused if Skuld cannot rely on it
run.actions # what was done to the app, Loki's 'action' events
run.source_reads # what the app read of an instrumented source, and what it was handed
run.changes # source settings changed during the run, with their times
run.messages # the captured HTTP messages (captured_http_message)
run.connections # the captured connections (captured_connection)
run.verified # Loki's verification of the instrumentation; run.verification has the details
run.scans # by package: the permissions an app requests and its tracker libraries (if the run exported scans)A run is refused (RunRefused.reason) if the folder is not a run (not_a_run), its record is of a
version Skuld does not read (unsupported_version), it did not end in order (unfinished), was not
captured or its capture failed (no_capture, capture_failed; load(…, capture=False) does not
read the capture), Loki did not validate its export (export_not_validated), the export is not
complete (incomplete_export), or its instrumentation record or its scans do not conform to
Ratatoskr's schemas (invalid_record), which Skuld checks again itself.
pytest
ruff format . && ruff check .One test reads a real run of Loki: SKULD_RUN_DIR, or the latest captured and instrumented run in
the sibling Loki/runs/. It is skipped if there is none.
GPL-3.0-only, see LICENSE.