Skip to content

fix(dav): stop advertising unimplemented production methods - #1296

Closed
seonghobae wants to merge 15 commits into
developfrom
fix/dav-capability-truthfulness-20260809
Closed

fix(dav): stop advertising unimplemented production methods#1296
seonghobae wants to merge 15 commits into
developfrom
fix/dav-capability-truthfulness-20260809

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • register only the production-backed DAV methods (OPTIONS and PROPFIND);
  • reduce the DAV compliance header to class 1 instead of claiming locking, calendar, or address-book behavior that is not implemented;
  • remove success-shaped and 501 Not Implemented DAV/demo handlers so unsupported verbs receive framework-level 405 Method Not Allowed;
  • lock the transitive nanoid remediation through the authoritative pnpm workspace and frozen lock;
  • remove both temporary branch-writing one-shot workflows and add a repository contract that rejects future workflow-based source publishers.

Product contract

An unsupported capability is no longer advertised as if it were part of the product. Provider-backed mutation remains available only through signed writeback-intent APIs until DAV mutation semantics, source capability checks, and ETag/If-Match enforcement are implemented. The durable DAV boundary is recorded in backend/docs/dav-production-capabilities.md.

RCA and remedy

The prior branch attempted to materialize the changelog and lock through two push-triggered Actions jobs with contents: write and git push. Those temporary publishers were the first security boundary failure and also left the lock unchanged because the real override authority is frontend/pnpm-workspace.yaml, not only package.json.

Exact head 00bb2d6bd80faee9e0ff5fec6c558003207f7bf3 removes both workflows, records nanoid: 5.1.6 in the workspace and lock, and adds test_github_workflows_never_push_repository_source_branches. The two GHAS token-permission findings are therefore addressed at source rather than weakened.

Verification

Validated locally against the published source tree:

  • backend full suite: 1,701 passed, 33 skipped with proxy transport variables removed;
  • focused DAV/governance suite: 61 passed;
  • frontend: 427 passed;
  • ESLint and TypeScript typecheck: passed;
  • Ruff, compileall, and git diff --check: passed;
  • pnpm 11.5.3 frozen-lock install: passed;
  • resolved dependency graph: postcss 8.5.24 -> nanoid 5.1.6;
  • published remote tree was refetched; the complete pre-existing CHANGELOG blob is preserved.

Current exact-head GitHub CI/security/review evidence remains required before merge.

Summary by CodeRabbit

  • Security
    • Updated the frontend dependency to nanoid 5.1.16 and added safeguards to keep all installations on a secure version.
  • Bug Fixes
    • Improved DAV endpoint behavior by clearly advertising supported OPTIONS and PROPFIND capabilities.
    • Unsupported DAV methods now consistently return 405 Method Not Allowed.
    • Improved protection against control characters in DAV-related logging.
  • Documentation
    • Added documentation covering DAV capabilities and the dependency security update.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review available on request

  • 🔍 Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bafaeae3-14da-4ac7-b0f7-ee2e11035a5b

📝 Walkthrough

Walkthrough

Changes

DAV capability scope

Layer / File(s) Summary
DAV route capability contract
backend/api/dav.py
The route now supports only OPTIONS and PROPFIND. OPTIONS advertises DAV version 1 and the implemented methods. PROPFIND uses project collection handling.
WebDAV persistence and capability contract
backend/services/webdav_service.py, backend/docs/dav-production-capabilities.md
Demo storage, fake synchronization, and no-op write APIs were removed. The production contract defines persisted data, ownership, writeback, and safety behavior.
DAV regression coverage
backend/tests/test_dav_api.py, backend/tests/test_dav_sync.py
Tests verify method advertisements, 405 responses, log escaping, and removal of demo synchronization APIs.

nanoid security enforcement

Layer / File(s) Summary
nanoid resolution authorities and checks
frontend/package.json, frontend/pnpm-workspace.yaml, frontend/src/lib/dependency-security.test.ts, backend/tests/test_release_governance.py
Frontend dependency authorities pin nanoid to 5.1.16. Tests validate configured and lockfile resolutions.
nanoid remediation and workflow governance
CHANGELOG.md, docs/doctoring/nanoid-cve-2026-67214.md, backend/tests/test_release_governance.py
The CVE remediation evidence is documented. Governance tests reject workflows that combine contents: write with git push.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary DAV change: stopping advertisement of unimplemented production methods.
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 💡 1
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch fix/dav-capability-truthfulness-20260809
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/dav-capability-truthfulness-20260809

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.

❤️ Share

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

Comment thread backend/tests/test_dav_api.py Fixed
Comment thread .github/workflows/one-shot-dav-production-contract.yml Fixed
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

PR governance metadata gate is not ready for 9bcf66d6c5cd6f3d4f46f5b44f4dd0d8aab879c4:

  • Merge state is DIRTY; resolve conflicts before merge.
  • Review decision is CHANGES_REQUESTED; address requested changes before merge.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 9, 2026
Comment thread .github/workflows/one-shot-nanoid-lock-refresh.yml Fixed
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/services/webdav_service.py (1)

20-35: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Enforce workspace isolation across DAV persistence paths. The DAV service queries do not consistently constrain records to the active workspace. This can disclose or select resources from another workspace in the same organization.

  • backend/services/webdav_service.py#L20-L35: require a workspace scope or explicitly constrain intentional global accounts with workspace_id IS NULL.
  • backend/services/webdav_service.py#L52-L68: accept workspace_id and filter ProjectFolder records by it.
  • backend/services/webdav_service.py#L107-L119: apply workspace_id to the task and provenance query.
  • backend/api/dav.py#L201-L205: pass auth_context.workspace_id to the project-folder lookup.
🤖 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 `@backend/services/webdav_service.py` around lines 20 - 35, Enforce workspace
isolation across all listed DAV persistence paths: in
backend/services/webdav_service.py lines 20-35, require a workspace scope or
explicitly filter intentional global accounts with workspace_id IS NULL; in
lines 52-68, update the project-folder lookup to accept workspace_id and
constrain ProjectFolder records; in lines 107-119, apply workspace_id to the
task and provenance query; and in backend/api/dav.py lines 201-205, pass
auth_context.workspace_id to the project-folder lookup. Update the relevant
service methods and callers while preserving existing organization and user
scoping.

Source: Coding guidelines

🤖 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 `@backend/tests/test_release_governance.py`:
- Around line 327-332: Update the source-publishing check around the
governed_workflows loop to parse each workflow and evaluate effective workflow-
and job-level contents permissions, including permissions: write-all and
job-level contents: write. Detect publication through shell commands, GitHub Git
refs API calls, and supported actions that create or update refs, while
continuing to allow package-only publishing; append the relative workflow path
only when these semantic checks identify source publication.

In `@docs/doctoring/nanoid-cve-2026-67214.md`:
- Line 53: Update the documented backend verification command to run with
PYTHONWARNINGS=error and DISABLE_BACKGROUND_WORKERS=1, then rerun the full suite
in the existing frozen offline mode. Replace the reported result only after all
tests pass with no Timeout, Fatal, Warn, or Denied output; do not report
warnings.

In `@frontend/src/lib/dependency-security.test.ts`:
- Around line 28-30: Update the lockfile assertions in the dependency security
test to parse both package entries and snapshot keys for every locked nanoid
version. Assert that each discovered version is outside the documented affected
range, rejecting all affected versions rather than only the literal nanoid@5.1.6
key, while preserving the existing expected 5.1.16 checks.

---

Outside diff comments:
In `@backend/services/webdav_service.py`:
- Around line 20-35: Enforce workspace isolation across all listed DAV
persistence paths: in backend/services/webdav_service.py lines 20-35, require a
workspace scope or explicitly filter intentional global accounts with
workspace_id IS NULL; in lines 52-68, update the project-folder lookup to accept
workspace_id and constrain ProjectFolder records; in lines 107-119, apply
workspace_id to the task and provenance query; and in backend/api/dav.py lines
201-205, pass auth_context.workspace_id to the project-folder lookup. Update the
relevant service methods and callers while preserving existing organization and
user scoping.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 0b7b400a-fdce-4478-9f62-f209c837e47e

📥 Commits

Reviewing files that changed from the base of the PR and between 5425ce4 and fa0ab43.

⛔ Files ignored due to path filters (1)
  • frontend/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • CHANGELOG.md
  • backend/api/dav.py
  • backend/docs/dav-production-capabilities.md
  • backend/services/webdav_service.py
  • backend/tests/test_dav_api.py
  • backend/tests/test_dav_sync.py
  • backend/tests/test_release_governance.py
  • docs/doctoring/nanoid-cve-2026-67214.md
  • frontend/package.json
  • frontend/pnpm-workspace.yaml
  • frontend/src/lib/dependency-security.test.ts

Comment thread backend/tests/test_release_governance.py
Comment thread docs/doctoring/nanoid-cve-2026-67214.md Outdated
Comment thread frontend/src/lib/dependency-security.test.ts Outdated
Keep the fail-closed DAV method set and the patched nanoid 5.1.16 pin
when merging current develop. Align the incoming 3.x-only Nano ID
lock test with that same patched override.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
@cursor

cursor Bot commented Aug 16, 2026

Copy link
Copy Markdown

Merged current develop into this branch to clear the DIRTY merge conflict.

Resolution on exact head 254ba721:

  • Kept fail-closed DAV registration (OPTIONS/PROPFIND only; unsupported verbs stay framework 405).
  • Kept the patched nanoid@5.1.16 override already present in the frontend manifests and lock overrides. Develop’s incoming 3.x-only lock test now follows that same pin.
  • Preserved this branch’s cryptography/PostCSS/tooling lock governance tests.

Focused verification in progress:

PYTHONWARNINGS=error DISABLE_BACKGROUND_WORKERS=1 python -m pytest \
  backend/tests/test_dav_api.py \
  backend/tests/test_dav_sync.py \
  backend/tests/test_frontend_nanoid_security.py \
  backend/tests/test_release_governance.py \
  backend/tests/test_workflow_source_publication_governance.py -q

@cursor cursor 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.

Review — 254ba721 (do not merge this head)

The DAV honesty contract is the right product change: OPTIONS/PROPFIND only, DAV: 1, unsupported verbs unregistered so clients get framework 405 instead of a success-shaped or 501 handler. Owner-scope, ownerless-path reject, XML escaping, and repr() log encoding stay in place. The nanoid@5.1.16 pin is consistent across package, workspace, and both lock sections.

Do not merge this head. The develop-merge commit added test_cryptography_runtime_pins_are_bleichenbacher_oracle_fixed, which calls tomllib.loads with no import. App CI will NameError as soon as that test is collected/run.

Landing vehicle: #1380 (45652bbc) adds the missing top-of-module import tomllib on top of this branch.

flowchart LR
  dav["DAV OPTIONS/PROPFIND"] --> honest["405 for other verbs"]
  merge["254ba721 merge"] --> bug["NameError tomllib"]
  bug --> ci["backend pytest fails"]
  fix["#1380 import tomllib"] --> ciFix["pin contract can run"]
Loading

Prior CodeRabbit CHANGES_REQUESTED on fa0ab43c

Finding Still valid on 254ba721?
Semantic source-publish detector (write-all, job-level contents: write, refs API, package-only allow) Addressed by backend/tests/test_workflow_source_publication_governance.py. The leftover substring check in test_release_governance.py is residual only.
Doctoring command must use PYTHONWARNINGS=error and DISABLE_BACKGROUND_WORKERS=1 Addressed in docs/doctoring/nanoid-cve-2026-67214.md.
Reject every affected locked nanoid version, not only 5.1.6 Addressed in frontend/src/lib/dependency-security.test.ts.
ProjectFolder / task queries must filter workspace_id Not a one-line fix on this PR. ProjectFolder and TicketTask have no workspace_id column. WebdavAccount already filters when a workspace is passed.

Next action

Close or leave #1296 open as historical, and land #1380 after its current-head checks are green. Do not cherry-pick this head without the tomllib import.

Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

"""Require every governed Python surface to use the first oracle-safe release."""
backend_requirements = read_repo_text("backend/requirements.txt")
backend_project_text = read_repo_text("backend/pyproject.toml")
backend_project = tomllib.loads(backend_project_text)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 — this new pin test calls tomllib.loads but the module never imports tomllib. App CI raises NameError: name 'tomllib' is not defined before any cryptography assertion runs.

Add a top-of-module stdlib import (do not import inside the test body):

import tomllib

Landing fix is already on 45652bbc in #1380. Verify with:

PYTHONWARNINGS=error DISABLE_BACKGROUND_WORKERS=1 python -m pytest \\
  backend/tests/test_release_governance.py::test_cryptography_runtime_pins_are_bleichenbacher_oracle_fixed -q

Copy link
Copy Markdown
Contributor Author

Closing as technically superseded by #1380, not because the DAV work is unwanted. Fresh exact-head comparison proves 254ba7212b209ecf3e8fa8e0a6d8f1571483a166...45652bbc53fe32c7dab69da42326a1e3eda44ad0 is ahead_by: 1, behind_by: 0, with merge-base exactly #1296 head. The sole successor commit imports stdlib tomllib so the develop-added cryptography pin test can execute instead of raising NameError. #1380 therefore preserves the complete #1296 tree plus the required CI fix. #1380 is still Draft/queued and must satisfy its own unchanged-head checks, threads, live rules, and qualifying independent post-last-push approval before any merge; this closure is only queue deduplication and does not manufacture passing evidence.

@seonghobae seonghobae closed this Aug 16, 2026
@cursor

cursor Bot commented Aug 17, 2026

Copy link
Copy Markdown

Hosted backend (Python 3.14) failed on 254ba721 at Run backend lint (ruff F821), before tests ran.

Exact head 2e765565 restores the tomllib import used by the kept cryptography pin test after the develop merge dropped it. Local ruff check . is clean, and the focused governance/nanoid tests still pass. DAV fail-closed registration is unchanged.

@cursor

cursor Bot commented Aug 17, 2026

Copy link
Copy Markdown

Hosted backend (Python 3.14) failed on 254ba721 at Run backend lint (tests were skipped). Ruff F821: the develop merge kept test_cryptography_runtime_pins_are_bleichenbacher_oracle_fixed but dropped import tomllib.

Exact head 2e765565 restores that import. Local ruff check . is clean; focused governance/nanoid tests still pass. DAV fail-closed registration is unchanged (OPTIONS/PROPFIND only).

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.

3 participants