Skip to content

Commit bc09865

Browse files
v0.6.50: ppt/doc/pdf worker isolation, docs, chat, sidebar improvements
2 parents dcf3302 + 524f33c commit bc09865

File tree

403 files changed

+4827
-2155
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

403 files changed

+4827
-2155
lines changed

.claude/rules/global.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,25 @@ const shortId = generateShortId()
3030
const tiny = generateShortId(8)
3131
```
3232

33+
## Common Utilities
34+
Use shared helpers from `@/lib/core/utils/helpers` instead of writing inline implementations:
35+
36+
- `sleep(ms)` — async delay. Never write `new Promise(resolve => setTimeout(resolve, ms))`
37+
- `toError(value)` — normalize unknown caught values to `Error`. Never write `e instanceof Error ? e : new Error(String(e))`
38+
- `toError(value).message` — get error message safely. Never write `e instanceof Error ? e.message : String(e)`
39+
40+
```typescript
41+
// ✗ Bad
42+
await new Promise(resolve => setTimeout(resolve, 1000))
43+
const msg = error instanceof Error ? error.message : String(error)
44+
const err = error instanceof Error ? error : new Error(String(error))
45+
46+
// ✓ Good
47+
import { sleep, toError } from '@/lib/core/utils/helpers'
48+
await sleep(1000)
49+
const msg = toError(error).message
50+
const err = toError(error)
51+
```
52+
3353
## Package Manager
3454
Use `bun` and `bunx`, not `npm` and `npx`.

.cursor/rules/global.mdc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,25 @@ const shortId = generateShortId()
3737
const tiny = generateShortId(8)
3838
```
3939

40+
## Common Utilities
41+
Use shared helpers from `@/lib/core/utils/helpers` instead of writing inline implementations:
42+
43+
- `sleep(ms)` — async delay. Never write `new Promise(resolve => setTimeout(resolve, ms))`
44+
- `toError(value)` — normalize unknown caught values to `Error`. Never write `e instanceof Error ? e : new Error(String(e))`
45+
- `toError(value).message` — get error message safely. Never write `e instanceof Error ? e.message : String(e)`
46+
47+
```typescript
48+
// ✗ Bad
49+
await new Promise(resolve => setTimeout(resolve, 1000))
50+
const msg = error instanceof Error ? error.message : String(error)
51+
const err = error instanceof Error ? error : new Error(String(error))
52+
53+
// ✓ Good
54+
import { sleep, toError } from '@/lib/core/utils/helpers'
55+
await sleep(1000)
56+
const msg = toError(error).message
57+
const err = toError(error)
58+
```
59+
4060
## Package Manager
4161
Use `bun` and `bunx`, not `npm` and `npx`.

.cursor/rules/sim-sandbox.mdc

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
description: Isolated-vm sandbox worker security policy. Hard rules for anything that lives in the worker child process that runs user code.
3+
globs: ["apps/sim/lib/execution/isolated-vm-worker.cjs", "apps/sim/lib/execution/isolated-vm.ts", "apps/sim/lib/execution/sandbox/**", "apps/sim/sandbox-tasks/**"]
4+
---
5+
6+
# Sim Sandbox — Worker Security Policy
7+
8+
The isolated-vm worker child process at
9+
`apps/sim/lib/execution/isolated-vm-worker.cjs` runs untrusted user code inside
10+
V8 isolates. The process itself is a trust boundary. Everything in this rule is
11+
about what must **never** live in that process.
12+
13+
## Hard rules
14+
15+
1. **No app credentials in the worker process**. The worker must not hold, load,
16+
or receive via IPC: database URLs, Redis URLs, AWS keys, Stripe keys,
17+
session-signing keys, encryption keys, OAuth client secrets, internal API
18+
secrets, or any LLM / email / search provider API keys. If you catch yourself
19+
`require`'ing `@/lib/auth`, `@sim/db`, `@/lib/uploads/core/storage-service`,
20+
or anything that imports `env` directly inside the worker, stop and use a
21+
host-side broker instead.
22+
23+
2. **Host-side brokers own all credentialed work**. The worker can only access
24+
resources through `ivm.Reference` / `ivm.Callback` bridges back to the host
25+
process. Today the only broker is `workspaceFileBroker`
26+
(`apps/sim/lib/execution/sandbox/brokers/workspace-file.ts`); adding a new
27+
one requires co-reviewing this file.
28+
29+
3. **Host-side brokers must scope every resource access to a single tenant**.
30+
The `SandboxBrokerContext` always carries `workspaceId`. Any new broker that
31+
accesses storage, DB, or an external API must use `ctx.workspaceId` to scope
32+
the lookup — never accept a raw path, key, or URL from isolate code without
33+
validation.
34+
35+
4. **Nothing that runs in the isolate is trusted, even if we wrote it**. The
36+
task `bootstrap` and `finalize` strings in `apps/sim/sandbox-tasks/` execute
37+
inside the isolate. They must treat `globalThis` as adversarial — no pulling
38+
values from it that might have been mutated by user code. The hardening
39+
script in `executeTask` undefines dangerous globals before user code runs.
40+
41+
## Why
42+
43+
A V8 JIT bug (Chrome ships these roughly monthly) gives an attacker a native
44+
code primitive inside the process that owns whatever that process can reach.
45+
If the worker only holds `isolated-vm` + a single narrow workspace-file broker,
46+
a V8 escape leaks one tenant's files. If the worker holds a Stripe key or a DB
47+
connection, a V8 escape leaks the service.
48+
49+
The original `doc-worker.cjs` vulnerability (CVE-class, 225 production secrets
50+
leaked via `/proc/1/environ`) was the forcing function for this architecture.
51+
Keep the blast radius small.
52+
53+
## Checklist for changes to `isolated-vm-worker.cjs`
54+
55+
Before landing any change that adds a new `require(...)` or `process.send(...)`
56+
payload or `ivm.Reference` wrapper in the worker:
57+
58+
- [ ] Does it load a credential, key, connection string, or secret? If yes,
59+
move it host-side and expose as a broker.
60+
- [ ] Does it import from `@/lib/auth`, `@sim/db`, `@/lib/uploads/core/*`,
61+
`@/lib/core/config/env`, or any module that reads `process.env` of the
62+
main app? If yes, same — move host-side.
63+
- [ ] Does it expose a resource that's workspace-scoped without taking a
64+
`workspaceId`? If yes, re-scope.
65+
- [ ] Did you update the broker limits (`IVM_MAX_BROKER_ARGS_JSON_CHARS`,
66+
`IVM_MAX_BROKER_RESULT_JSON_CHARS`, `IVM_MAX_BROKERS_PER_EXECUTION`) if
67+
the new broker can emit large payloads or fire frequently?
68+
69+
## What the worker *may* hold
70+
71+
- `isolated-vm` module
72+
- Node built-ins: `node:fs` (only for reading the checked-in bundle `.cjs`
73+
files) and `node:path`
74+
- The three prebuilt library bundles under
75+
`apps/sim/lib/execution/sandbox/bundles/*.cjs`
76+
- IPC message handlers for `execute`, `cancel`, `fetchResponse`,
77+
`brokerResponse`
78+
79+
The worker deliberately has **no host-side logger**. All errors and
80+
diagnostics flow through IPC back to the host, which has `@sim/logger`. Do
81+
not add `createLogger` or console-based logging to the worker — it would
82+
require pulling the main app's config / env, which is exactly what this
83+
rule is preventing.
84+
85+
Anything else is suspect.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ You are a professional software engineer. All code must follow best practices: a
88
- **Comments**: Use TSDoc for documentation. No `====` separators. No non-TSDoc comments
99
- **Styling**: Never update global styles. Keep all styling local to components
1010
- **ID Generation**: Never use `crypto.randomUUID()`, `nanoid`, or `uuid` package. Use `generateId()` (UUID v4) or `generateShortId()` (compact) from `@/lib/core/utils/uuid`
11+
- **Common Utilities**: Use shared helpers from `@/lib/core/utils/helpers` instead of inline implementations. `sleep(ms)` for delays, `toError(e)` to normalize caught values.
1112
- **Package Manager**: Use `bun` and `bunx`, not `npm` and `npx`
1213

1314
## Architecture

apps/docs/components/ui/action-media.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useState } from 'react'
3+
import { useRef, useState } from 'react'
44
import { cn, getAssetUrl } from '@/lib/utils'
55
import { Lightbox } from './lightbox'
66

@@ -50,18 +50,22 @@ export function ActionImage({ src, alt, enableLightbox = true }: ActionImageProp
5050
}
5151

5252
export function ActionVideo({ src, alt, enableLightbox = true }: ActionVideoProps) {
53+
const videoRef = useRef<HTMLVideoElement>(null)
54+
const startTimeRef = useRef(0)
5355
const [isLightboxOpen, setIsLightboxOpen] = useState(false)
5456
const resolvedSrc = getAssetUrl(src)
5557

5658
const handleClick = () => {
5759
if (enableLightbox) {
60+
startTimeRef.current = videoRef.current?.currentTime ?? 0
5861
setIsLightboxOpen(true)
5962
}
6063
}
6164

6265
return (
6366
<>
6467
<video
68+
ref={videoRef}
6569
src={resolvedSrc}
6670
autoPlay
6771
loop
@@ -80,6 +84,7 @@ export function ActionVideo({ src, alt, enableLightbox = true }: ActionVideoProp
8084
src={src}
8185
alt={alt}
8286
type='video'
87+
startTime={startTimeRef.current}
8388
/>
8489
)}
8590
</>

apps/docs/components/ui/animated-blocks.tsx

Lines changed: 0 additions & 195 deletions
This file was deleted.

0 commit comments

Comments
 (0)