Skip to content

fix(security): fix SQL injection in the sample-listing sort parameter#286

Merged
gary-Shen merged 261 commits into
mainfrom
fix/security-vulnerabilities
Jul 13, 2026
Merged

fix(security): fix SQL injection in the sample-listing sort parameter#286
gary-Shen merged 261 commits into
mainfrom
fix/security-vulnerabilities

Conversation

@gary-Shen

Copy link
Copy Markdown
Member

No description provided.

semantic-release-bot and others added 30 commits October 28, 2024 03:35
## [1.0.7-alpha.6](v1.0.7-alpha.5...v1.0.7-alpha.6) (2024-10-28)

### Bug Fixes

* update notification action ([e9152c9](e9152c9))
## [1.0.7-alpha.7](v1.0.7-alpha.6...v1.0.7-alpha.7) (2024-10-28)

### Bug Fixes

* update notification action ([046f47a](046f47a))
## [1.0.7-alpha.8](v1.0.7-alpha.7...v1.0.7-alpha.8) (2024-10-28)

### Bug Fixes

* test notification action ([8fed078](8fed078))
## [1.0.7-alpha.9](v1.0.7-alpha.8...v1.0.7-alpha.9) (2024-10-28)

### Bug Fixes

* test notification action ([851818e](851818e))
## [1.0.7-alpha.10](v1.0.7-alpha.9...v1.0.7-alpha.10) (2024-10-28)

### Bug Fixes

* test notification action ([bc63ee5](bc63ee5))
## [1.0.7-alpha.11](v1.0.7-alpha.10...v1.0.7-alpha.11) (2024-10-28)

### Bug Fixes

* test notification action ([83f43eb](83f43eb))
## [1.0.7-alpha.12](v1.0.7-alpha.11...v1.0.7-alpha.12) (2024-10-28)

### Bug Fixes

* update notification action ([63286cb](63286cb))
## [1.0.9-alpha.1](v1.0.8...v1.0.9-alpha.1) (2024-10-28)

### Bug Fixes

* test notification action ([83f43eb](83f43eb))
* test notification action ([bc63ee5](bc63ee5))
* test notification action ([851818e](851818e))
* test notification action ([8fed078](8fed078))
* update notification action ([63286cb](63286cb))
* update notification action ([046f47a](046f47a))
* update notification action ([e9152c9](e9152c9))
* update notification action ([04e0388](04e0388))
* update notification action ([b6abe17](b6abe17))
* Upgrade frontend to v5.3.0-alpha.4. See the details in [release notes](https://github.com/opendatalab/labelU-Kit/releases/tag/v5.3.0-alpha.4) ([01fc3b5](01fc3b5))
* Upgrade frontend to v5.3.0-alpha.5. See the details in [release notes](https://github.com/opendatalab/labelU-Kit/releases/tag/v5.3.0-alpha.5) ([f97601d](f97601d))
## [1.0.9-alpha.2](v1.0.9-alpha.1...v1.0.9-alpha.2) (2024-10-28)

### Bug Fixes

* Upgrade frontend to v5.3.0-alpha.6. See the details in [release notes](https://github.com/opendatalab/labelU-Kit/releases/tag/v5.3.0-alpha.6) ([9f5e698](9f5e698))
## [1.0.9-alpha.3](v1.0.9-alpha.2...v1.0.9-alpha.3) (2024-10-28)

### Bug Fixes

* Upgrade frontend to v5.3.0-alpha.7. See the details in [release notes](https://github.com/opendatalab/labelU-Kit/releases/tag/v5.3.0-alpha.7) ([7cb455e](7cb455e))
## [1.0.9-alpha.4](v1.0.9-alpha.3...v1.0.9-alpha.4) (2024-10-29)

### Bug Fixes

* Upgrade frontend to v5.5.0-alpha.1. See the details in [release notes](https://github.com/opendatalab/labelU-Kit/releases/tag/v5.5.0-alpha.1) ([7b04670](7b04670))
* Upgrade frontend to v5.5.0-alpha.2. See the details in [release notes](https://github.com/opendatalab/labelU-Kit/releases/tag/v5.5.0-alpha.2) ([491cf33](491cf33))
## [1.0.9-alpha.5](v1.0.9-alpha.4...v1.0.9-alpha.5) (2024-10-30)

### Bug Fixes

* Upgrade frontend to v5.5.0-alpha.3. See the details in [release notes](https://github.com/opendatalab/labelU-Kit/releases/tag/v5.5.0-alpha.3) ([dc022fd](dc022fd))
add pascal voc, yolo, tfrecord exporting format files
# [1.1.0-alpha.1](v1.0.9-alpha.5...v1.1.0-alpha.1) (2024-11-05)

### Bug Fixes

* Upgrade frontend to v5.5.0-alpha.4. See the details in [release notes](https://github.com/opendatalab/labelU-Kit/releases/tag/v5.5.0-alpha.4) ([7622524](7622524))

### Features

* supports exporting "csv" format files ([d35a93a](d35a93a))
* supports exporting "labelme" format files ([8d4ea8e](8d4ea8e))
* supports exporting "pascal voc" format files ([4344f99](4344f99))
* supports exporting "tfrecord" format files ([f728fd6](f728fd6))
* supports exporting "xml" format files ([b165cce](b165cce))
* supports exporting "yolo" format files ([b3d07b4](b3d07b4))
fix: fix category name in pascal_voc and tfrecord format files
# [1.1.0-alpha.2](v1.1.0-alpha.1...v1.1.0-alpha.2) (2024-11-05)

### Bug Fixes

* fix category name in pascal_voc and tfrecord format files ([b089074](b089074))
gary-Shen and others added 28 commits September 30, 2025 17:48
# [1.3.0-alpha.18](v1.3.0-alpha.17...v1.3.0-alpha.18) (2025-10-01)

### Bug Fixes

* cli options ([2c42b7e](2c42b7e))
…nticated arbitrary file read)

_resolve only stripped leading slashes from the key; it neither handled
".." nor verified the resolved path stayed within MEDIA_ROOT. Because the
/api/v1/tasks/attachment/{path} and /partial/{path} download endpoints are
unauthenticated, an attacker could traverse with "../" to read any
process-readable file (e.g. labelu.sqlite, /etc/passwd).

_resolve now resolve()s both MEDIA_ROOT and the target and enforces
containment, raising 404 on escape. This covers read/write/delete/exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…itrary file write)

Attachment upload only sanitized the last path segment; the directory part
"/".join(path_filename[:-1]) was kept verbatim and could contain "..",
letting save_file -> _resolve -> shutil.move create files anywhere the
process can write (potential RCE).

Each directory segment is now sanitized the same way and "", "." and ".."
segments are dropped. Legitimate subdirectories still work while traversal
is neutralized; uploads always land under upload/<task_id>/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… (CWE-89)

crud_sample.list_by interpolated the sort column/direction into an ORDER BY
clause via a raw text() f-string, and the route pattern used an unanchored
re.search that could be bypassed with "valid_col:dir,<injection>", letting
an authenticated user blind-extract arbitrary data.

Primary fix: the crud layer now maps allowed column names to real ORM
columns, accepts only asc/desc, and skips anything else, removing the
text() interpolation entirely.
Defense in depth: the route pattern is anchored to ^(col:dir)(,col:dir)*$,
rejecting injection at validation and closing the substring bypass while
still allowing comma-separated multi-column sorts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CreateDataSourceCommand/UpdateDataSourceCommand only bounded the length of
endpoint, and _build_s3_client passed it straight to boto3 as endpoint_url,
so an authenticated user could point it at http://169.254.169.254 and other
internal/metadata addresses, triggering outbound requests via
list_objects/import_from_s3 (cloud IAM credential theft, internal scanning).

The endpoint is now validated: only http(s) is allowed, and the host is
resolved and rejected if it maps to a loopback/private/link-local/reserved/
multicast/unspecified address.

Note: connection-time DNS-rebinding re-check (TOCTOU) is left as a follow-up
defense-in-depth item.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sample create/import/list/get/patch/delete and export create/status/download
did not verify the caller could access the corresponding task, so any
authenticated user could enumerate auto-increment IDs to read, modify or
delete other users' annotation data, or download their export results.

Adds access.assert_task_access(task, current_user) (owner or collaborator)
and enforces it across the sample service and export endpoints; get/patch
additionally verify sample.task_id matches the URL task to prevent
referencing another user's sample through a task you own.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
task.update neither received current_user nor checked ownership
(inconsistent with get/delete/collaborator management in the same file), so
any authenticated user could PATCH and overwrite another user's task
config/name/description/media_type.

update now receives current_user and calls assert_task_access (owner or
collaborator).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Data source get/update/delete/list_objects and S3 import did not check
ownership, so any authenticated user could read others' S3 configuration,
tamper with/delete data sources, or use the victim's decrypted S3
credentials to list their private bucket or import objects.

Adds access.assert_owner(resource, current_user) (owner-only; data sources
have no collaborator concept) and enforces it on the four data source
endpoints and in sample.import_from_s3 before the credentials are used;
list_objects checks access before building the S3 client, preventing
credential abuse.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pre-annotation create/list/get/delete/delete_file already received
current_user but never used it for authorization, so any authenticated user
could read/inject/delete another task's pre-annotations (delete_file also
physically removed the underlying files).

All endpoints now call assert_task_access; get additionally verifies
pre_annotation.task_id matches the URL task, and delete checks access for
each pre-annotation's task.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The test suite persisted state across runs in two places: test.db was
pinned to the cwd (so sqlite_sequence accumulated and task_ids kept
growing) and MEDIA_ROOT pointed at the real appdirs data directory
(~/Library/Application Support/labelu/media). Fresh task_ids collided
with leftover upload/<task_id>/... files, intermittently failing uploads
with a 400 "file already exists" (e.g. test_upload_file_with_hash_symbol).

- Redirect both the sqlite test DB and MEDIA_ROOT into a per-run temp
  directory created at import time (the engine is built at module import,
  before any tmp_path/monkeypatch fixture could run); remove it at session
  end via the _hermetic_storage fixture.
- Force STORAGE_BACKEND=local and clear the get_storage_backend lru_cache
  so it resolves against the new MEDIA_ROOT.
- Seed the test user at session scope so it exists before the
  module-scoped login fixture (previously it survived only because test.db
  persisted across runs).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…bilities

Make the test suite hermetic by isolating the sqlite test DB and media
storage into a per-run temp directory, so tests no longer pollute the real
appdirs data directory or the cwd and can be run repeatedly.
…loyments

The SSRF guard rejected any endpoint resolving to a non-public address,
which broke the common on-prem deployment backed by an internal MinIO/
S3-compatible store on a LAN or the same host.

Adds ALLOW_PRIVATE_S3_ENDPOINT (default true): private (RFC1918/ULA) and
loopback endpoints are permitted by default so internal deployments work
out of the box, and can be locked down to public-only with a strict mode
(set false). The cloud metadata endpoint (link-local 169.254.0.0/16,
fe80::/10), multicast, reserved and unspecified addresses are ALWAYS
rejected regardless of the flag, so the highest-impact SSRF (IAM credential
theft) stays closed even in the permissive default.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@gary-Shen gary-Shen merged commit 91f578d into main Jul 13, 2026
1 check passed
@gary-Shen gary-Shen deleted the fix/security-vulnerabilities branch July 13, 2026 05:40
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.

2 participants