Skip to content

fix(history): deny unknown page IDs in access check#57

Open
Micsi wants to merge 1 commit into
mainfrom
codex/propose-fix-for-unauthenticated-history-access
Open

fix(history): deny unknown page IDs in access check#57
Micsi wants to merge 1 commit into
mainfrom
codex/propose-fix-for-unauthenticated-history-access

Conversation

@Micsi
Copy link
Copy Markdown
Owner

@Micsi Micsi commented May 18, 2026

Upstream Tracking

Motivation

  • Close an authorization bypass where a forged X-Page-Id or a node with inherited/NULL access was treated as public, allowing unauthenticated reads of history/aggregate endpoints.
  • Ensure history endpoints use the same effective page ACL resolution as other API paths instead of defaulting missing rows to public.

Description

  • Added async def _resolve_page_access(db: Database, node_id: str) -> str which walks visu_nodes.parent_id to determine the effective access level and returns "private" for unknown nodes.
  • Updated _check_history_access(request, user, db) to call await _resolve_page_access(db, page_id) and use the resolved ACL instead of defaulting missing/NULL access to public.
  • Preserved existing behavior for public, readonly, and protected pages and kept session-token validation via validate_session unchanged.
  • Changes made in obs/api/v1/history.py to deny unknown page IDs and fail closed for missing/inherited ACLs.

Testing

  • Attempted to run pytest -q tests/integration/test_history.py -k limit_above_1000, but the test run failed in this environment due to a missing test dependency (ModuleNotFoundError: No module named 'pytest_asyncio').

Codex Task

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

if session_token and validate_session(session_token, page_id):

P1 Badge Validate protected session against defining ACL node

When access is inherited from a protected ancestor, this check validates the token against the requested page id, but session tokens are minted for the node passed to /visu/nodes/{node_id}/auth and validate_session requires an exact node-id match. After this commit started resolving inherited ACLs, protected child pages now hit this branch and valid tokens from the defining protected parent are rejected with 401, breaking legitimate history reads for inherited-protected pages.

ℹ️ 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 obs/api/v1/history.py
async def _resolve_page_access(db: Database, node_id: str) -> str:
"""Traversiert die parent_id-Kette und gibt das effektive Access-Level zurück."""
current_id: str | None = node_id
while current_id:
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 Badge Guard against cycles in access-chain traversal

Track visited node IDs (or enforce a max depth) in _resolve_page_access, because the current while current_id loop can become non-terminating when visu_nodes.parent_id contains a cycle. Cycles are possible from existing write paths (for example, node moves do not enforce acyclic parent relationships), and with such data a history request using that X-Page-Id will repeatedly query forever, tying up a worker and creating a denial-of-service condition for affected endpoints.

Useful? React with 👍 / 👎.

@Micsi Micsi added the promoted upstream Fork PR has an associated upstream PR label May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

aardvark codex promoted upstream Fork PR has an associated upstream PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant