Conversation
Security guards, workspace scope enforcement, readonly bash guard, and agent redirect logic had zero test coverage. This adds pytest tests for the pure functions in each script, covering all regex patterns, edge cases, bypass vectors, and false positive checks.
- Resolve CHANGELOG.md merge conflict (testing section + main's fixes) - Fix run_main() return type in test_redirect_builtin_agents.py (CodeRabbit review) - Update block-dangerous tests for new source patterns: - --force-with-lease now intentionally blocked (was documented as bug) - Bare force push message changed to FORCE_PUSH_SUGGESTION - Add tests for remote branch deletion patterns (--delete, colon-refspec)
Scope guard: resolve CWD with realpath to prevent symlink mismatches, detect .claude/worktrees/ and expand scope to project root so sibling worktrees aren't blocked, and improve error messages with resolved paths. Stop hooks: add 5-minute per-session cooldown to commit-reminder and spec-reminder to prevent repeated firing in team/agent scenarios.
resolve_scope_root() now walks up from CWD looking for .git to find the repository root, preventing false positives when working in subdirectories like cli/, src/, or tests/. Safety ceiling at /workspaces prevents scope from escaping the workspace boundary.
Move .git/ to project root so the entire workspace is tracked in a single repository. Git detects all container-root files as renames into the container/ subdirectory. Root-level files (.github/, LICENSE.txt, CLA.md, CONTRIBUTING.md, .gitattributes) remain at the repository root. The docs/ package was already tracked at docs/ and is unaffected by this change. This is a structural reorganization — no code changes.
Add codeforge-cli v0.1.0 (Bun/TypeScript) — a CLI for CodeForge development workflows including session search, plan management, and task tracking. The docs package was already tracked from the previous repository structure.
CI workflows: - Add working-directory: container to all container job steps - Add path filters (container/**, cli/**) to trigger workflows selectively - Add test-cli job using Bun for CLI package - Update changelog/package.json paths for container subdirectory - Update devcontainer feature publish paths Config: - Add repository.directory to container and cli package.json - Remove docs:* scripts from container (docs is now a sibling package) - Simplify container/.gitignore (root handles shared patterns) - Update dependabot directories for monorepo layout Docs: - Add root README.md with monorepo overview and package table - Add root CLAUDE.md with branching strategy and dev rules - Update container/CLAUDE.md to reference root for shared rules
Update sync-changelog.mjs to read from container/.devcontainer/CHANGELOG.md instead of the old .devcontainer/CHANGELOG.md path. Regenerate the docs changelog page with updated source reference.
Scope guard now only enforces isolation between workspace projects. Paths outside the workspace (e.g. /dev/null, /usr/, /etc/) are not this guard's jurisdiction — other guards handle system-level security. Removes the complex system-command exemption logic that was insufficient and fragile.
The redirect patterns matched text content inside command arguments (e.g. PR body text containing example paths), causing false positives. Write location enforcement is the scope guard's responsibility, not the dangerous-command-blocker's.
- plugin list/show/enable/disable/hooks/agents/skills subcommands - config show/apply subcommands with settings writer - review command with headless Claude runner and prompt templates - Plugin/config/review schemas, loaders, and output formatters - Platform detection utility - Tests for plugin loader, plugin list, review output, review runner, settings writer, and platform detection
- Register plugin, config, and review subcommands in index.ts - Remove fast-glob dependency (use native Bun glob) - Fix build output to single file (--outfile dist/codeforge.js) - Add npm publish metadata (keywords, files, prepublishOnly) - Fix search filter edge cases with new tests - Fix plan-loader path resolution - Update session list/show formatting
- release-cli.yml: tag-triggered (cli-v*) npm publish + GitHub release - codeforge-cli devcontainer feature: installs CLI globally via npm - Register codeforge-cli feature in devcontainer.json - Remove dead codeforge alias, add codeforge to cc-tools list - CI: cross-platform test matrix (ubuntu, windows, macos) - Fix docs changelog sync paths for monorepo structure
Add plugin, config, and review commands to CLI
…weep CLI (experimental): - Add index command group (build, search, show, stats, tree, clean) - Add container command group (up, down, rebuild, exec, ls, shell) - Add container proxy — auto-proxies into devcontainer from host - Remove review command (never shipped) - Mark CLI as experimental in all metadata and docs Container (v2.1.0 + v2.1.1): - Spec workflow v2 "Spec Packages" — 8 commands replaced with 3 - Scope guard: fix /dev/null false positive, fix CWD drift - Updated agents, skills, system prompts, and config Docs: - Add CLI commands to reference, tools, and changelog pages - Sync docs changelog with container CHANGELOG (v2.1.0, v2.1.1) - Update spec workflow, agents, skills, and rules docs
…weep (#58) CLI (experimental): - Add index command group (build, search, show, stats, tree, clean) - Add container command group (up, down, rebuild, exec, ls, shell) - Add container proxy — auto-proxies into devcontainer from host - Remove review command (never shipped) - Mark CLI as experimental in all metadata and docs Container (v2.1.0 + v2.1.1): - Spec workflow v2 "Spec Packages" — 8 commands replaced with 3 - Scope guard: fix /dev/null false positive, fix CWD drift - Updated agents, skills, system prompts, and config Docs: - Add CLI commands to reference, tools, and changelog pages - Sync docs changelog with container CHANGELOG (v2.1.0, v2.1.1) - Update spec workflow, agents, skills, and rules docs Co-authored-by: AnExiledDev <AnExiledDev@users.noreply.github.com>
- CLI CHANGELOG: "Ships with CodeForge v2.1.0" → "v2.1.1" to match the actual container release version - Remove agent-system's inject-cwd.py and its SubagentStart hook — workspace-scope-guard already handles SubagentStart with superior scope-resolved CWD (worktree-aware, git-root-aware, session-persisted)
# Conflicts: # container/.devcontainer/CHANGELOG.md # container/package.json
Installer now falls back to HOME override when su is unavailable, which happens on VM-based Docker (Docker Desktop). Also removes unnecessary su call in version verification.
…iner runtime - Switch status bar from 6-line ccburn layout to 3-line native session-usage and weekly-usage ccstatusline widgets - Disable ccburn devcontainer feature (commented out in devcontainer.json) - Remove preflight.sh — redundant with Docker's own error reporting - Forward port 7847 for dashboard and add container name to runArgs
- Add autoMemoryDirectory setting for project-local .claude/memory/ - Add safety rules, hooks awareness, tool selection guidance, and anti-over-engineering directives to main and orchestrator prompts - Add auto-memory system documentation with memory types and format - Add context management notes for tool result persistence
New skill for headless browser automation with CLI reference and workflow patterns. Bumps skill count from 22 to 23 across plugin metadata, container docs, and site documentation. Also adds CLAUDE_PLUGIN_DATA docs, npmignore hardening, and changelog entries.
New commands for viewing team tasks: `codeforge task list` shows all tasks for a team, `codeforge task show` displays task detail with dependencies. Includes text and JSON formatters and test coverage. Also removes prompts/ from package files and adds CLI README.
Session list now shows plan slugs and task progress bars when sessions have associated plans or team tasks. Loads plans once and indexes by slug, caches task summaries per team name. Includes text and JSON output support with full test coverage.
New Svelte 5 SPA + Bun backend for session analytics, conversation replay, task/plan/agent views, and cost tracking. Updates root CLAUDE.md to reflect four-package monorepo with dashboard-specific test commands and Dashboard vs CLI guidance.
Spec packages are local working directories, not tracked in version control.
Dashboard package: - Rename @codeforge/dashboard → codeforge-dashboard, remove private flag - Add bin wrapper with --port/--host/--version/--help flags - Add HOST env var support to Bun.serve for container port forwarding - Add files, engines, prepublishOnly fields for npm publish - Move build-time deps (Svelte, Vite, Tailwind) to devDependencies Container feature: - Rewrite install.sh: bun install -g replaces npm install -g - Add autostart poststart hook (PID-guarded, nohup background launch) - Rename command: claude-dashboard → codeforge-dashboard - Remove persistence symlink hook (DB on bind mount) - Update feature metadata, README, devcontainer.json, CLAUDE.md CI/CD: - Add release-dashboard.yml workflow (dashboard-v* tags → npm publish) - Add test-dashboard job to ci.yml - Add dashboard/CHANGELOG.md
- Add dashboard/.svelte-kit/, dashboard/build/, dashboard/mockups/, and .claude/ to .gitignore - Untrack 817 committed build artifacts (git rm --cached) - Replace git-changes statusline widget with cached custom-command that skips git diff when index.lock is held and caches results for 30s - Add allow-list exception to protected-files-guard for .git/index.lock deletion
Container: - Update devcontainer.json configuration - Expand claude-code-headless skill documentation Dashboard — Parser/Server: - Add memory-sync service for background synchronization - Update parser queries, types, and DB layer for memory filtering - Extend API routes with memory and session endpoints Dashboard — UI Components: - Add ApproveModal, MaintenanceModal, and ConfirmModal components - Enhance memory views: MemoriesPage, MemoriesTab, ObservationsTab, RunDetail, RunsTab with filtering and approval workflows - Update session views: SessionList, SessionDetail, AgentsView - Improve dashboard charts: ActivityHeatmap, DurationDistribution, HourlyHeatmap, ModelDistribution, OverviewCards, ToolUsage - Update Sidebar, ProjectDetail, and global styles Dashboard — Stores/Routes: - Extend memory, sessions, and SSE stores for new data flows - Update page routes for memories and session detail views
# Conflicts: # container/.devcontainer/CHANGELOG.md # container/package.json
# Conflicts: # .gitignore # cli/CHANGELOG.md # cli/src/index.ts # container/.codeforge/config/orchestrator-system-prompt.md # container/.devcontainer/CHANGELOG.md # container/.devcontainer/CLAUDE.md
… into staging # Conflicts: # container/.devcontainer/CHANGELOG.md # container/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/guard-workspace-scope.py
- Add dashboard and memories feature docs, update astro sidebar config - Expand plugin guard tests with edge cases and new test fixtures - Add pyproject.toml, dashboard README, CLI README task subcommands - Update changelog, architecture, and getting-started docs
Include dashboard in the packages table and test instructions.
Hooks now check .codeforge/config/disabled-hooks.json at startup and exit early if their script name appears in the disabled list. Disables git-state-injector, ticket-linker, spec-reminder, and commit-reminder by default. Also comments out legacy claude-session-dashboard feature in devcontainer.json (replaced by first-party dashboard). Fixed misplaced hook gate in syntax-validator.py (was inside try block).
New CLI command that launches Claude Code through mitmweb, enabling raw API request/response inspection via a browser UI. Auto-installs mitmproxy via pipx, manages CA certificate trust, and cleans up on exit. Usage: codeforge proxy [--setup] [--no-web] [-- <claude-args>]
- Bump changelog to v2.1.0 with proxy feature, dashboard, hooks, scope guard fixes, and all unreleased changes - Document codeforge proxy command in CLAUDE.md - Add CLAUDE_VERSION_LOCK support to update script - Add DISABLE_AUTOUPDATER to settings.json - Export CLAUDE_VERSION_LOCK in setup.sh - Add version lock docs to .env.example - Fix syntax-validator.py formatting
|
Important Review skippedToo many files! This PR contains 216 files, which is 66 over the limit of 150. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (216)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Security: - Default mitmweb to 127.0.0.1 instead of 0.0.0.0 - Generate random per-session password for mitmweb UI - Check claude binary exists before spawning Reliability: - Poll for CA cert with 500ms intervals (replaces unreliable 2s sleep) - Replace lsof port check with Bun.listen probe (no external dep) - Log proxy cleanup errors instead of swallowing silently Tests: - Extract buildClaudeEnv() as pure testable function (4 tests) - Add generatePassword tests (2 tests) - Add occupied port test for isPortInUse - Fix environment-dependent isCaInstalled test Docs: - Add commit-reminder to disabled hooks changelog entry
# Conflicts: # .github/workflows/ci.yml # .gitignore # CLAUDE.md # README.md # cli/bun.lock # cli/package.json # cli/src/commands/session/list.ts # cli/src/index.ts # cli/src/output/session-list.ts # cli/src/output/task-text.ts # cli/tests/session-list.test.ts # cli/tests/task-search.test.ts # container/.codeforge/config/ccstatusline-settings.json # container/.codeforge/config/orchestrator-system-prompt.md # container/.devcontainer/CHANGELOG.md # container/.devcontainer/CLAUDE.md # container/.devcontainer/features/claude-session-dashboard/README.md # container/.devcontainer/features/claude-session-dashboard/devcontainer-feature.json # container/.devcontainer/features/claude-session-dashboard/install.sh # container/.devcontainer/plugins/devs-marketplace/plugins/session-context/scripts/commit-reminder.py # container/.devcontainer/plugins/devs-marketplace/plugins/spec-workflow/scripts/spec-reminder.py # container/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/guard-workspace-scope.py # container/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/inject-workspace-cwd.py # container/.devcontainer/scripts/preflight.sh # container/README.md # container/package.json # container/tests/plugins/test_guard_workspace_scope.py # docs/src/content/docs/reference/changelog.md # docs/src/content/docs/reference/commands.md
| const s = this.getAttribute('data-sessions'); | ||
| const t = this.getAttribute('data-tokens'); | ||
| const dt = this.getAttribute('data-date'); | ||
| tooltip.innerHTML = `<strong>${dt}</strong><br>${s} session${s !== '1' ? 's' : ''} | ${t} tokens`; |
Check failure
Code scanning / CodeQL
DOM text reinterpreted as HTML High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 days ago
In general, the problem is that DOM text (attribute values) is being inserted into the DOM via innerHTML, which interprets the string as HTML. The robust fix is to avoid innerHTML for dynamic, potentially untrusted data and instead either:
- Use
textContent/innerTextto insert plain text, or - Build the DOM tree explicitly (e.g., create
<strong>and text nodes, insert<br>elements) so that untrusted values are only ever assigned as text, not as HTML.
For this specific case in dashboard/mockups/dashboard-mockup.html around line 2278, we should replace:
tooltip.innerHTML = `<strong>${dt}</strong><br>${s} session${s !== '1' ? 's' : ''} | ${t} tokens`;with code that:
- Clears the tooltip’s existing children (
tooltip.innerHTML = ''or similar). - Creates a
<strong>element, sets itstextContenttodt, and appends it. - Appends a
<br>element. - Creates a text node for the rest of the string, combining
s,t, and the pluralization text, and appends it.
All untrusted pieces (dt, s, t) will then be treated as text, not HTML, eliminating XSS even if they contain HTML metacharacters. No new imports or external libraries are needed; we only use standard DOM APIs. The change is localized to the mouseenter event listener in the shown snippet of dashboard/mockups/dashboard-mockup.html.
| @@ -2275,7 +2275,14 @@ | ||
| const s = this.getAttribute('data-sessions'); | ||
| const t = this.getAttribute('data-tokens'); | ||
| const dt = this.getAttribute('data-date'); | ||
| tooltip.innerHTML = `<strong>${dt}</strong><br>${s} session${s !== '1' ? 's' : ''} | ${t} tokens`; | ||
| // Build tooltip content safely without using innerHTML with untrusted data | ||
| tooltip.innerHTML = ''; | ||
| const strongEl = document.createElement('strong'); | ||
| strongEl.textContent = dt; | ||
| tooltip.appendChild(strongEl); | ||
| tooltip.appendChild(document.createElement('br')); | ||
| const sessionsText = `${s} session${s !== '1' ? 's' : ''} | ${t} tokens`; | ||
| tooltip.appendChild(document.createTextNode(sessionsText)); | ||
| tooltip.classList.add('visible'); | ||
| const rect = this.getBoundingClientRect(); | ||
| tooltip.style.left = (rect.left + rect.width / 2 - tooltip.offsetWidth / 2) + 'px'; |
| const EVENT_HANDLER_RE = /\s+on\w+\s*=\s*["'][^"']*["']/gi; | ||
|
|
||
| function sanitize(html: string): string { | ||
| return html.replace(DANGEROUS_TAG_RE, "").replace(EVENT_HANDLER_RE, ""); |
Check failure
Code scanning / CodeQL
Incomplete multi-character sanitization High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 days ago
In general, to fix incomplete multi-character sanitization, we must ensure that applying the sanitizer cannot reveal new instances of the same unsafe pattern. This can be done either by (a) using a robust HTML sanitization library, or (b) repeatedly applying the existing regexes until the output no longer changes. Since we should avoid changing functionality and external behavior significantly, the best minimal change is to wrap the current two .replace calls in a loop that runs until no further replacements occur.
Concretely, in dashboard/src/web/lib/utils/markdown.ts, we will modify the sanitize(html: string) function (lines 7–9). Instead of a single return html.replace(...).replace(...);, we introduce a simple fixed-point loop:
- Keep a
previousstring. - In each iteration, compute
current = previous.replace(DANGEROUS_TAG_RE, "").replace(EVENT_HANDLER_RE, "");. - Continue looping while
current !== previous. - Return the stable
current.
This preserves the existing sanitization semantics for inputs that already stabilize in one pass, but fixes the multi-character sanitization issue for tricky inputs where new matches appear after earlier replacements. No new imports or helpers are required; we only change the body of sanitize.
| @@ -5,7 +5,17 @@ | ||
| const EVENT_HANDLER_RE = /\s+on\w+\s*=\s*["'][^"']*["']/gi; | ||
|
|
||
| function sanitize(html: string): string { | ||
| return html.replace(DANGEROUS_TAG_RE, "").replace(EVENT_HANDLER_RE, ""); | ||
| let previous: string; | ||
| let current = html; | ||
|
|
||
| do { | ||
| previous = current; | ||
| current = previous | ||
| .replace(DANGEROUS_TAG_RE, "") | ||
| .replace(EVENT_HANDLER_RE, ""); | ||
| } while (current !== previous); | ||
|
|
||
| return current; | ||
| } | ||
|
|
||
| type Highlighter = HighlighterGeneric<string, string>; |
| const EVENT_HANDLER_RE = /\s+on\w+\s*=\s*["'][^"']*["']/gi; | ||
|
|
||
| function sanitize(html: string): string { | ||
| return html.replace(DANGEROUS_TAG_RE, "").replace(EVENT_HANDLER_RE, ""); |
Check failure
Code scanning / CodeQL
Incomplete multi-character sanitization High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 days ago
General fix: Stop relying on a single-pass multi-character regex replacement to enforce HTML safety. Instead, either (a) use a well-tested HTML sanitization library, or (b) make the regex-based approach robust by repeatedly sanitizing until a fixed point is reached so that no newly formed matches remain.
Best fix here without changing existing functionality: Wrap the current two-step .replace chain in a loop that keeps applying the same replacements until they no longer change the string. This preserves the exact semantics of the current regexes (we’re still removing the same patterns in the same way) while addressing the “incomplete multi-character sanitization” concern by eliminating residual dangerous tags or event handlers that might appear after the first pass.
Concretely, in dashboard/src/web/lib/utils/markdown.ts, modify sanitize (lines 7–9). Replace the single return html.replace(...).replace(...); line with a small loop: track the previous value, repeatedly apply .replace(DANGEROUS_TAG_RE, "").replace(EVENT_HANDLER_RE, ""), and stop when the result stops changing. No new imports are required, and the rest of the file remains unchanged. escapeHtml is already only used for code blocks, so it doesn’t need modification.
| @@ -5,7 +5,17 @@ | ||
| const EVENT_HANDLER_RE = /\s+on\w+\s*=\s*["'][^"']*["']/gi; | ||
|
|
||
| function sanitize(html: string): string { | ||
| return html.replace(DANGEROUS_TAG_RE, "").replace(EVENT_HANDLER_RE, ""); | ||
| let previous: string; | ||
| let current = html; | ||
|
|
||
| do { | ||
| previous = current; | ||
| current = previous | ||
| .replace(DANGEROUS_TAG_RE, "") | ||
| .replace(EVENT_HANDLER_RE, ""); | ||
| } while (current !== previous); | ||
|
|
||
| return current; | ||
| } | ||
|
|
||
| type Highlighter = HighlighterGeneric<string, string>; |
Summary
Release v2.1.0 consolidating all work since v2.1.1 patch release.
Highlights
codeforge proxy— new CLI command to launch Claude Code through mitmproxy (mitmweb) for real-time API traffic inspection. Auto-installs mitmproxy, manages CA certificates, provides browser UI at port 8081. Useful for monitoring token usage and rate limit utilization viaanthropic-ratelimit-unified-*response headers.codeforge-dashboardbuilt from monorepodisabled-hooks.jsonwithout disabling entire pluginsCLAUDE_VERSION_LOCKin.envclaude-code-nativeinstall failuresPackages affected
cli/— new proxy command, testscontainer/— changelog, docs, config, scripts, plugin fixesdashboard/— first-party dashboard package (added in prior commits)Test plan
cd cli && bun test— 320 tests passcd cli && bun run build— builds successfullycodeforge proxy --setupinstalls mitmproxy and CA certcodeforge proxylaunches mitmweb + claude, traffic visible at :8081CLAUDE_VERSION_LOCK=2.1.80in.env, verify pinned on container startdisabled-hooks.json, verify hook skippedcodeforge-dashboard