Skip to content

fix(security): bound proxy work and enforce provider and input boundaries - #193

Draft
anantham wants to merge 20 commits into
mainfrom
fix/codex-security-2026-10-02
Draft

anantham wants to merge 20 commits into
mainfrom
fix/codex-security-2026-10-02

Conversation

@anantham

@anantham anantham commented Oct 2, 2026 •

Copy link
Copy Markdown
Owner

Summary

The public scraping proxy could buffer unbounded upstream bodies and return active HTML on the application origin. Reader comparison, explanation and diff could also send content to OpenRouter despite a different selected provider. This patch bounds proxy work, returns inert source text and routes auxiliary requests through the selected provider, with fail-closed behavior.

The grouped repair also authenticates the complete pinned SillyTavern source, uses a trusted parser, bounds imports and logs, validates generated identifiers and file paths, renders untrusted UI content literally, and isolates EPUB statistics dictionaries from prototypes. The legacy inspector uses a different database from current imports; its unsafe sink was hardened as defense in depth without claiming a current-import exploit.

Changes

  • Shared API/dev proxy policy: HTTPS/default ports, 4MiB actual response cap, 20s absolute deadline, four redirects, bounded caller/process admission and inert security headers.
  • Selected-provider comparison/explanation/diff; no automatic unrelated public CORS proxy fallback. Separate comparison/explanation metric categories retain costs and exclude new auxiliary records from translation ETA.
  • Exact source provenance and pinned tool-owned YAML tooling, provisioned by both platform setup paths with lifecycle scripts disabled; bounded bridge/telemetry logs.
  • Staged remote-import validation before writes; safe liturgy identifiers, grounding/report paths, extension sender/DOM handling and EPUB statistics.
  • Recipient/resource/input regressions and finding validation, contracts and deployment prerequisites.

Source base: 9e79b036400d6c009edd5c4881f4e223be3e74ae. Final head: f0729190a470c6f698e649e4a90c07a7d66491c4. Private scan report and private evidence are excluded.

Validation

  • Exact-head GitHub CI: all five required Test jobs passed.
  • Independent final source/documentation review: no actionable findings; confidence 0.90 for local/mocked behavior.
  • Full Vitest/coverage: 331 files, 9,832 passed, 347 skipped. Untouched base: 324 files, 9,610 passed, 347 skipped. Coverage policy and every per-file floor pass (L62.16%, S60.57%, F60.15%, B48.88%).
  • Bridge 72 and grounding 8 tests pass. Metric follow-up 262 relevant tests and 71 independently run focused tests pass; old-label replay fails 10 cases as expected.
  • Full typecheck, production build, client-artifact secret scan, extension packaging, exact-base integrity and domain invariants pass. Lint 0 errors/1,853 warnings; existing 275 invariant advisories. Earlier JSX guard errors were missing local React declarations, corrected without source suppression.
  • Codex's Windows tooling and auxiliary metric findings corrected, with regressions and independent review.
  • Final-head Codex review: reported no major issues on f0729190a4, matching the unchanged full PR head. Manual review; draft automatic eligibility remains unverified.
  • Native Windows, genuine upstream seed, installed-extension, large-browser-import and deployed acceptance remain open. No paid calls or live exploit tests.

Boundaries

This PR remains draft. Readiness, merge and production deployment need separate authorization. Existing Vercel integration created previews automatically; no production promotion or settings change occurred. No obsolete Actions workflow was enabled.

Admission budgets are per process; fleet-wide edge controls remain a deployment prerequisite. Historical mislabeled auxiliary metrics remain unchanged. Existing browser prompt/response diagnostic logging is separately recorded privacy debt. Deployment steps and remaining limits are in the receipt above.

Context: L05 security review found comparison, explanation, and enabled diff silently used OpenRouter regardless of provider selection.

Changes: Reuse configured provider adapters; add explicit plain-text response mode; bind diff to current Settings after cache lookup and reject recipient/model substitution.

Impact: Missing credentials, provider errors, and malformed output fail closed without a hidden OpenRouter or default-model fallback.

Tests: 52 mocked real-SDK transport recipient regressions; focused suite 87 passed; relevant aggregate suite 222 passed. Typecheck retains two baseline JSX directive errors; lint has no errors.

Docs: Append routing correction to CORE-014; WORKLOG integration delegated to coordinator.
Context: imported legacy titles and scraper messages could reach HTML sinks.

Changes: render all inspector fields and errors with DOM text; admit popup messages only from the active allowed top frame and restrict injection URLs.

Impact: hardens the legacy LexiconForgeDB v9 inspector without claiming current lexicon-forge imports reach it.

Tests: 13 synthetic browser boundary tests; extension packaging gate.
Context: exportName was interpolated as executable TypeScript syntax.

Changes: require one ASCII non-reserved binding; use a safe fallback for invalid generated slug names.

Tests: 25 generator tests including code, comment, keyword and length rejection.
Context: stableId values controlled read and write paths outside grounding directories.

Changes: preflight identifiers and duplicate IDs, require canonical single-file containment, and use descriptor-relative no-follow regular-file I/O.

Impact: rejects traversal and symlinks; fails closed on platforms without safe POSIX open APIs.

Tests: 8 local synthetic Python regressions including complete ground/build/validate flow.
Context: report IDs allowed Windows separators and development packets could follow outside symlinks.

Changes: reject non-basename IDs and devices, enforce canonical containment for both packet layouts, bind development serving to loopback by default.

Tests: 26 report grammar, middleware, packet-layout, symlink and host checks; production build.
Context: provider/model dictionary lookups resolved inherited prototype properties.

Changes: aggregate metric labels in null-prototype dictionaries while preserving all labels as data.

Tests: prototype-shaped label safety plus EPUB and export regressions.
Context: Remote downloads trusted optional Content-Length and lacked a full-body
budget; streamed chapters could persist before a later malformed body rejected.
Changes: Count received bytes, enforce absolute download deadlines and finite
JSON/schema limits, and validate staged bytes before chapter-at-a-time import.
Reject malformed/truncated/duplicate/prototype-key payloads without library writes.
Impact: First-ready callbacks occur after full remote validation; established
translation resume/version behavior remains intact. Storage failures after the
validation boundary retain the existing import semantics.
Tests: 99 focused cases and 313 relevant aggregate cases pass on Node 24;
production build, client-secret scan, and changed-file lint checks pass.
Docs: Parent coordinator owns the combined security roadmap/worklog receipt.
@vercel

vercel Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
lexicon-forge Ready Ready Preview Oct 2, 2026 1:49pm UTC

anantham commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Please review this draft's security changes for regressions, especially proxy representation and resource limits, selected-provider recipients/fail-closed behavior, local source provenance and trusted parsing, staged import limits, and hostile identifier/path/DOM/prototype handling. Validate the disputed legacy inspector reachability rather than assuming a current-import exploit. Use source and synthetic tests; do not run paid model calls, live exploit requests, or inspect private user data.

This is a manual review request after observing no automatic Codex review/comments on draft creation. Automatic-review eligibility remains a separate verification; keep the PR in draft.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4376776e1b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

$configuratorPath,
$dependencyInspectorPath,
$sourceVerifierPath,
(Join-Path $bridgeRoot 'deploy\tools\node_modules\yaml\dist\index.js'),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Provision the trusted parser in the Windows setup

On a clean Windows checkout, the documented workflow runs bootstrap-bridge.ps1 and then this hardener, but the bootstrap never installs deploy/tools/package-lock.json and node_modules is not tracked. Consequently this new required-file check always aborts before source/config verification unless the operator discovers and manually runs the npm command currently shown only in the macOS/test instructions. Install the pinned tool dependency from the Windows bootstrap or add that required step to the Windows preparation sequence.

Useful? React with 👍 / 👎.

anantham commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Please review updated head cf87047. The P2 from review 5392209451 is corrected: Windows bootstrap installs the fixed trusted tooling lock with lifecycle scripts disabled and fails before Python/uv if installation or parser verification fails. All five exact-head Test jobs passed: https://github.com/anantham/LexiconForge/actions/runs/37013308085. Local bridge aggregate:72 passed; independent follow-up review:9 focused tests passed, no actionable findings. Native Windows probe remains unexecuted on this Mac.

Keep review to source and synthetic tests. No paid model calls, live exploit requests, private content inspection/export or runtime activation. This PR remains draft.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf870477ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread services/comparisonService.ts Outdated
: {}),
maxTokens: maxOutput,
temperature: 0,
apiType: 'translation',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep auxiliary analyses out of translation ETA samples

When a user runs a focused comparison, this records the request as apiType: 'translation' (and ExplanationService now does the same), so the provider adapters persist its duration among actual translation metrics. estimateTranslationTime() consumes every successful translation metric for the selected model/provider, meaning these typically different workloads can skew the ETA displayed for subsequent chapter translations and misclassify their costs. Give comparison and explanation distinct metric types rather than labeling them as translations.

Useful? React with 👍 / 👎.

Context: PR #193 review found comparison and explanation duration samples were labeled translation and could bias chapter ETA.

Changes: Record distinct comparison/explanation categories and retain their cost totals in session, lifetime and CSV summaries.

Tests: 90 focused mocked-provider/metrics tests and 262 relevant aggregate tests pass; ten recipient-metric cases fail when replaying the old labels. Typecheck passes; changed-file lint has zero errors.

Impact: Provider recipients are unchanged. No migration, historical metric rewrite or production action.

anantham commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Please review updated head f072919. Both prior P2 findings are corrected: fixed-lock trusted Windows parser bootstrap, and distinct comparison/explanation metric categories that preserve costs while excluding new auxiliary durations from translation ETA. Historical metrics are unchanged.

All five exact-head Test jobs passed: https://github.com/anantham/LexiconForge/actions/runs/37015503559. Root full suite:331 files,9832 passed,347 skipped; coverage policy/typecheck/build/integrity pass. Relevant metric aggregate:262 passed; independent follow-up source/documentation review passed with71 focused tests. Native Windows probe remains unexecuted on this Mac.

Keep review to source and synthetic tests. No paid calls, live exploit requests, private data inspection/export or runtime activation. This PR remains draft.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: f0729190a4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

This branch was successfully deployed

1 active deployment
Preview — f0729190 Deployed Oct 2, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant