Repository navigation
fix: security and settings bug batch (#517, #532, #533, #543, #544, #545, #547, #548) - #551
Merged
Merged
Conversation
Record the creating PID; rebuild with dispose(close=False) on mismatch and drop inherited engines on worker_process_init. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
Add auth.contracts.tokens.parse_bearer(), the one reader of an Authorization: Bearer header: the scheme is matched case-insensitively (RFC 9110 §11.1) and surrounding whitespace is tolerated. The users and keycloak providers and the api_tokens resolver all use it, so a client that builds its header from /auth/token's token_type authenticates. /auth/token now returns token_type="Bearer". Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…on (#543) The OAuth callback now checks, before find-or-create, whether the identity already belongs to an account (linked OAuth account, then email association). With allow_signup off and no such account it answers 403 OAUTH_SIGNUP_DISABLED, the same error-code shape as the callback's other refusals; existing accounts still link and sign in. The fake OAuth provider used by test_external_users moves to a shared _users_oauth_support helper. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
With users.require_verification off, on_after_register marks a self-registered account verified and sends no verification email, so the new user can sign in at once. Request-less creates (admin, invite) and OAuth provisioning are unchanged; with the setting on, behaviour is as before. The register view passes require_verification to the page, whose aside bullet and success screen now follow it (new users.register keys, i18n keys regenerated). attach_default_role moves to users/registration.py to keep manager.py under the 300-line cap. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
Every authenticated file route (list, get, download, thumbnail, publish, delete, bulk delete) and the browse screen now act only on rows the caller uploaded (created_by == current user id) unless they hold file_storage.manage. Another user's id answers 404 like an unknown one. The scope is resolved by deps.get_owner_scope and passed to the service as an explicit owner= argument, so internal callers (branding, reapers) stay unscoped and anonymous public serving is untouched. file_storage.manage is now mapped to tenant admins and owners; platform admins hold it via *. Browse facets for scoped callers come from their own rows only. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
Replace the ACTIVE_CONTENT_TYPES deny-list, which missed scriptable XML (atom/rss/mathml +xml, text/xsl, vnd.wap.xhtml+xml) and let odd casing, parameters or malformed values through, with an allow-list of types safe to serve inline: common raster images, PDF, JSON, text/plain, text/csv and audio/* or video/* (minus any xml/html subtype). The stored type is lower-cased and stripped of parameters; anything that is not exactly one type/subtype token pair (text/html,) is treated as active rather than cleaned up, so it is served as a sandboxed attachment and streamed. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
quota_bytes accepted -1, 0 and 2**63. It is now Field(gt=0, le=2**53 - 1): None still means unmeasured, and the upper bound keeps the value exact in the browse screen and settings editor, which read it as a JS number. Stored out-of-range rows are dropped by the existing lenient hydration. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…545) application/octet-stream (PMTiles), zip, gzip, protobuf / vector tiles, GeoJSON and font/* are never rendered as documents, and treating them as active would stream S3 range reads through the app instead of redirecting to the presigned URL. Caught by test_public_route_serves_ranges_with_its_headers. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
… it active (#545) The check read the part before ';', but a browser splits the header on commas first: image/png;x=1,text/html was classified inline-safe and rendered as HTML. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…ng; OAuth won't link unverified accounts (#547) Self-registration with users.require_verification off no longer marks the account verified. Password login skips the verification requirement while the setting is off, so earlier signups get in too. The OAuth callback refuses to associate by email with an unverified, self-registered password account (403 OAUTH_ACCOUNT_NOT_VERIFIED), closing an account pre-hijack: an attacker registering the victim's address would otherwise share the victim's account once they signed in with SSO. Already-linked identities, verified accounts, external accounts and pending invites still sign in. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…ld rule (#548) The background_tasks soft/hard time-limit rule is reported on task_time_limit so the editor shows it on that field. With the hard limit pinned by env and the soft limit stored, lenient hydration had no DB key to drop and re-raised: the web lost every background_tasks override and the worker refused to start. A validator can now name the other fields it depends on under ctx[RELATED_FIELDS_CTX]; when the reported field did not come from the DB, lenient hydration drops those instead and logs it. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…every read (#517) A permanently failing runtime permission source was called, and logged a full traceback, on every read of the registry — about once per request. The failure is now remembered for SOURCE_RETRY_SECONDS (monotonic clock, injectable for tests): reads in that window answer empty without calling it, and the traceback is logged once per window. A transient failure still recovers without invalidate_source, which now also clears the failure. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Deploying simple-module-python with
|
| Latest commit: |
9f2c4d5
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://0b3b874f.simple-module-python.pages.dev |
| Branch Preview URL: | https://fix-bug-batch-517-548.simple-module-python.pages.dev |
…, reuse base_type - background_tasks: fold the #548 env-pin tests into the runner/settings suites - users tests: find_user, seed_password_user, set_users_settings in the shared support module - file_storage: OwnerScope defined once in deps; media_types reuses thumbnails.base_type; owner-scope tests use the shared upload helpers Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…ne, one Register copy object, typed _culprits Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
/auth/token refuses unverified accounts while require_verification is on; the all_permissions snapshot is cached until a failing source's retry instead of rebuilt per check. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
antosubash
added a commit
that referenced
this pull request
Oct 19, 2026
…gs defaults, inline errors) (#552) * fix(file_storage): show owner-scoped callers their own usage, not the tenant's Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4 * fix(file_storage): sandbox CSP on streamed authenticated downloads Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4 * fix(settings): show a field's validation error on its own row below the control Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4 * fix(settings): saving a field's default removes its override row Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4 * fix(settings): a no-op save of a default removes its stale override row Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4 * docs: changelog for the #551 QA follow-ups Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
antosubash
added a commit
that referenced
this pull request
Oct 19, 2026
…gs defaults, inline errors) (#553) * fix(file_storage): show owner-scoped callers their own usage, not the tenant's Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4 * fix(file_storage): sandbox CSP on streamed authenticated downloads Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4 * fix(settings): show a field's validation error on its own row below the control Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4 * fix(settings): saving a field's default removes its override row Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4 * fix(settings): a no-op save of a default removes its stale override row Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4 * docs: changelog for the #551 QA follow-ups Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes a batch of open bugs, most of them security issues found while reviewing and testing #525.
Closes #517
Closes #532
Closes #533
Closes #543
Closes #544
Closes #545
Closes #547
Closes #548
Behaviour changes
file_storage.managecan list, get, download, thumbnail, change visibility and delete only files they uploaded. Anyone else's file is a 404.manageis held by admins (*) and bytenant:adminandtenant:owner. Files with no recorded uploader are now visible to managers only. Internal callers such as branding are unscoped.*+xml,text/xsl, and any malformed value (such as a comma or quote anywhere).allow_signupis off, OAuth refuses to create accounts with a 403OAUTH_SIGNUP_DISABLED. Existing linked accounts and accounts matched by email still sign in.require_verification. While the setting is off, no verification email is sent and password login doesn't require verification; the register page copy follows the setting. To prevent pre-hijacking, OAuth now refuses to link by email to an unverified account that has a password (403OAUTH_ACCOUNT_NOT_VERIFIED). Pending invites still link.auth.contracts.tokens.parse_bearer, used by the users, keycloak and api_tokens resolvers./auth/tokenreturnstoken_type="Bearer".Fixes
dispose(close=False), both on a PID mismatch and onworker_process_init.quota_bytesmust be between 1 and 2^53-1.task_time_limitmust be greater thantask_soft_time_limit.Review
image/png;x=1,text/html).Verification
make lint: pass.make test-js: pass.pg_backend_pid()fork test for background_tasks: cached sync engine is not reset after Celery prefork, so children can share inherited DB connections #532 is marked@pytest.mark.postgres. It passed once against the local Postgres; CI's SQLite run skips it./ship
OwnerScopedependency; the engine PID resets inside_drop_engine; Register picks its copy once;_culpritsis typed./auth/tokennow refuses unverified accounts whilerequire_verificationis on. It used to mint bearer tokens for them, so this is now in the CHANGELOG.all_permissionsis cached until a failing source's retry instead of being rebuilt on every check.https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4