opencode-self-improvement 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-self-improvement",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Durable memory for opencode: remember facts, decisions, and commands across sessions, plus a one-command per-repo setup (/repo-init).",
5
5
  "main": "index.ts",
6
6
  "exports": {
@@ -17,10 +17,20 @@ const PAGE = join(import.meta.dir, "page.html");
17
17
  const HOST = process.env.OPENCODE_VIEWER_HOST || "127.0.0.1";
18
18
  const PORT = Number(process.env.OPENCODE_VIEWER_PORT || 8787);
19
19
 
20
+ // Defense-in-depth headers on every response. CSP: the page uses only inline
21
+ // script/style and same-origin fetch, so everything else is off — a stored-XSS
22
+ // payload (see issue #11) gains no exfil channel and no framing.
23
+ const SECURITY_HEADERS: Record<string, string> = {
24
+ "x-content-type-options": "nosniff",
25
+ "content-security-policy":
26
+ "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; " +
27
+ "connect-src 'self'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'",
28
+ };
29
+
20
30
  function json(body: unknown, status = 200): Response {
21
31
  return new Response(JSON.stringify(body), {
22
32
  status,
23
- headers: { "content-type": "application/json" },
33
+ headers: { ...SECURITY_HEADERS, "content-type": "application/json" },
24
34
  });
25
35
  }
26
36
 
@@ -116,13 +126,21 @@ export async function startViewer(port: number = PORT): Promise<ViewerServer> {
116
126
  hostname: HOST,
117
127
  port,
118
128
  fetch(req, srv) {
119
- // Bun builds req.url from the request's Host header.
120
- const url = new URL(req.url);
129
+ // Bun builds req.url from the request's Host header. A malformed Host
130
+ // makes the URL parse THROW — before rejectRequest could answer. Letting
131
+ // that escape hands the caller Bun's dev error page (stack + absolute
132
+ // paths), so the parse itself is the first guarded step (issue #12).
133
+ let url: URL;
134
+ try {
135
+ url = new URL(req.url);
136
+ } catch {
137
+ return error("malformed request URL (bad Host header?)", 400);
138
+ }
121
139
  const rejected = rejectRequest(req, url, server.port ?? port);
122
140
  if (rejected) return rejected;
123
141
  if (url.pathname === "/") {
124
142
  return new Response(page, {
125
- headers: { "content-type": "text/html; charset=utf-8" },
143
+ headers: { ...SECURITY_HEADERS, "content-type": "text/html; charset=utf-8" },
126
144
  });
127
145
  }
128
146
  if (req.method === "GET" && url.pathname === "/api/data") {