Three fresh mechanisms look
like containment if you name
them loosely. An install-token
names a workload. Assisted
permissions names a
confidence. A web view names
a JavaScript engine. None of
them is the fence. The fence
has to sit outside the thing
that is asking to proceed.
Identity first. Server-to-server
Copilot auth removes the
signed-in person on purpose.
What replaces the person is
not "the org" as a fog. It is
a GitHub App, a read-only
Copilot Requests permission,
a short-lived installation
token, org billing, and an
app_client_id in
the usage CSV. The token
dying does not revoke the
grant. Suspending or
uninstalling the app does.
If the job cannot name the
app, it does not have an
identity yet. It has a missing
user, which is a different
bug.
Approval second. Assisted
permissions runs after the
rules you already wrote. A
deny still denies. An allow
you already granted never
even reaches the model. The
trap is the middle: in Copilot
CLI, an enterprise ask rule
can be satisfied by the
review model, so a policy that
says "ask" becomes "the model
may say yes." That reviewer
does not cover a sandbox
bypass, and it does not cover
every other tool call your
policy reserved for a person.
In a non-interactive run, a
request that still needs a
human is denied, then the
explanation is passed back so
the agent can try another
approach. That is a hint for
a retry, not a stop, unless
the harness also refuses the
next attempt. GitHub says the
model can approve a dangerous
action. Believe that sentence.
Runtime third. A tool that
has no fs and no
process is a
useful layer. It is not a
sandbox while the page can
reach localhost, keep cookies
between runs, and lie about
its own result. The published
webframe probes, which are
labeled as model-written, are
still a clean checklist of
what "outside" means: empty
network namespace, ephemeral
profile, a real process
sandbox, a timeout that kills
the group, a fresh process,
and a nonce so the page
cannot forge the answer.
Wrapping only the renderer
left the network process
outside the wrap. Same shape
as Assisted: the inner
classifier is not the outer
wall.
-
Name the GitHub App before
the first server-to-server
call. Record
app_client_id.
Revoke by suspending the
app, not by waiting for the
token to expire.
-
If Assisted is on, treat
CLI ask rules as
model-satisfiable. Keep
deny rules. Do not let the
review model approve a
sandbox bypass.
-
In a non-interactive run,
a denied approval is not a
stop unless the harness
also refuses the next
attempt. The docs hand the
explanation back so the
agent can try again.
-
Do not run untrusted page
JavaScript in a stock web
view and call it contained.
Put the network namespace,
the ephemeral profile, the
timeout, and a fresh
process outside the tool.
-
Stop when the app is named,
Assisted is not your only
fence, and a sandbox bypass
still requires a person. Do
not inventory every
auto-approved command to
feel finished.
The thing that asks for
permission cannot be the thing
that proves the permission was
safe. Write the no where the
asker cannot edit it.
The notes this sits on are
GitHub's
server-to-server auth,
assisted permissions, and
Willison's webframe evaluation.