Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 7 additions & 33 deletions apps/api/bun.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions apps/api/bunfig.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ minimumReleaseAgeExcludes = [
# we override `form-data` directly to clear `bun audit`. The patched release
# is <7 days old, so exempt it from the quarantine window.
"form-data",
# handlebars 4.7.10 (2026-10-05) is the only release patching two critical
# JavaScript-injection advisories (GHSA-8r5x-fm3f-whwj, GHSA-p8wg-vrv2-v86f)
# and GHSA-xw65-4hp5-5hc7. A known critical fix outweighs the quarantine
# window for this one release; remove the entry once it is past 7 days.
"handlebars",
]

[test]
Expand Down
30 changes: 0 additions & 30 deletions apps/api/osv-scanner.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,3 @@ the @boring-stack-pkg ESLint plugins: lint-time tooling, never in the
production image or reached by request input. Remove once braces is patched.
"""

# Handlebars has no release that is both patched and past the 7-day quarantine
# (4.7.10 was published 2026-10-05, eligible from 2026-10-12). Bump
# handlebars to 4.7.10 when it ages in, then drop these three entries.
[[IgnoredVulns]]
id = "GHSA-8r5x-fm3f-whwj"
ignoreUntil = "2026-10-16T00:00:00Z"
reason = """
Handlebars compile-path JavaScript injection (bypass of CVE-2026-33937), fixed
in 4.7.10. Templates are compiled only at build time (src/templates/email/build.ts,
preview.ts) from files we own; runtime rendering uses precompiled templates via
handlebars/runtime. No user-supplied template source reaches compile().
"""

[[IgnoredVulns]]
id = "GHSA-p8wg-vrv2-v86f"
ignoreUntil = "2026-10-16T00:00:00Z"
reason = """
Handlebars own-property check bypass leading to JavaScript injection, fixed in
4.7.10. Same usage as GHSA-8r5x-fm3f-whwj: compile() runs only over owned
templates at build time; no attacker-controlled template or helper source.
"""

[[IgnoredVulns]]
id = "GHSA-xw65-4hp5-5hc7"
ignoreUntil = "2026-10-16T00:00:00Z"
reason = """
Handlebars unsafe inline embedding of precompiled templates, fixed in 4.7.10.
Only precompiled, repo-owned templates are embedded; no template content is
derived from request input. Same expiry as GHSA-8r5x-fm3f-whwj.
"""
2 changes: 1 addition & 1 deletion apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
"elysia": "1.4.30",
"elysia-rate-limit": "4.6.3",
"fs-extra": "11.4.1",
"handlebars": "4.7.9",
"handlebars": "4.7.10",
"ioredis": "5.11.1",
"nodemailer": "10.0.13",
"openai": "7.27.0",
Expand Down
5 changes: 1 addition & 4 deletions apps/docs/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"react-dom": "19.3.0",
"reading-time": "1.5.0",
"remark-gfm": "4.0.1",
"sharp": "0.35.4",
"sharp": "0.35.5",
"tailwindcss": "4.3.3",
"ws": "8.22.0"
},
Expand Down
2 changes: 1 addition & 1 deletion apps/site/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@fontsource/manrope": "5.3.0",
"astro": "7.3.5",
"satori": "0.34.0",
"sharp": "0.35.4"
"sharp": "0.35.5"
},
"devDependencies": {
"@astrojs/check": "0.9.10",
Expand Down
9 changes: 8 additions & 1 deletion tools/agent-evals/isolated/docker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,21 @@ function redactedTail(stderr: string, args: readonly string[]): string {
return tail.replace(/\s+/g, " ");
}

/**
* Secrets travel in the Docker client's environment, never in its arguments:
* `-e NAME` without a value makes Docker read NAME from that environment, so
* a password never appears in a process list or in an argument echo.
*/
export async function docker(
root: string,
args: string[],
timeoutMs = 120_000
timeoutMs = 120_000,
secrets: Readonly<Record<string, string>> = {}
): Promise<string> {
const result = await runProcess(["docker", ...args], {
cwd: root,
timeoutMs,
env: { ...process.env, ...secrets },
});

if (result.status !== "completed" || result.code !== 0) {
Expand Down
188 changes: 100 additions & 88 deletions tools/agent-evals/isolated/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,97 +61,109 @@ export async function withIsolatedRuntime(
900_000
);
await docker(root, runnerArguments(name, image));
await docker(root, [
"run",
"-d",
"--name",
state.postgres,
"--network",
`container:${name}`,
"--read-only",
"--cap-drop",
"ALL",
"--security-opt",
"no-new-privileges",
"--user",
"postgres",
"--pids-limit",
"128",
"--memory",
"1g",
"--cpus",
"1",
"--tmpfs",
"/var/lib/postgresql/data:rw,nosuid,nodev,size=512m,mode=1777",
"--tmpfs",
"/var/run/postgresql:rw,nosuid,nodev,mode=1777",
"--tmpfs",
"/tmp:rw,nosuid,nodev,size=64m,mode=1777",
"-e",
"PGDATA=/var/lib/postgresql/data/pgdata",
"-e",
"POSTGRES_USER=app",
"-e",
`POSTGRES_PASSWORD=${state.password}`,
"-e",
"POSTGRES_DB=app",
selectImage(pins, "postgres"),
]);
await docker(root, [
"run",
"-d",
"--name",
state.valkey,
"--network",
`container:${name}`,
"--read-only",
"--cap-drop",
"ALL",
"--security-opt",
"no-new-privileges",
"--user",
"valkey",
"--pids-limit",
"64",
"--memory",
"256m",
"--cpus",
"1",
selectImage(pins, "valkey/valkey"),
"valkey-server",
"--save",
"",
"--appendonly",
"no",
"--requirepass",
state.valkeyPassword,
]);
await docker(
root,
[
"run",
"-d",
"--name",
state.postgres,
"--network",
`container:${name}`,
"--read-only",
"--cap-drop",
"ALL",
"--security-opt",
"no-new-privileges",
"--user",
"postgres",
"--pids-limit",
"128",
"--memory",
"1g",
"--cpus",
"1",
"--tmpfs",
"/var/lib/postgresql/data:rw,nosuid,nodev,size=512m,mode=1777",
"--tmpfs",
"/var/run/postgresql:rw,nosuid,nodev,mode=1777",
"--tmpfs",
"/tmp:rw,nosuid,nodev,size=64m,mode=1777",
"-e",
"PGDATA=/var/lib/postgresql/data/pgdata",
"-e",
"POSTGRES_USER=app",
"-e",
"POSTGRES_PASSWORD",
"-e",
"POSTGRES_DB=app",
selectImage(pins, "postgres"),
],
undefined,
{ POSTGRES_PASSWORD: state.password }
);
await docker(
root,
[
"run",
"-d",
"--name",
state.valkey,
"--network",
`container:${name}`,
"--read-only",
"--cap-drop",
"ALL",
"--security-opt",
"no-new-privileges",
"--user",
"valkey",
"--pids-limit",
"64",
"--memory",
"256m",
"--cpus",
"1",
"-e",
"VALKEY_PASSWORD",
"--entrypoint",
"sh",
selectImage(pins, "valkey/valkey"),
"-c",
'exec valkey-server --save "" --appendonly no --requirepass "$VALKEY_PASSWORD"',
],
undefined,
{ VALKEY_PASSWORD: state.valkeyPassword }
);

for (let attempt = 0; ; attempt++) {
try {
await docker(root, [
"exec",
"-e",
`PGPASSWORD=${state.password}`,
state.postgres,
"psql",
"-h",
"127.0.0.1",
"-U",
"app",
"-d",
"app",
"-c",
"SELECT 1",
]);
await docker(root, [
"exec",
state.valkey,
"valkey-cli",
"-a",
state.valkeyPassword,
"ping",
]);
await docker(
root,
[
"exec",
"-e",
"PGPASSWORD",
state.postgres,
"psql",
"-h",
"127.0.0.1",
"-U",
"app",
"-d",
"app",
"-c",
"SELECT 1",
],
undefined,
{ PGPASSWORD: state.password }
);
await docker(
root,
["exec", "-e", "REDISCLI_AUTH", state.valkey, "valkey-cli", "ping"],
undefined,
{ REDISCLI_AUTH: state.valkeyPassword }
);
break;
} catch {
if (attempt >= 60) {
Expand Down
Loading