Skip to content

[WRONG BRANCH] fix(live): keep frame forensics metadata-only - #180

Draft
luvs01 wants to merge 1 commit into
mainfrom
codex/propose-fix-for-live-frame-logging-vulnerability
Draft

[WRONG BRANCH] fix(live): keep frame forensics metadata-only#180
luvs01 wants to merge 1 commit into
mainfrom
codex/propose-fix-for-live-frame-logging-vulnerability

Conversation

@luvs01

@luvs01 luvs01 commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Motivation

  • The env-gated live sideband forensic logger could include short decoded payload excerpts around U+FFFD, which for short frames or decoded-binary cases leaked user content contrary to the metadata-only intent.
  • The log file was created with default permissions, making diagnostic files potentially readable by others on typical umasks.

Description

  • Stop extracting and writing any context text from frames and record only metadata fields: ts, dir, kind, bytes, and a boolean fffd flag when U+FFFD is present in decoded text, implemented in logLiveSidebandFrame in src/server/live.ts.
  • Avoid decoding-derived excerpts for binary or view frames; detect U+FFFD presence via String.prototype.includes over the decoder result and do not persist surrounding text.
  • Create/append the forensic JSONL file with owner-only permissions (0o600) by passing { mode: 0o600 } to appendFileSync so new files are private on POSIX systems.
  • Update the regression in tests/server-live.test.ts to assert that no context property or payload text is present in the log and to check POSIX file mode is 0600 when applicable.

Testing

  • Ran bun run typecheck, which succeeded (no type errors).
  • Ran the focused test bun run test -- tests/server-live.test.ts --test-name-pattern "sideband frame log records metadata without payload content", which passed and verifies metadata-only logging and file permissions.
  • Ran bun run privacy:scan, which passed.
  • A full bun run test was started under the pinned Bun runtime; it exercised many suites but an unrelated existing test (tests/server-auth.test.ts) failed (expected 401 vs received 403) during the full run and that unrelated failure was observed while the overall long suite was running.

Codex Task

Summary by CodeRabbit

  • Bug Fixes
    • Sideband frame diagnostics now record metadata only, including frame direction, type, size, and replacement-character detection.
    • Diagnostic logs no longer include payload data or surrounding text excerpts.
    • Diagnostic log files are now created with owner-only access permissions.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

⚠️ Wrong target branch

This pull request currently targets main, but pull requests must target one of dev.

@luvs01 Please retarget this PR to dev. All contributions go to dev; main receives only release promotions. See our Contributing guide for details. Thanks! 🙏

Its title has been prefixed with [WRONG BRANCH].

This pull request is being kept as a draft automatically. Once every issue above is resolved, it will be marked ready for review again.

@github-actions github-actions Bot changed the title fix(live): keep frame forensics metadata-only [WRONG BRANCH] fix(live): keep frame forensics metadata-only Aug 8, 2026
@github-actions
github-actions Bot marked this pull request as draft August 8, 2026 15:59
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Sideband frame diagnostics now record metadata without payload excerpts. They track U+FFFD presence across text and binary payloads. Diagnostic files use owner-only permissions, with tests covering log content and non-Windows permissions.

Changes

Sideband diagnostic logging

Layer / File(s) Summary
Metadata-only frame logging
src/server/live.ts
Sideband logs retain frame direction, kind, byte length, and a boolean U+FFFD indicator for text, ArrayBuffer, and typed-array payloads. Payload excerpts and context data are removed. Log files use mode 0o600.
Diagnostic logging validation
tests/server-live.test.ts
Tests verify that frame logs contain no payload or context content and that non-Windows log files have 0600 permissions.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: wibias, lidge-jun, ingwannu

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: keeping live frame forensics metadata-only.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 2
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch codex/propose-fix-for-live-frame-logging-vulnerability
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/propose-fix-for-live-frame-logging-vulnerability

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/server/live.ts`:
- Line 116: Update logLiveSidebandFrame in src/server/live.ts to open the frame
log descriptor, enforce mode 0o600 with fchmodSync, append the record through
that descriptor, and close it reliably. In tests/server-live.test.ts:850, retain
the creation-path permission assertion and add a reuse-path case that
pre-creates frameLogPath with mode 0o644, invokes the logger, and verifies it
becomes 0o600.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 18ff4741-3c9f-4f44-bbf0-da4c85da76fc

📥 Commits

Reviewing files that changed from the base of the PR and between 8a9c0ef and 59d9f74.

📒 Files selected for processing (2)
  • src/server/live.ts
  • tests/server-live.test.ts

Comment thread src/server/live.ts
fffd,
};
appendFileSync(logPath, `${JSON.stringify(record)}\n`);
appendFileSync(logPath, `${JSON.stringify(record)}\n`, { mode: 0o600 });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- candidate files ---'
git ls-files 'src/server/live.ts' 'tests/server-live.test.ts' 'package.json' 'bun.lock' 'bun.lockb' 'tsconfig.json'

printf '%s\n' '--- source outline ---'
ast-grep outline src/server/live.ts || true

printf '%s\n' '--- source context ---'
sed -n '1,180p' src/server/live.ts

printf '%s\n' '--- test context ---'
sed -n '810,875p' tests/server-live.test.ts

printf '%s\n' '--- filesystem permission references ---'
rg -n -S 'appendFileSync|fchmodSync|chmodSync|frameLogPath|logPath|forensic|frame log' src tests package.json bun.lock bun.lockb 2>/dev/null || true

printf '%s\n' '--- runtime/config context ---'
for f in package.json bun.lock bun.lockb tsconfig.json; do
  if [ -f "$f" ]; then
    echo "### $f"
    sed -n '1,180p' "$f"
  fi
done

Repository: luvs01/opencodex

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- enclosing frame-log test ---'
rg -n -B 45 -A 12 'frameLogPath|OCX_LIVE_FRAME_LOG|frame-log' tests/server-live.test.ts

printf '%s\n' '--- package scripts and runtime declarations ---'
node - <<'JS'
const fs = require("fs");
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
console.log(JSON.stringify({
  engines: pkg.engines,
  type: pkg.type,
  scripts: pkg.scripts,
  dependencies: pkg.dependencies,
  devDependencies: pkg.devDependencies,
}, null, 2));
JS

printf '%s\n' '--- focused permission patterns ---'
rg -n -S -C 3 'chmodSync\(path, 0o600\)|appendFileSync\(path|openSync\(.*0o600|fchmodSync' src/usage src/server tests/server-live.test.ts

printf '%s\n' '--- standalone existing-file mode probe ---'
node - <<'JS'
"use strict";
const {
  appendFileSync,
  chmodSync,
  mkdtempSync,
  readFileSync,
  rmSync,
  statSync,
} = require("node:fs");
const { join } = require("node:path");
const { tmpdir } = require("node:os");

const dir = mkdtempSync(join(tmpdir(), "ocx-mode-probe-"));
const path = join(dir, "frame.jsonl");
try {
  appendFileSync(path, "seed\n", { mode: 0o644 });
  chmodSync(path, 0o644);
  const before = statSync(path).mode & 0o777;
  appendFileSync(path, "record\n", { mode: 0o600 });
  const after = statSync(path).mode & 0o777;
  console.log(JSON.stringify({ before: before.toString(8), after: after.toString(8), content: readFileSync(path, "utf8") }));
} finally {
  rmSync(dir, { recursive: true, force: true });
}
JS

Repository: luvs01/opencodex

Length of output: 10915


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- Bun availability ---'
if command -v bun >/dev/null 2>&1; then
  bun --version
  printf '%s\n' '--- Bun node:fs descriptor probe ---'
  bun - <<'JS'
import { chmodSync, closeSync, fchmodSync, mkdtempSync, openSync, readFileSync, rmSync, statSync, writeSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";

const dir = mkdtempSync(join(tmpdir(), "ocx-bun-mode-probe-"));
const path = join(dir, "frame.jsonl");
try {
  writeSync(openSync(path, "w", 0o644), "seed\n");
  chmodSync(path, 0o644);
  const before = statSync(path).mode & 0o777;
  const fd = openSync(path, "a", 0o600);
  fchmodSync(fd, 0o600);
  writeSync(fd, "record\n");
  closeSync(fd);
  const after = statSync(path).mode & 0o777;
  console.log(JSON.stringify({ before: before.toString(8), after: after.toString(8), content: readFileSync(path, "utf8") }));
} finally {
  rmSync(dir, { recursive: true, force: true });
}
JS
else
  echo 'bun unavailable'
fi

printf '%s\n' '--- test imports and TEST_DIR lifecycle ---'
sed -n '1,90p' tests/server-live.test.ts
rg -n -B 8 -A 12 'TEST_DIR|rmSync\(TEST_DIR|mkdirSync\(TEST_DIR|mkdtempSync' tests/server-live.test.ts

Repository: luvs01/opencodex

Length of output: 6885


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- Bun availability ---'
if command -v bun >/dev/null 2>&1; then
  bun --version
  printf '%s\n' '--- Bun node:fs descriptor probe ---'
  bun - <<'JS'
import { chmodSync, closeSync, fchmodSync, mkdtempSync, openSync, readFileSync, rmSync, statSync, writeSync } from "node:fs";
import { join } from "node:path";
import { tmpdir } from "node:os";

const dir = mkdtempSync(join(tmpdir(), "ocx-bun-mode-probe-"));
const path = join(dir, "frame.jsonl");
try {
  const seedFd = openSync(path, "w", 0o644);
  writeSync(seedFd, "seed\n");
  closeSync(seedFd);
  chmodSync(path, 0o644);
  const before = statSync(path).mode & 0o777;
  const fd = openSync(path, "a", 0o600);
  fchmodSync(fd, 0o600);
  writeSync(fd, "record\n");
  closeSync(fd);
  const after = statSync(path).mode & 0o777;
  console.log(JSON.stringify({ before: before.toString(8), after: after.toString(8), content: readFileSync(path, "utf8") }));
} finally {
  rmSync(dir, { recursive: true, force: true });
}
JS
else
  echo 'bun unavailable'
fi

printf '%s\n' '--- test imports and TEST_DIR lifecycle ---'
sed -n '1,90p' tests/server-live.test.ts
rg -n -B 8 -A 12 'TEST_DIR|rmSync\(TEST_DIR|mkdirSync\(TEST_DIR|mkdtempSync' tests/server-live.test.ts

Repository: luvs01/opencodex

Length of output: 6885


Harden reused frame log files before appending.

{ mode: 0o600 } affects only file creation. If OCX_LIVE_FRAME_LOG points to an existing 0o644 file, logLiveSidebandFrame keeps its permissive mode. On POSIX, open the file, call fchmodSync(fd, 0o600), append the record, and close the descriptor.

In tests/server-live.test.ts, retain the creation-path assertion and add a reuse-path case that pre-creates frameLogPath with 0o644, invokes the logger, and asserts 0o600.

📍 Affects 2 files
  • src/server/live.ts#L116-L116 (this comment)
  • tests/server-live.test.ts#L850-L850
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server/live.ts` at line 116, Update logLiveSidebandFrame in
src/server/live.ts to open the frame log descriptor, enforce mode 0o600 with
fchmodSync, append the record through that descriptor, and close it reliably. In
tests/server-live.test.ts:850, retain the creation-path permission assertion and
add a reuse-path case that pre-creates frameLogPath with mode 0o644, invokes the
logger, and verifies it becomes 0o600.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant