Repository navigation
Expand file tree
/
Copy pathsecurity.html
More file actions
154 lines (145 loc) · 10.4 KB
/
Copy pathsecurity.html
File metadata and controls
154 lines (145 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<!doctype html>
<html lang="en"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Capabilities and the supply chain</title>
<meta name="description" content="A Grasm package declares what it may reach, and the compiler enforces it.">
<link rel="icon" href="favicon.svg" type="image/svg+xml">
<link rel="preload" href="vendor/fonts/figtree.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="vendor/fonts/sora.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="style.css">
<script src="vendor/motion.js" defer></script>
<script src="vendor/lottie.js" defer></script>
<script type="module" src="app.js"></script>
</head><body data-page="security">
<header class="topbar">
<a class="brand" href="index.html"><svg viewBox="0 0 48 48" width="20" height="20" fill="none" stroke="currentColor" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 6H39"/><path d="M24 14A13 13 0 1 0 37 27H26"/></svg><span>Grasm</span></a>
<span class="ver">v1.0.0</span>
<nav>
<a href="different.html">Why Grasm</a>
<a href="start.html">Docs</a>
<a href="security.html">Security</a>
<a href="achieved.html">Scorecard</a>
<a href="playground.html">Playground</a>
</nav>
<a class="cta" href="start.html">Get started</a>
</header>
<div class="frame">
<nav class="rail">
<a class="mark" href="index.html"><svg viewBox="0 0 48 48" width="18" height="18" fill="none" stroke="currentColor" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 6H39"/><path d="M24 14A13 13 0 1 0 37 27H26"/></svg><b>grasm</b><span>a systems language</span></a>
<h2>Start</h2>
<a href="different.html">Why Grasm</a>
<a href="start.html">Getting started</a>
<a href="install.html">Install</a>
<a href="playground.html">Playground</a>
<h2>Learn</h2>
<a href="tutorial.html">Tutorial</a>
<a href="tour.html">Tour</a>
<a href="effects.html">Effects</a>
<a href="tiers.html">Ownership</a>
<a href="errors.html">Errors</a>
<a href="concurrency.html">Concurrency</a>
<a href="security.html" aria-current="page">Security</a>
<h2>Reference</h2>
<a href="syntax.html">Syntax</a>
<a href="language.html">Language</a>
<a href="library.html">Library</a>
<a href="packages.html">Packages</a>
<a href="spec.html">Specification</a>
<a href="architecture.html">Architecture</a>
<h2>More</h2>
<a href="examples.html">Examples</a>
<a href="achieved.html">Scorecard</a>
<a href="performance.html">Performance</a>
<a href="about.html">About</a>
<a href="status.html">Status</a>
<a href="roadmap.html">Roadmap</a>
</nav>
<main>
<p class="eyebrow">Learn</p>
<h1>A dependency cannot quietly grow teeth.</h1>
<p class="lede">When you install a library that says it does arithmetic, nothing
in Python, Go, Rust or Zig stops it from opening your files or reaching the
network. Grasm writes that permission down and refuses the build when it is
exceeded.</p>
<h2>The attack</h2>
<p>A trusted, pure library ships a patch release. Same name, same signature,
same return value — and it now reads <code>/etc/passwd</code> and writes it
out. Nothing about the call site changes. This is not hypothetical; it is the
shape of every dependency compromise of the last decade.</p>
<div class="term">
<div class="chrome"><span class="dot"></span><span class="dot"></span><span class="dot"></span>
<span>app — grasm build</span></div>
<div class="body"></div>
</div>
<div class="verdicts"><div class="verdict-row" data-result="refused"><span class="lang"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m4 12 5 5L20 6"/></svg>Grasm</span><span class="out">COMPILE ERROR</span><span class="why">inferred effects (io) exceed the declared ceiling ([])</span></div><div class="verdict-row" data-result="clean"><span class="lang"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg>Rust</span><span class="out">builds clean</span><span class="why">std::fs is ambient; no capability is recorded</span></div><div class="verdict-row" data-result="clean"><span class="lang"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg>Go</span><span class="out">builds clean</span><span class="why">os.ReadFile is importable by any package</span></div><div class="verdict-row" data-result="clean"><span class="lang"><svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg>Python</span><span class="out">compiles clean</span><span class="why">open() needs no import and no declaration</span></div></div><div class="actions"><button class="btn ghost" data-run-verdicts>Run it again</button></div>
<p>Only Grasm’s toolchain refuses. Everywhere else the tampered code builds,
ships and runs; detection is left to runtime sandboxing or to a reviewer
noticing — neither of which the toolchain does.</p>
<h2>How it works</h2>
<p>Two halves. The first is the effect row, which is <em>inferred</em>, so it
cannot be wrong about the body:</p>
<pre><code><span class="cm">// the row is worked out from the body, then checked against what you wrote</span>
<span class="kw">fn</span> <span class="fn">load</span><span class="op">(</span>path<span class="op">:</span> <span class="ty">str</span><span class="op">)</span> <span class="op">-></span> <span class="ty">str</span> <span class="op">!</span> <span class="ty">IoError</span> <span class="op">/</span> <span class="op">{</span>io<span class="op">}</span> <span class="op">{</span>
<span class="kw">try</span> <span class="fn">read_file</span><span class="op">(</span>path<span class="op">)</span>
<span class="op">}</span></code></pre>
<p>The second is the manifest, which is the ceiling for the whole package:</p>
<pre><code><span class="op">[</span>package<span class="op">]</span>
name <span class="op">=</span> <span class="st">"mathlib"</span>
version <span class="op">=</span> <span class="st">"1.0.1"</span>
capabilities <span class="op">=</span> <span class="op">[</span><span class="op">]</span> # this package may perform no <span class="kw">effect</span> at all</code></pre>
<p>Add the <code>read_file</code> and the package performs <code>io</code>,
which exceeds <code>[]</code>. The error names the exact place:</p>
<pre><code>error<span class="op">:</span> package `mathlib` performs `io` but its manifest only permits nothing
help<span class="op">:</span> either add the capability to that package's manifest<span class="op">,</span> <span class="kw">or</span> stop it
from performing the <span class="kw">effect</span>
performed<span class="op">:</span> `io` at mathlib<span class="op">/</span>src<span class="op">/</span>main<span class="op">.</span>gr<span class="op">:</span><span class="nu">2</span><span class="op">:</span><span class="nu">9</span></code></pre>
<p>The maintainer <em>can</em> raise the ceiling — but the manifest is in the
diff, and a package that used to declare <code>[]</code> and now declares
<code>["io"]</code> is one line a consumer can see, refuse, or gate in CI.
That is the whole design: make the change visible where a human is already
looking.</p>
<h2>What this does not do</h2>
<p class="note"><strong>This is a build-time check, not a sandbox.</strong> It
constrains what code in a Grasm package can be <em>written</em> to do. It does
not contain a process that is already running, it does not survive
<code>unsafe</code>, and it says nothing about a compromised compiler or
operating system.</p>
<ul>
<li><code>unsafe</code> and <code>extern fn</code> reach C, and C is outside
this. That is why the tier is called Tier 3, why every call must sit inside an
<code>unsafe</code> block, <em>and</em> why the package must additionally
declare the <code>unsafe</code> capability — so a consumer can refuse the
whole package by reading one line.</li>
<li><code>exit</code> performs no effect and can still end the process. So
can a panic and an endless loop. A ceiling bounds what a dependency can
<em>reach</em>, never how long it runs.</li>
</ul>
<h2>Prior art</h2>
<p>This stands on proven ground. <a href="about.html">Austral</a> pioneered
capability-secure modules, Wyvern did capability-safe modules before that, and
the effect row is <a href="about.html">Koka</a>’s. What no one had shipped is
the combination, with a gate that proves it:
<code>security_bench.sh</code> runs the real attack against four toolchains on
every green build, and three of them wave it through.</p>
</main>
</div>
<footer class="sitefoot">
<div class="inner">
<div class="cols">
<div class="brandcol">
<a class="brand" href="index.html"><svg viewBox="0 0 48 48" width="20" height="20" fill="none" stroke="currentColor" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 6H39"/><path d="M24 14A13 13 0 1 0 37 27H26"/></svg><span>Grasm</span></a>
<span>Four engines, one answer.</span>
</div>
<div class="links">
<div><span>Start</span><a href="different.html">Why Grasm</a><a href="start.html">Getting started</a><a href="install.html">Install</a><a href="playground.html">Playground</a></div>
<div><span>Learn</span><a href="tutorial.html">Tutorial</a><a href="tour.html">Tour</a><a href="effects.html">Effects</a><a href="tiers.html">Ownership</a><a href="errors.html">Errors</a><a href="concurrency.html">Concurrency</a><a href="security.html">Security</a></div>
<div><span>Reference</span><a href="syntax.html">Syntax</a><a href="language.html">Language</a><a href="library.html">Library</a><a href="packages.html">Packages</a><a href="spec.html">Specification</a><a href="architecture.html">Architecture</a></div>
<div><span>More</span><a href="examples.html">Examples</a><a href="achieved.html">Scorecard</a><a href="performance.html">Performance</a><a href="about.html">About</a><a href="status.html">Status</a><a href="roadmap.html">Roadmap</a></div>
</div>
</div>
<p>Counts here are computed from the repository as the page is written;
measurements are read from the document that recorded them.</p>
</div>
</footer>
</body></html>