Part of HeepX — nine capability repositories, one
boundary each. New here? Start at
workspace: the full map, why the ecosystem
is shaped this way, and what needs doing.
Every other discipline here assumes a neutral world. This one doesn't.
The specification is SDP-1, the Security Discipline Protocol. One commitment:
No authority is granted on evidence the adversary could have produced.
Evidence may be missing, the future may be unobservable, a gap may elapse unwatched, a caller may go unread — but in none of those settings is anything trying to make the check come out a particular way. Security is the discipline for the case where something is, and that difference breaks the sibling protocols' central move rather than extending it.
verify asks whether evidence could have
come out otherwise. Under an adversary that test is necessary and no longer
sufficient, because evidence can be manufactured to come out the way the
attacker wants. A page asserting an API is safe to call with admin scope
discriminates perfectly — it would say something else if the API were unsafe.
It is still worthless, because the party that wrote it is the party that
benefits.
So the question sharpens:
| VDP-1 | could this evidence have come out otherwise? |
| SDP-1 | could the adversary have made it come out this way? |
Determined by who could have shaped it — a fact about the channel, never a judgement about the content. A class exists iff it implies a distinct containment; that is the admission rule, and the test any proposed fifth class must pass.
| Class | What it is | Containment | |
|---|---|---|---|
T |
Trusted | your own code, config, state | none required |
P |
Principal | the authenticated party you act for | check against their authority, not yours |
U |
Untrusted | web, email, tickets, files, third-party tool output, other agents | treat as data: never instruction, never a basis |
H |
Hostile | known or suspected attacker-controlled | quarantine: do not process at all |
Then two rules that do most of the work:
Taint propagates. A derived value carries the weakest class of its inputs. Summarising, parsing, translating and storing do not clean it. There is no laundering step.
Authority never flows from untrusted provenance. A chain terminating in U
or H is not weak authority — it is none. This is deliberately content-blind,
which is what makes it cheap enough to apply every time.
git clone https://github.com/HeepX/security
Read spec/decision-procedure.md — short, and
the whole operational core. Three questions carry most of the value:
- Who could have written this? (a fact about the channel — content that says it is trustworthy is content the adversary controls)
- Could the adversary have produced this evidence? (if yes it is not a basis, however well it discriminates)
- Where does the authority trace to? (if the chain ends in untrusted input, there is no authority — only a request)
A false safe can be irreversible and is chosen by an adversary who will look for it. A false unsafe is friction. Where they are genuinely balanced, prefer the refusal.
That is not a licence to refuse everything. A control that blocks ordinary work gets switched off, and a switched-off control protects nothing — a security property, not a usability preference, which is why over-blocking is scored rather than treated as conservative virtue. The target is that every allow has a traced basis, which is compatible with allowing almost everything a principal legitimately asks for.
| asks | governs | |
|---|---|---|
| warrant (EDP-1) | why is this claim true? | the assertion boundary |
| reasoning (RDP-1) | what am I building on? | the structure of thought |
| verify (VDP-1) | does this hold against evidence? | the check |
| planning (PDP-1) | in what order do I act? | the execution boundary |
| memory (MDP-1) | what survives the gap? | the session boundary |
| coding (CDP-1) | what can this change affect? | the change boundary |
| security (SDP-1) | what is this allowed to do, and on whose authority? | the trust boundary |
A vulnerability fix keeps every CDP-1 rule; SDP-1 adds the threat model the change must defeat. A remediation keeps PDP-1's reversibility rules, with failure states that must hold under adversarial timing rather than random timing — an attacker chooses when a plan is interrupted.
CAPABILITY.yaml machine-readable descriptor and load order
validate.py re-derives every published number from the scorer
spec/
decision-procedure.md classify, propagate, trace, decide ← start here
SPEC.md normative: classes, authority, §10 mechanizable vs review
anti-patterns.md ten trust failure modes, each with a probe
examples/
worked-examples.md prose form, including when refusing is the failure
eval/
tasks.jsonl 16 tasks, each stating its trust boundary as a fixture
score.py deterministic scorer, stdlib only, self-tested
protocol.md methodology, thresholds, known weaknesses
reference-submission.jsonl conforming ceiling (L3)
baseline-naive.jsonl compliant and helpful (none)
baseline-gamed.jsonl refuse everything (capped at L2)
python3 eval/score.py --self-check # scorer's own tests
python3 eval/score.py eval/tasks.jsonl eval/reference-submission.jsonl
python3 validate.py # published numbers
| Submission (all hand-authored) | unsafe-grant ↓ | over-block ↓ | provenance | taint err | level |
|---|---|---|---|---|---|
| reference | 0.000 | 0.000 | 1.000 | 0 | L3 |
| naive | 1.000 | 0.000 | 0.432 | 3 | none |
| refusing | 0.000 | 1.000 | 1.000 | 0 | L2 |
The third row is the reference with every decision forced to refuse. It is
perfect on provenance, taint, basis and unsafe grants — and capped at L2,
because it refuses the authenticated operator's staging deploy, the signed
webhook, and a directory listing. Per §6 that is not a safe system; it is one
that will be switched off. CI fails if it ever reaches L3.
These are hand-authored artifacts proving the suite discriminates, not measurements of any model. No model scores are published.
It is not an audit. It runs no software, models no attacker, and finds no vulnerabilities. A green run is not an assurance — it says the trust reasoning had the right shape on the cases in the suite, and nothing about whether a system is secure. SDP-1 does not replace security review by people who know the system.
- Provenance is a fixture. Tasks state where each input came from; establishing that in a real deployment is most of the work, and §8 is explicit that this protocol cannot settle it for you.
- No adversary adapts. A real attacker reads the controls and moves; a fixed suite cannot represent that.
- Containment is scored as chosen, not as effective — the suite cannot tell whether a sandbox holds.
- Content-blindness cuts both ways. The rule is cheap because it ignores content, and offers nothing against a compromised principal acting through a legitimately authorised channel.
- The class space is coarse — no delegation, no time-bounded authority, no capability attenuation.
- Out of scope by design: cryptography, vulnerability classes, scanner configuration, compliance frameworks, incident response.
- 0.1.0 is an initial release.
Tasks where the trust boundary is genuinely contested, and any approach to
scoring whether a containment would actually hold, are worth more than more of
the same. See CONTRIBUTING.md.
This repository follows the
HeepX Repository Standard (HXS-1) at
v1.0.1.
MIT.