Skip to content

fix(security): close Strix tenant and connector boundaries - #1123

Closed
seonghobae wants to merge 7 commits into
developfrom
audit/strix-base-security-1114
Closed

fix(security): close Strix tenant and connector boundaries#1123
seonghobae wants to merge 7 commits into
developfrom
audit/strix-base-security-1114

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Summary

This base-branch security follow-up remediates all seven actionable Strix findings reported against PR #1114.

  • bind runner responses to opaque per-socket connection identities, reject duplicate request IDs, and revoke live sockets only after credential rotation commits
  • pin validated public IMAP destinations through TLS connection establishment without a second DNS lookup while preserving hostname verification and SNI
  • require an explicit OIDC API audience, an exact at+jwt access-token type, and an authorized client claim distinct from audience validation
  • make inbound email task creation replay-safe with normalized deduplication and a PostgreSQL partial unique expression index
  • enforce workspace ownership for calendar writeback sources and organization ownership for document quality statistics
  • add regression coverage for stale disconnects, cross-connection response injection, DNS rebinding, replay races, and cross-tenant reads

Migration and configuration notes

  • Alembic revision 0018_email_task_idempotency collapses exact duplicate email tasks before installing the unique index. Downgrade removes the index and intentionally does not recreate deleted duplicates.
  • OIDC deployments must set OIDC_API_AUDIENCE; it must differ from OIDC_CLIENT_ID.
  • Existing runner credentials keep their normal rotation contract, but successful rotation now terminates all live sockets for the organization so old tokens cannot retain an authenticated channel.

Validation

  • uv run ruff check .
  • uv run pytest -q — 1554 passed, 33 skipped
  • uv run --project backend ruff check backend/services/imap_worker.py backend/tests/test_imap_worker.py
  • uv run --project backend pytest -q backend/tests/test_imap_worker.py — 7 passed
  • git diff --check
  • CodeGraph synchronized and explored current ConnectionManager call paths and response ownership boundaries

Copilot AI review requested due to automatic review settings July 22, 2026 01:23

Copilot AI 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.

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

This PR hardens tenant and connector security boundaries by tightening OIDC access-token validation, pinning outbound IMAP connections to validated IPs to prevent DNS rebinding, and making several cross-tenant/cross-workspace operations replay-safe and scope-safe.

Changes:

  • Enforces stricter OIDC API token requirements (dedicated audience + typ=at+jwt + authorized-client claim).
  • Pins IMAP network connections to pre-validated socket destinations (prevents second DNS lookup) and adds regression tests.
  • Adds replay-safe email task creation with a partial unique index + migration, runner WS per-connection response binding, and stricter org/workspace scoping for calendar/data APIs.

Reviewed changes

Copilot reviewed 26 out of 26 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
docs/operations/auth-key-management.md Documents new OIDC access-token requirements (audience + at+jwt + client).
AGENTS.md Updates agent/security guidance for OIDC API audience and token type expectations.
backend/core/config.py Adds OIDC_API_AUDIENCE and validates it (including distinctness from client id).
backend/scripts/start_backend.py Extends runtime validation for new OIDC env var and distinct audience.
backend/api/auth.py Enforces typ=at+jwt, dedicated API audience, and azp/client_id checks.
backend/services/email_client.py Introduces ValidatedImapDestination and pinned IMAP socket connection helper.
backend/services/imap_worker.py Switches IMAP sync to pinned sockets and preserves TLS hostname verification/SNI.
backend/api/tasks.py Makes email-derived task creation idempotent and replay-safe (DB-enforced).
backend/db/models.py Adds partial unique expression index to enforce email task idempotency.
backend/alembic/versions/0018_email_task_idempotency.py Migration to collapse duplicates then install unique boundary.
backend/api/runner_ws.py Binds runner responses to per-connection IDs; rejects duplicate request IDs; supports revocation.
backend/api/runner_config.py Revokes live runner sockets after credential rotation.
backend/api/calendar.py Enforces workspace ownership when selecting/authorizing writeback sources.
backend/api/data.py Adds organization scoping to document quality surface query.
backend/tests/test_auth_real.py Adds coverage for OIDC token type/audience/authorized-client enforcement.
backend/tests/test_config.py Adds tests for OIDC_API_AUDIENCE behavior and distinctness.
backend/tests/test_start_backend.py Updates runtime settings tests to include new OIDC env var requirements.
backend/tests/test_email_client_pop3_imap.py Adds DNS rebinding regression test for pinned IMAP socket connections.
backend/tests/test_imap_worker.py Updates IMAP worker tests for pinned sockets and TLS hostname behavior.
backend/tests/live/mail_smoke_test.py Updates live IMAP smoke path to use pinned socket + pinned client builder.
backend/tests/test_tasks_api.py Adds model/index assertions and replay/idempotency tests for email task creation.
backend/tests/test_alembic_migrations.py Validates new Alembic revision installs expected unique boundary.
backend/tests/test_runner_ws_api.py Adds regression tests for stale disconnects, response injection, and revocation.
backend/tests/test_runner_config_api.py Adds test ensuring rotate triggers live-connection revocation.
backend/tests/test_calendar_api.py Adds coverage for cross-workspace writeback rejection and workspace scoping in DB queries.
backend/tests/test_data_api.py Updates fake DB layer + assertions for org scoping in data quality surface.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread backend/services/imap_worker.py Outdated
Comment thread backend/services/email_client.py Outdated
Comment thread backend/api/tasks.py
Comment thread backend/db/models.py
Copilot AI review requested due to automatic review settings July 22, 2026 01:58

Copilot AI 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.

Pull request overview

Copilot reviewed 26 out of 26 changed files in this pull request and generated 3 comments.

Comment thread backend/api/tasks.py Outdated
Comment thread backend/alembic/versions/0018_email_task_idempotency.py
Comment thread backend/services/email_client.py Outdated
Comment thread backend/api/auth.py Fixed
Comment thread backend/api/runner_ws.py Fixed
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

PR governance metadata gate update for 606d3bbe6d945611933c7c7b42ca1cbbc4cf65f1: no current blocking failures remain.

PR governance metadata gate is waiting on current-head requirements; see the latest check for pending reasons.

Copilot AI review requested due to automatic review settings July 22, 2026 09:28

Copilot AI 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.

Pull request overview

Copilot reviewed 26 out of 26 changed files in this pull request and generated 4 comments.

Comment thread backend/api/tasks.py Outdated
Comment thread backend/alembic/versions/0018_email_task_idempotency.py
Comment thread backend/tests/live/mail_smoke_test.py Outdated
Comment thread backend/tests/live/mail_smoke_test.py Outdated
Copilot AI review requested due to automatic review settings July 22, 2026 10:28

Copilot AI 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.

Pull request overview

Copilot reviewed 26 out of 26 changed files in this pull request and generated 4 comments.

Comment thread backend/api/runner_ws.py
Comment thread backend/api/runner_ws.py
Comment thread backend/api/runner_ws.py
Comment thread backend/alembic/versions/0018_email_task_idempotency.py
Copilot AI review requested due to automatic review settings July 22, 2026 10:56

Copilot AI 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.

Pull request overview

Copilot reviewed 26 out of 26 changed files in this pull request and generated 2 comments.

Comment thread backend/api/runner_ws.py
Comment thread backend/db/models.py
Copilot AI review requested due to automatic review settings July 23, 2026 01:38

Copilot AI 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.

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • frontend/pnpm-lock.yaml: Generated file

@seonghobae
seonghobae enabled auto-merge July 23, 2026 01:48
@seonghobae
seonghobae requested a review from Copilot July 26, 2026 14:41

Copilot AI 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.

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • frontend/pnpm-lock.yaml: Generated file

Comment thread backend/api/tasks.py
Comment on lines +302 to +306
for attempt in range(2):
tasks_by_title = await _existing_email_tasks(
db,
auth_context=auth_context,
email_id=email.id,
Comment thread backend/api/tasks.py
Comment on lines +330 to +333
except IntegrityError as exc:
await db.rollback()
if not _is_email_task_idempotency_conflict(exc):
raise
Comment on lines +38 to +51
op.create_index(
_INDEX_NAME,
"ticket_tasks",
[
"user_id",
sa.text("COALESCE(organization_id, '')"),
"source_type",
"email_id",
sa.text("sha256(convert_to(task_title, 'UTF8'))"),
],
unique=True,
postgresql_where=sa.text("source_type = 'email' AND email_id IS NOT NULL"),
if_not_exists=True,
)
@opencode-agent
opencode-agent Bot disabled auto-merge July 26, 2026 15:07
@seonghobae

Copy link
Copy Markdown
Contributor Author

Closing as permanently blocked by long-standing merge conflicts vs develop after Loop drain. Security intent must be re-opened as a focused TDD PR on current develop (do not force-merge).

@seonghobae seonghobae closed this Jul 31, 2026
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