💡 Codex Review
|
await self._queue.set_state( |
|
job.job_id, |
|
JobStatus.DISPATCHED, |
|
details={"attempt": attempts + 1}, |
|
) |
Preserve job ownership details across dispatcher status updates
JobDispatcher._dispatch_job replaces state.details with small dictionaries (for example {"attempt": ...}), which drops owner_user_id and owner_extension_id that were written at job creation. The authorization checks in jobs.py (get_job_state, stream_job_updates, and publish_job_update) depend on those fields, so once a job is dispatched any authenticated user/extension can read or update jobs they do not own.
|
db: Session = Depends(session_dependency), |
|
broker: WorkflowRunEventBroker = Depends(get_workflow_event_broker), |
Avoid holding request DB sessions for workflow SSE streams
stream_workflow_run is an SSE endpoint but takes db: Session = Depends(session_dependency) at request scope; with FastAPI yield dependencies, that session is not cleaned up until the stream ends. In practice each open stream keeps a DB session/transaction alive for its full lifetime, which can exhaust the SQLAlchemy pool under concurrent viewers and block unrelated API work.
|
artifact = db.get(Artifact, artifact_id) |
|
if not artifact: |
Enforce artifact authorization in extension download route
download_artifact_for_extension fetches artifacts by raw UUID and returns the file without any course/submission/owner permission check. Any extension client with jobs:read can therefore download arbitrary artifacts if it knows or guesses IDs, creating cross-course data exposure in production.
ℹ️ 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".
Originally posted by @chatgpt-codex-connector[bot] in #185 (comment)
💡 Codex Review
FAIR/src/fair_platform/backend/services/job_dispatcher.py
Lines 76 to 80 in 5391684
JobDispatcher._dispatch_jobreplacesstate.detailswith small dictionaries (for example{"attempt": ...}), which dropsowner_user_idandowner_extension_idthat were written at job creation. The authorization checks injobs.py(get_job_state,stream_job_updates, andpublish_job_update) depend on those fields, so once a job is dispatched any authenticated user/extension can read or update jobs they do not own.FAIR/src/fair_platform/backend/api/routers/workflow_runs.py
Lines 247 to 248 in 5391684
stream_workflow_runis an SSE endpoint but takesdb: Session = Depends(session_dependency)at request scope; with FastAPI yield dependencies, that session is not cleaned up until the stream ends. In practice each open stream keeps a DB session/transaction alive for its full lifetime, which can exhaust the SQLAlchemy pool under concurrent viewers and block unrelated API work.FAIR/src/fair_platform/backend/api/routers/artifacts.py
Lines 150 to 151 in 5391684
download_artifact_for_extensionfetches artifacts by raw UUID and returns the file without any course/submission/owner permission check. Any extension client withjobs:readcan therefore download arbitrary artifacts if it knows or guesses IDs, creating cross-course data exposure in production.ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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".
Originally posted by @chatgpt-codex-connector[bot] in #185 (comment)