Skip to content
AppCrane
// blog · appcrane

The future of application platforms defends itself.

The next application platform will not just run your code. It will watch every deploy, refuse what is broken at the door, draft its own fix and wait for one human nod. AppCrane already works that way. You still own the app. You are just no longer the only thing standing between it and an attacker.

Diagram in two rows. Catch and block: 1, every deploy and a daily scan check lockfiles against OSV and images with a pinned Trivy on the resolved digest; 2, a finding is recorded on the deployment, proxy-addr 2.0.7, advisory GHSA-jqcg-44mw-7w3h, fixed in 2.0.8; 3, the release check refuses the production deploy because a published fix exists, and the current version keeps running. Route and fix: 4, a request Upgrade proxy-addr 2.0.7 to 2.0.8 lands in the owner's queue once per advisory; 5, the coder bumps the package to the fixed version and deploys it to the sandbox; then the flow splits: 6a, a remote-code-execution fix is approved by policy and promoted once health and the release check pass; 6b, every other fix waits for a person who reviews, releases and promotes; 7, released: the fix is live in production and the request closes itself on a clean scan.
Scan → block → request → coder → RCE fixes ship on policy, the rest wait for a person → released

It is 2 a.m. An advisory goes out for a package you have never heard of. It sits four levels down in a lockfile, pulled in by something that was pulled in by something else, and it is running in production right now, inside an app someone built in an afternoon with an AI agent and shipped before lunch.

Nobody is awake. Nobody remembers that app exists. That is how most of these stories start: not with a brilliant attacker, but with a forgotten dependency, a key pasted where it should never be, or an admin page that nobody thought to lock.

Three ways an internal app gets you

None of this is exotic. On most platforms, each one is a developer's problem, alone, at 2 a.m. Here is what changes when the app runs on AppCrane.

Every deploy is scanned

Every deploy scans what it just shipped and records the result against that deployment. Apps built from source are read from their lockfiles (npm, yarn, pnpm, Composer, Go, Cargo, RubyGems, pip and Poetry) and checked against OSV. Apps deployed from an image are scanned with a pinned Trivy against the resolved digest: the bytes actually running, not whatever the tag points at today. Each finding carries the version that fixes it.

The report does not hide behind a reassuring word. It opens with arithmetic: how many app-and-stage rows have a usable scan result, out of how many, as a percentage, with the skipped and errored rows counted beside it. "Partial" can mean one per cent or ninety-nine, so it never travels alone.

A daily digest goes to each person scoped to what they are allowed to see: the whole fleet for a platform admin, their own apps for an app owner. The forgotten app is no longer forgotten. The daily scan re-checks what is running, and its owner hears about it in the next digest.

Production has a door, and it locks

The scan itself never blocks: a scanner that is missing, slow or wrong cannot fail your deploy. What stands at the door is the release check, which runs on every production deploy and promote. It looks at the app's intake, the dependency and image scan, secrets committed in the code, the required access rules, whether the single sign-on gate has been bypassed, and the health of the sandbox.

By default, a dependency with a known vulnerability and a published fix blocks production, for every app. The deploy is refused before it starts, and the version already in production keeps running. The other checks block apps classified confidential or restricted and warn for the rest.

Sometimes you need to ship anyway. An app owner or platform admin can record an exception for one check, with a reason and an expiry of at most 90 days, and the exception goes in the audit log. A platform admin can also turn dependency blocking off in Settings → Security.

The fix files itself

A finding that only lives in a report is a finding nobody fixes. So each advisory becomes an ordinary request in the app owner's queue, reading something like Upgrade proxy-addr 2.0.7 → 2.0.8 (GHSA-jqcg-44mw-7w3h), with the ecosystem, the environment it was found in and the advisory link. It is opened once per app, package and advisory, so the daily scan does not bury anyone in duplicates.

For an app whose code AppCrane hosts, the owner can tick the request and press Send to coder. The in-platform coder works on the sandbox and leaves its change for a person to review; nothing reaches production until someone releases it, promotes it and the release check passes.

A remote-code-execution advisory does not wait for anyone. With RCE auto-patch, on by default, AppCrane bumps only the vulnerable npm package to its fixed version, deploys it to the sandbox, runs the release check and promotes it to production on its own, under a written, audited policy. It only acts when the branch is exactly what production runs, waits a day after the fixed version is published, and rolls production back if its health check fails. Every other fix still goes to a person. When the latest successful scan of every environment no longer finds the advisory, the request closes itself. A failed scan never closes one.

The 2 a.m. job used to be: notice, triage, find the package, upgrade, test, ship. Here, it can shrink to reading a diff and pressing Release.

The doors the agent forgot

Dependencies are half the story. The other half is what an AI-built app was supposed to do and did not.

Sign-in it never wrote

Apps on AppCrane do not implement their own authentication. Every request passes through AppCrane's proxy first, which removes any X-AppCrane-* header the browser sent, checks the session (single sign-on over OIDC or SAML, or a local sign-in), and only then hands the app the verified identity. No session means a sign-in page, not the app. The identity headers are also signed per app and environment, so the app can reject any request that did not come through AppCrane.

The admin page it never locked

An app can declare in deployhub.json that /admin/* needs the admin role. AppCrane's gate then answers everyone else with a 403 before the request ever reaches the container, and the rule holds against method-override headers, .json suffixes and framework data routes. The app does not have to remember to check.

The secrets it would have leaked

Environment variables are encrypted with AES-256-GCM and shown masked. Revealing one is a deliberate press that is audited and alerts the app's owners; a production value needs the owner or a platform admin, and a platform admin who is not assigned to the app cannot read it at all. With the LLM gateway on, the app gets a gateway token instead of your Anthropic or OpenAI key, and the real key never enters the container.

Adopting the app someone else built

The scariest app is the one that already exists. Adopt an app takes a Lovable, Bolt, v0, Replit or Figma Make project, any GitHub repository or a zip, and reads the code without running it. It reports the framework, the environment variables to fill, its use of Supabase, Firebase, Clerk or Auth0, and any exposed keys. A Supabase service-role key in client code is flagged as critical and must be acknowledged before anything deploys, and the first deploy goes to the sandbox only, with the app's secrets stored encrypted. Rotating that key in Supabase is still yours to do; the report tells you so, plainly.

When PHP2Shell landed

On 21 October 2026 PHP shipped fixes for PHP2Shell, two critical remote code execution flaws in PHP itself (CVE-2026-109618 and CVE-2026-109619), after details leaked early and exploitation was reported in the wild (watchTowr). The fix is in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35.

This is the kind of flaw no lockfile scan catches: it is in the runtime, not in a dependency. So AppCrane now patches the runtime too. Every build pulls a fresh copy of its base image, so a rebuild picks up the fixed PHP instead of a stale cached copy. An hourly check reads the PHP version inside every running app, and when it is affected and a fixed image exists, AppCrane rebuilds the same code on it, tests it in the sandbox, confirms the new PHP is fixed, runs the release check and promotes it to production on its own, rolling back if production health fails. Apps it cannot rebuild, such as a PHP branch with no fix, are listed in Job Health for a person, and platform admins are e-mailed the list.

When something does happen

Every action is in the audit log, tagged as taken by an agent or a human. The log is sealed into a SHA-256 hash chain with signed checkpoints, and events and checkpoints can stream to your SIEM, so someone other than the server's operator holds a copy. AppCrane's own password sign-in takes an authenticator code for platform admins by default, and sessions end on the server after a fixed lifetime or idle time.

Back to 2 a.m.

The advisory still goes out in the middle of the night. AppCrane cannot stop that. But within a day the scheduled scan has recorded it against the app, the owner has a request naming the fixed version, the next production deploy that still carries it will be refused at the door, and one click sends it to the coder, which proposes the upgrade for someone to review over coffee.

You still care about security. You just get to sleep.


AppCrane is a self-hosted platform for internal and AI-built apps. AGPL-3.0. Free. Runs on any Ubuntu 22.04+ server.

Stop being the last line of defence
Scan, block, route and fix, on a server you own.
See AppCrane → Read the security model