top of page

Simon Willison Quotes Jeremy Morrell, but Safe AI Extensions Need More Than a Sandbox

Aug 20
13 min read

Simon Willison highlighted a concrete conflict on August 19, 2026: LLMs make software extensions easier to write, while their generated code remains difficult to trust.

The observation came from Jeremy Morrell, who argues that web applications can combine an accountable core with user-authored extensions. Large language models would generate those extensions, while browser sandboxes would limit what the resulting code can access.

That model challenges two familiar approaches. Traditional applications expose fixed features selected by their developers. General AI agents receive broad access and attempt to operate existing interfaces on a user’s behalf.

Morrell proposes a third route. The application keeps its dependable center, but users can describe missing capabilities as they encounter them. An LLM supplies bounded code rather than controlling the entire product.

The proposal sounds simple because browsers already contain isolation mechanisms. Yet code generation and safe execution solve only part of the problem. Products must also control permissions, data movement, updates, accountability, and recovery when an extension behaves incorrectly.

The real contest is therefore not fixed software against limitless customization. It is accountable extensibility against unrestricted AI agency.

Simon Willison Puts Extensible Software Back on the Agenda

The important event is not a product launch, but a sharper architectural hypothesis for AI software.

In his August 19 post, Simon Willison quoted Morrell’s argument about a new opportunity for extensible web software. The post tagged the idea under sandboxing, LLMs, AI, and generative AI.

Morrell’s hypothesis joins two changes that have often been discussed separately. LLMs reduce the effort required to produce small amounts of application code. Modern web platforms provide primitives that can restrict where that code runs and what it can do.

Neither change eliminates software engineering. Together, however, they alter the economics of a feature that serves only one person or one team.

A conventional product team must evaluate a request, design the interaction, implement it, test it, document it, and maintain it. That process makes sense for widely shared features. It rarely works for a narrow workflow used by several people.

An LLM can turn a specific request into code without waiting for the feature to enter a public roadmap. The resulting extension might transform a document, add a custom visualization, validate a form, or connect two permitted data sources.

That does not make the generated code correct. It does make the first implementation much cheaper to attempt.

The second half of Morrell’s argument concerns deployment. Historically, installing third-party extensions often meant trusting a package, granting broad permissions, or running code inside a privileged application process.

The browser offers a different foundation. A sandboxed frame creates a separate browsing context and can disable capabilities unless the host explicitly restores them.

The available controls are specific rather than symbolic. The host can restrict scripts, forms, popups, downloads, storage access, and top-level navigation. It can also apply a Permissions Policy to features such as cameras and microphones.

Those controls make a meaningful security boundary possible. They do not automatically produce the correct boundary for every extension.

Morrell’s phrase “solid, accountable core” is the decisive part of the proposal. The host application would continue to own identity, durable data, authorization, audit history, and critical operations.

Generated extensions would fill local gaps around that core. They would not silently replace its security model or become the authoritative record.

That distinction separates extensible software from a general coding chatbot. A chatbot can produce a file and leave the user responsible for running it safely. An extensible application can define where generated code lives, which interfaces it receives, and how its actions are reviewed.

It also separates the idea from ordinary plugin stores. Traditional plugins are usually authored for many users, packaged as products, and distributed through a review process. LLM-generated extensions can target one workflow and still remain inside a controlled runtime.

The event matters because Willison’s post gives that architecture a concise public frame. The claim is not that AI should redesign every interface. It is that AI can make carefully bounded customization economical.

That is a narrower argument than “agents will replace apps.” It is also easier to test.

The Pressure Falls on Fixed SaaS Products and Broad AI Agents

Products now face pressure to offer customization without surrendering control of user data or core workflows.

Fixed software works by predicting common needs. Its designers choose the available objects, commands, views, integrations, and automation rules before customers encounter their individual edge cases.

That model produces consistency. It also creates a permanent backlog of requests that are too specific to justify shared development.

Enterprise customers work around those gaps with spreadsheets, scripts, browser extensions, integration platforms, and manual procedures. Each workaround introduces another place where logic can become stale or invisible.

Extensible software moves that logic closer to the application that owns the relevant data. A generated extension can use a narrow interface defined by the host instead of scraping screens or copying records elsewhere.

Consider a project manager who wants a review panel based on several unusual metadata fields. The product may never ship that exact panel because few customers need it.

An extension could request approved records, calculate the required grouping, and render a temporary view. The core application would continue to enforce which records the user can read.

A researcher might want a one-off extractor for a recurring document format. An engineer might need a dashboard for a private deployment convention. A sales team might want a validation rule tied to its own account process.

These requests are too small for most roadmaps but too repetitive for manual work. They form the economic opening behind Morrell’s hypothesis.

Geoffrey Litt described a related vision in his earlier work on malleable software. Litt argued that LLMs can act like local developers inside computational environments that users already understand.

That historical reference matters because end-user programming is not new. Spreadsheets, macros, HyperCard, browser scripts, and visual automation tools all allowed people to modify their working environment.

The persistent bottleneck was not merely syntax. Users needed to translate an informal goal into executable logic, understand available interfaces, and debug the result.

LLMs compress parts of that translation process. A user can describe an outcome in domain language, inspect a proposed extension, and revise it through examples.

The extension still needs a stable substrate. Without defined objects and capabilities, the model must guess how the application works. That produces fragile code and encourages screen automation.

This puts pressure on SaaS vendors to expose smaller, safer building blocks. A product designed only for human clicks gives an LLM fewer dependable ways to extend it.

The same pressure applies to broad AI agents. An agent with access to email, files, browsing sessions, and internal tools can perform varied work. That access also expands the consequences of a mistaken instruction.

A bounded extension takes the opposite approach. It receives the minimum capabilities required for one job. The surrounding application mediates sensitive operations.

The tradeoff is reduced autonomy. A narrow extension cannot improvise across every service or retrieve arbitrary data. That limitation is the point, not a defect.

For buyers, the question becomes more concrete than whether a product “has AI.” They can ask whether users can create local capabilities without granting a model unrestricted access.

They can also examine whether the generated behavior remains visible. A hidden agent plan is difficult to audit after an error. An installed extension can expose its code, declared permissions, inputs, outputs, and revision history.

Fixed applications will not disappear under this model. Shared features still need professional design, accessibility work, performance testing, support, and long-term maintenance.

The likely pressure concerns the boundary around those features. Vendors that keep every workflow closed must compete with products that let users safely complete the final mile themselves.

Teams will also need better ways to preserve the context behind custom behavior. A searchable engineering knowledge base can document why an extension exists, which assumptions it makes, and who owns it.

That record becomes essential when generated extensions spread from one user to a department. Cheap creation does not remove the cost of institutional memory.

Sandboxes Lower Deployment Cost, Not Accountability Cost

A sandbox can constrain code execution, but the product must still design every meaningful path across the boundary.

A browser sandbox is not a single protective wall. It is a collection of restrictions covering origin, scripts, navigation, storage, device capabilities, and communication with the host.

The sandbox attribute on an iframe begins with a restrictive posture. The application can then restore selected abilities through explicit tokens.

This is a capability model, meaning code receives particular powers rather than inheriting every privilege held by its host. The host might allow rendering and calculations while denying downloads, top navigation, or same-origin storage.

Browser documentation also identifies a dangerous combination. A same-origin frame granted both scripts and same-origin privileges can remove its own sandbox attribute under certain conditions.

That warning illustrates the larger rule. A sandbox remains useful only when its configuration, origin design, and surrounding interfaces preserve the intended separation.

Serving extension code from a separate origin can reduce damage if that code becomes hostile. It also prevents direct access to the host page’s Document Object Model under the browser’s same-origin policy.

Communication can pass through postMessage, which lets windows exchange structured messages across origins. The host must still validate the sender, message type, payload, and requested operation.

An unsafe message bridge can undo a careful iframe configuration. If generated code can send “delete all records” to an unquestioning host, blocking direct database access provides little comfort.

The better design exposes narrow verbs. An extension might request readSelectedDocuments, renderChart, or proposeMetadataUpdate, subject to authorization and validation.

Sensitive changes should pass through the accountable core. That core can check the active user, current record version, allowed field set, and applicable organizational policy.

It can also require confirmation. Reading approved values for a chart is different from sending those values to an external server.

Content Security Policy adds another layer. A content policy lets sites restrict where scripts, images, frames, styles, and network requests may originate.

For generated extensions, network control matters as much as code execution. A harmless-looking widget can become a data-exfiltration channel if it can transmit application content to arbitrary domains.

A strict policy can block most outbound connections. The host could then proxy approved requests through a service that applies authentication, rate limits, logging, and destination rules.

WebAssembly offers another possible runtime for bounded computation. Its security model describes execution within a sandboxed environment and access through explicit APIs supplied by the embedder.

WebAssembly does not determine product permissions. It provides a lower-level execution format that can support isolation when paired with a carefully designed host.

Some extensions will need no arbitrary code at all. A product can have the LLM generate a declarative specification describing fields, filters, layout, calculations, and permitted actions.

The application then interprets that specification using trusted components. This approach limits expressiveness but makes behavior easier to inspect and validate.

Other tasks require real code. Data transformation, custom visualizations, and specialized parsing often exceed the limits of a fixed schema.

A mature platform might support several execution levels. Simple extensions use declarative rules. More complex ones run JavaScript or WebAssembly under stricter review and narrower permissions.

The host must treat model output as untrusted in every level. Natural language intent does not guarantee that generated code implements the same intent.

The model can misunderstand a field, invert a condition, omit an edge case, or depend on an undocumented behavior. It can also reproduce unsafe patterns learned from public code.

Prompt injection adds another risk. An extension that processes documents or webpages may encounter text designed to alter the model’s behavior.

OWASP’s prompt injection guidance explains why model instructions and external data cannot always be cleanly separated. Filtering alone does not eliminate the problem.

The runtime should therefore assume that generated logic can be wrong, even when no attacker is present. Permissions limit consequences, while tests and previews help detect errors.

A useful creation flow would show the requested behavior, generated implementation, declared inputs, permissions, and example output before installation.

The extension should receive test fixtures rather than production data during its first run. Users can compare expected and actual behavior without risking an irreversible change.

For write operations, the host can present a diff. The extension proposes mutations, and the core applies them only after validation or confirmation.

Rollback also matters. If an extension updates many records correctly according to the wrong rule, the sandbox has technically succeeded while the user has still suffered damage.

An accountable platform needs immutable history or compensating operations. It should identify which extension revision caused each change and who approved its execution.

This is where Morrell’s “accountable core” carries more weight than “modern sandbox primitives.” Sandboxing lowers the infrastructure cost of isolation. Accountability requires product design, governance, and operational discipline.

The generated extension must remain subordinate to those systems. Otherwise, the platform merely relocates broad AI agency into a smaller window.

The Missing Layer Is Governance for Disposable Code

Cheap code generation creates a maintenance problem because useful extensions rarely remain disposable.

A user may generate a one-off tool for a meeting and never open it again. That is the easiest case because the extension’s value and risk end together.

Successful extensions behave differently. Colleagues copy them, workflows begin to depend on them, and temporary assumptions become unofficial infrastructure.

At that point, authorship becomes complicated. The user supplied the intent, the model supplied much of the implementation, and the host supplied interfaces and runtime controls.

The platform still needs a responsible owner. Someone must decide whether the extension remains valid after application data, policies, or APIs change.

Generated code can be cheap to replace, but the workflow around it may not be. A team might rely on a report when making operational or financial decisions.

The accountable core should classify extensions by reach and consequence. A personal read-only view deserves a lighter process than an organization-wide automation with write access.

Promotion can trigger stronger controls. Sharing an extension might require automated tests, named ownership, permission review, and an expiration date.

Wider deployment might require approval from an administrator or application owner. The review should focus on capabilities and data flows, not only source code.

Code review alone is insufficient because generated code can change frequently. Reviewers need stable descriptions of what an extension reads, sends, changes, and retains.

Those descriptions should be enforced rather than decorative. If an extension declares that it reads selected records, the runtime should prevent access to unrelated records.

Versioning is equally important. Regenerating an extension after a user request creates new behavior, even when the visible name remains unchanged.

The platform should preserve each revision, its generating request, model configuration, permissions, tests, and approval status. Existing users should not receive silent changes.

Model updates introduce another uncertainty. The same instruction can produce different code after a provider changes a model.

Reproducibility may require storing the generated artifact rather than regenerating it on every run. The artifact can be tested and signed before execution.

Dependencies create a related risk. Allowing generated code to import arbitrary packages expands the trusted surface and complicates long-term operation.

A constrained standard library would be less flexible but more dependable. The host could provide reviewed components for charts, parsing, dates, storage, and user interaction.

Extensions could combine those components without downloading new code. When a vulnerability appears, the platform could update the shared component centrally.

The user experience also needs boundaries. Asking people to approve a long list of technical permissions leads to habituation rather than informed consent.

Permission requests should describe consequences in the language of the task. “Send selected documents to api.example.com” is more useful than a generic network-access prompt.

Defaults should favor read-only behavior, limited scopes, and temporary grants. Persistent access should require a reason connected to a recurring workflow.

The strongest objection to Morrell’s hypothesis is therefore not that sandboxing fails. It is that the attractive demo ends before governance begins.

A generated widget can look successful after one prompt. A dependable extension system must survive shared use, policy changes, malicious inputs, model changes, and personnel turnover.

That work can outweigh the initial cost of authoring code. It will not disappear because the application runs in a browser.

There is also a product-design risk. Endless customization can make an application harder to understand, support, and use consistently.

Two colleagues might see different commands, fields, and calculations inside what appears to be the same product. Support teams may struggle to reproduce an issue.

Organizations may respond by standardizing successful extensions. The platform can observe repeated local needs and promote mature solutions into supported features.

That creates a useful feedback loop. Users explore the long tail, while the vendor identifies patterns deserving permanent design and maintenance.

The model does not replace the product team in this loop. It helps users prototype evidence about unmet needs.

Extensions that remain narrow can stay local. Extensions that become important can move through stronger review and eventually enter the core.

This is more accountable than treating every generated artifact as either disposable or production-ready. It recognizes that software changes status as people begin depending on it.

The unresolved question is whether vendors will build this lifecycle before users create an uncontrolled shadow ecosystem. LLMs already make code generation easy enough to outrun governance.

What Simon Willison Readers Should Watch Next

The hypothesis will gain credibility when products expose constrained extension systems that ordinary users can operate without granting broad agent access.

The first signal is a real permission model designed for generated extensions. Watch for products that expose narrow capabilities, separate execution origins, outbound network controls, and readable permission manifests.

A convincing implementation will make denial the default. Extensions should receive only the data and operations required for their declared purpose.

The strongest evidence would come from a system that handles write access safely. Previews, diffs, confirmations, audit records, and rollback should work together rather than appear as separate options.

If vendors ship these controls, Morrell’s accountable-core model becomes materially stronger. If extensions routinely require broad tokens or full page access, the model weakens.

The second signal is how platforms manage an extension after its first successful run. Creation demos are plentiful, but lifecycle evidence remains more valuable.

Watch for version pinning, automated tests, ownership, expiration, dependency controls, and a promotion path from personal use to team use.

A platform should also show what happens after its API changes. Extensions need compatibility contracts or clear failures, not silent incorrect results.

Successful lifecycle management would demonstrate that cheap authoring does not produce unmanageable software debt. Frequent breakage would reinforce the skeptical view.

The third signal is user behavior. The theory depends on people creating specific tools that remain safer and more useful than general agents or external workarounds.

Useful measurements include extension reuse, permission denials, rollback frequency, time to repair, and the share of creations that become recurring workflows.

Those figures should be interpreted carefully. A high creation count can indicate experimentation, confusion, or novelty rather than durable value.

The more telling outcome is whether users solve previously neglected tasks without increasing security incidents or support burdens.

Researchers and enterprise buyers should also watch where extensions run. Browser isolation is attractive, but some workloads need local files, private services, or intensive computation.

Platforms may use remote containers, edge isolates, WebAssembly runtimes, or combinations of these systems. Each choice changes latency, cost, data exposure, and operational responsibility.

The browser remains valuable because it already mediates origins, permissions, and user interaction. Its controls are also widely understood by security teams.

Yet no runtime can infer the correct business authorization from generated code. The host must supply that policy from its trusted core.

For developers, the practical question is not whether LLMs can write an extension. They already produce useful code often enough to make the design space relevant.

The question is whether an application can make failure ordinary and recoverable. Bad output should be contained, visible, reversible, and inexpensive to replace.

For enterprise buyers, ask vendors to demonstrate a hostile or incorrect extension, not only a successful one. Observe which data it can access and which actions the host refuses.

For knowledge workers, look for customization that remains understandable after the chat ends. You should be able to inspect what the tool does, revise it, disable it, and identify its effects.

Simon Willison’s quotation matters because it frames AI-generated code as a component rather than the whole product. That modest framing gives the idea its credibility.

Morrell’s hypothesis does not require every user to become a software engineer. It requires applications to expose safe materials that an LLM can assemble under user direction.

The opportunity is real, but the winning product will not be the one that generates the most code. It will be the one that makes generated behavior accountable.

When evaluating the next extensible AI product, request one narrow customization and then deliberately give it a misleading input. Can you see its permissions, inspect its proposed changes, and reverse the result?

Those questions reveal more than a polished generation demo. They test whether the product has built the solid core Morrell describes.

Keep watching Simon Willison’s coverage for concrete implementations, but apply the same standard to each one. Does the system merely run AI-written code, or does it make that code governable throughout its useful life?

Give every agent the context to do better work

Connect your agents to the knowledge, decisions, and history already organized in remio.

remio currently supports Windows 10+ (x64) and Macs with Apple silicon.

Your AI Partner at Work
Get more done with remio

Plan. Create. Deliver.
All in one place.

bottom of page