Bitcoin Forum
May 13, 2026, 09:44:43 PM *
News: Latest Bitcoin Core release: 31.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: « 1 2 3 4 [5]  All
  Print  
Author Topic: Round#2 [OPEN] Omnisee 🚨 Bug Hunt Campaign – Help To Improve & Get Rewarded! 🐞  (Read 650 times)
irfan_pak10
Legendary
*
Offline

Activity: 3710
Merit: 1721


🧙‍♂️ #kycfree


View Profile WWW
May 08, 2026, 07:07:13 PM
 #81

/sitemap.xml lists only 10 latest blocks — site is invisible to search

Sitemap contains 11 <loc> entries: the homepage and the latest 10 blocks. No /address/{x}, no /tx/{x}, no /faq, no older blocks. For a Bitcoin explorer with hundreds of thousands of indexable pages, this means search engines see almost nothing.

Reproducer
Code:
$ curl -s https://omnisee.io/sitemap.xml | grep -c "<loc>"
11
 
$ curl -s https://omnisee.io/sitemap.xml | grep "<loc>" | head -3
<loc>https://omnisee.io/</loc>
<loc>https://omnisee.io/block/948314</loc>
<loc>https://omnisee.io/block/948313</loc>
   …only the latest 10 blocks…

Impact
•   Search engines miss /faq, popular addresses, recent transactions, older blocks.
•   SEO crawl budget is wasted re-discovering the same 10 latest blocks every visit.
•   Discoverability for the Tor mirror, the FAQ, the Asset-AI Detective explanations is zero.

Fix
Generate a paginated sitemap-index: sitemaps/blocks/{i}.xml, sitemaps/addresses/{i}.xml, sitemaps/transactions/{i}.xml. Include /faq and the Tor mirror. Cap each sub-sitemap at 50 000 URLs (the spec maximum).



ContentWriter
Member
**
Offline

Activity: 431
Merit: 23

Earn from your cryptocurrencies


View Profile
May 10, 2026, 01:23:24 PM
 #82

Report Title: Unsanitized external input stored and returned via API

Report Details: Starting with any address (I use the Silk Road one, but it could be your own or Satoshi’s Genesis address)

https://omnisee.io/api/address/1HQ3Go3ggs8pFnXuHVHRytPCq5fGG8Hbhx/scam-check

and querying the API, you get:

Code:
{
  "address": "1HQ3Go3ggs8pFnXuHVHRytPCq5fGG8Hbhx",
  "is_scam": true,
  "details": {
    "is_scam": true,
    "address": "1HQ3Go3ggs8pFnXuHVHRytPCq5fGG8Hbhx",
    "category": "sextortion",
    "risk_level": "high",
    "sources": [
      "chainabuse"
    ],
    "report_count": 5,
    "first_seen": "2026-03-27T20:45:09+00:00",
    "description": "ChainAbuse: {{7*7}} its for the test in bugcrowd",
    "ai_summary": "## Verdict\nSUSPICIOUS — address linked to sextortion scams, but no authoritative sanctions or law enforcement confirmation.\n\n## Key Factors\n- Flagged by multiple community reports (5) on ChainAbuse as a sextortion scam wallet.\n- On-chain activity shows high total received (208,210 BTC) with zero balance, consistent with a disposable collection address.\n- Mixing score indicates some coinjoin usage, possibly to obfuscate flow.\n\n## Activity Pattern\nAddress likely used to receive payments from sextortion email scams. Large volume suggests widespread targeting; funds have been moved out.\n\n## Recommendation\nMONITOR — while not confirmed by OFAC or major analytics firms, the pattern and multiple reports warrant caution. Interaction may expose users to legal or reputational risk."
  }
}

the line
Code:
"description": "ChainAbuse: {{7*7}} its for the test in bugcrowd"

This shows that the Chainabuse data has not been sanitized it would have returned 49. It is the log of a test carried out on Bugcrowd by someone else, and if it were rendered in HTML on the website. If this field is rendered in an HTML context without escaping, it could lead to Stored XSS.

Based on the bolded, it is compelling to state that there is no basis in "it would have returned 49". The reason for this is that   

Code:
{{7*7}}
is Angular/Handlebars syntax, not Python/Jinja2. This means that FastAPI doesn't evaluate it.
What would return 49: Jinja2/Flask template syntax (
Code:
{{7*7}}
in a template context), which is different from what Omnisee uses: FastAPI (Python), which returns
Code:
{{7*7}}
literally as a string

What I'm saying is that
Code:
{{7*7}}
would NOT evaluate to 49 in this situation, bearing in mind that it's just a string that someone else submitted to ChainAbuse.

Also bear in mind that stored XSS is unproven in this case.

This is a good bug find, just needed correcting the incorrect claims.

🔐 No KYC Crypto Trading
💸 Earn While You Trade
👉 Join Bridgoro Now
ContentWriter
Member
**
Offline

Activity: 431
Merit: 23

Earn from your cryptocurrencies


View Profile
May 10, 2026, 04:23:51 PM
 #83

MAJOR   TLSv1.0 and TLSv1.1 accepted on the edge

RFC 8996 (March 2021) deprecates TLSv1.0/1.1. Modern browsers refuse them, but legacy bots and downgrade-attack tooling still negotiate them. PCI-DSS, NIST SP 800-52r2 disallow them.

Reproducer
Code:
$ nmap --script ssl-enum-ciphers -p 443 omnisee.io | grep -E "TLSv1\.[01]"
| TLSv1.0:
| TLSv1.1:


Impact
•   Audit/compliance flag.
•   Legacy bots and TLS downgrade attacks remain possible.

Fix
Cloudflare → SSL/TLS → Edge Certificates → Minimum TLS Version → set to TLS 1.2 (or 1.3).




Report Title: Additional test cases and recommendations for /block/{invalid_format} handling

Report Details: I looked at this one and ran a few more tests. A couple of things are still missing.

First, there are other inputs worth checking. 0 is the genesis block and works fine. But floats like 1.5 or 3.14159 – those should be a straight 400. Right now they might be slipping through. Overflow numbers like 99999999999999999999 and 18446744073709551616 (that's 2^64) are also edge cases worth testing. A valid looking hash that doesn't actually exist should be 404, not something else. And mixed hex like 123abc456 – that's neither a height nor a real hash, so 400 is the right call.

The real problem here is that invalid input is hitting an unhandled exception and bubbling up as a 5xx. That's not great. The code is probably trying to parse whatever comes in without checking format first. So you get a crash on something that should have been rejected early.

The original report didn't mention a few practical things. First, monitoring will fire on every 503. Someone running a quick fuzz will fill your alert dashboard with noise. Those should be filtered out. Second, logging these as ERROR instead of WARN just adds clutter. It's a user typo, not a broken service. Third, rate limiting these paths would make fuzzing a lot harder.

A proper fix needs a regex for 64-char hex hashes, a sane max height (something like 10 million is safe), and a clear path: check height, then hash, then return 400. Upstream errors should never surface as 5xx. Wrap them and return 404.

Also worth noting, this same pattern is probably sitting in /api/block and /api/transaction as well. Would be good to audit all path parameters in one go.

The bottom line is if someone types garbage, you don't return a 5xx. That's the rule to enforce everywhere. Something like this should work pretty well:

Code:
import re

BLOCK_HASH_PATTERN = re.compile(r'^[0-9a-fA-F]{64}$')
MAX_HEIGHT = 10_000_000

@app.get("/block/{input}")
async def get_block(input: str):
    # Try height
    if input.isdigit():
        height = int(input)
        if height < 0 or height > MAX_HEIGHT:
            return {"error": "height out of range"}, 400
        try:
            result = fetch_by_height(height)
            return result if result else {"error": "not found"}, 404
        except:
            return {"error": "not found"}, 404
    
    # Try hash
    if BLOCK_HASH_PATTERN.match(input):
        try:
            result = fetch_by_hash(input)
            return result if result else {"error": "not found"}, 404
        except:
            return {"error": "not found"}, 404
    
    # Invalid format
    return {"error": "invalid block identifier"}, 400


🔐 No KYC Crypto Trading
💸 Earn While You Trade
👉 Join Bridgoro Now
ContentWriter
Member
**
Offline

Activity: 431
Merit: 23

Earn from your cryptocurrencies


View Profile
May 10, 2026, 05:00:39 PM
 #84

MAJOR   /api/transaction/{nonexistent_txid} returns 500 instead of 404

Valid 64-hex-format but nonexistent txids trigger an unhandled backend exception. API returns bare 'Internal Server Error' (text/plain, 21 bytes). The HTML route /tx/{nonexistent} correctly returns 200 with a 'Transaction Not Found' page — handlers diverge.

Reproducer
Code:
$ for tx in 1111...1111 ffff...ffff 0123...cdef 2cca...47ce; do
    curl https://omnisee.io/api/transaction/$tx
  done
[HTTP 500] tx=1111...      → "Internal Server Error"
[HTTP 500] tx=ffff...      → "Internal Server Error"
[HTTP 500] tx=0123...cdef  → "Internal Server Error"
[HTTP 500] tx=2cca...47ce  → "Internal Server Error"

Impact
•   Reveals an unhandled exception path on the API.
•   Wrong status code (500) confuses any client doing 'if 404 then ... else error' control flow.
•   Pollutes error metrics / SRE dashboards with fake outages.

Fix
Wrap the upstream provider call in try/except; return 404 + JSON {"error":"Transaction not found","code":"TX_NOT_FOUND"} when no provider returns the tx.




I tried to reproduce this but kept running into Cloudflare blocking me with 520 errors after just a couple requests. Couldn't get far enough to confirm if the 500 is still there. That said, there's a few things worth adding to this report.

First, the fix mentioned is solid but missing something. The API returns JSON for other errors like invalid format, but right now on 500 it's returning plain text. Whatever fix Omnisee implements should keep the response format consistent, ie JSON across the board, even for 404. Clients expecting JSON will break on plain text.

Second, worth checking how the HTML route
Code:
/tx/{nonexistent}
handles this. The reports says it returns 200 with a not-found page. That's okay for a browser but the API should stick to proper HTTP status codes. I believe that 200 for a missing resource is technically incorrect even if it works for humans.

The third issue is that the difference between API and HTML routes matters for anyone who would like to build tools on top of the Omnisee app. If an API client gets 500 today, they might retry or alert. But a 404 would tell them to stop immediately. The current behavior could cause unnecessary retries and false alarms.

One more thing, I suggest if someone can still test this, try edge cases like 63-character hex, 65-character hex, or valid length with non-hex characters like "zzz". Those should return 400. If they return 500 that's the same root cause.




🔐 No KYC Crypto Trading
💸 Earn While You Trade
👉 Join Bridgoro Now
ContentWriter
Member
**
Offline

Activity: 431
Merit: 23

Earn from your cryptocurrencies


View Profile
May 12, 2026, 05:15:32 AM
Merited by irfan_pak10 (1)
 #85

/api/health leaks internal architecture

The health endpoint returns the full provider fallback chain, Redis status, circuit-breaker states, and the application version. Useful to plan provider-targeted DoS so the fallback chain exhausts.

Reproducer
Code:
$ curl -s https://omnisee.io/api/health | python -m json.tool
{
  "status": "healthy",
  "version": "1.0.0",
  "providers": {"blockstream":"up", "mempool":"up", ...},
  "redis": "up",
  "circuits": {
    "primary":   {"name": "blockstream", ...},
    "fallback":  {"name": "mempool", ...},
    "tertiary":  {"name": "blockchain_info", ...},
    "quaternary":{"name": "blockcypher", ...},
    "local":     {"name": "local_esplora", ...}
  }
}

Impact
•   Reveals the provider fallback order so an attacker can target the chain.
•   Reveals presence of Redis and a private/local Esplora node.
•   Reveals application version (1.0.0).

Fix
Public /api/health should return only {"status":"ok"}. Move the rich payload to /api/health/internal gated behind an admin token or Cloudflare Access policy.




In addition to the issues already mentioned, the screenshot also shows that the endpoint exposes operational state information for every fallback provider, including whether each circuit breaker is currently “closed” and how many failures have occurred. This gives a potential attacker real-time insight into backend resilience and failover behavior, not just the provider names themselves.

The disclosure of `
Code:
local_esplora
` is of particular concern. I think it's interesting because it suggests the presence of a self-hosted internal blockchain node or infrastructure component. i don't really see it directly reachable. Nevertheless this kind of information would help an attacker map the environment and prioritize further probe against potentially exposed endpoints.

Another point I believe is worth mentioning is that the response can also help optimize resource-exhaustion attacks. You can see that the exact provider sequence is visible in the screenshot (blockstream to mempool to blockchain_info to blockcypher to local_esplora). This makes it even easier for an attacker to practically degrade upstream providers one by one until traffic is forced onto fallback systems. the consequence would be increasing operational costs and reducing reliability for everyday users of the platform.

The version number (1.0.0) should never be exposed since it helps potential attackers. They can use it to search for known bugs in this version of FastAPI or any other library Omnisee app depends on, and try to exploit them.

It's obvious that this endpoint reduces attacker reconnaissance effort since internal architecture, dependency relationships, failover logic, and operational telemetry are clearly exposed through this unauthenticated public route.

🔐 No KYC Crypto Trading
💸 Earn While You Trade
👉 Join Bridgoro Now
ContentWriter
Member
**
Offline

Activity: 431
Merit: 23

Earn from your cryptocurrencies


View Profile
May 12, 2026, 05:31:09 AM
 #86

Backend nginx 1.29.8 version disclosed via /metrics 404

Cloudflare normally rewrites the Server header, but the upstream nginx default 404 body still renders the version in the page footer.

Reproducer
Code:
$ curl -s https://omnisee.io/metrics
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.29.8</center>
</body>
</html>

Impact
•   Identifies the exact upstream nginx version for CVE targeting.

Fix
On the upstream nginx set server_tokens off; and provide a custom 404 page that does not leak the version.




I'll add that this issue appears to bypass part of Cloudflare’s normal origin masking behavior. Even though Cloudflare hides the upstream Server header, the default nginx error page in plain sight still exposes the exact backend version (
Code:
nginx/1.29.8
) clearly in the HTML response body, as shown in the screenshot. If I'm an attacker, I already have a more accurate fingerprint of the infrastructure and so targeting CVE research is a bit easier.

This could also be a pointer to a wider hardening issue rather than being limited only to
Code:
/metrics
. For me, an  attack strategy would be chaining together small disclosures like this to build a complete map of the backend stack before attempting deeper attacks.

Another important point is that the issue leaks information about the origin server even behind Cloudflare protection. While researching an infrastructure, we mostly use these seemingly minor inconsistencies to differentiate CDN behavior from origin behavior and identify misconfigurations between reverse proxy and upstream systems.

A stronger fix in my opinion would be to disable nginx version tokens entirely using
Code:
server_tokens off
, replace the default nginx error templates with generic custom pages before verifying that all error responses returned by the origin server are sanitized consistently across the application. It may also be necessary to test additional endpoints and status codes to ensure no other backend details are unintentionally exposed.

🔐 No KYC Crypto Trading
💸 Earn While You Trade
👉 Join Bridgoro Now
ContentWriter
Member
**
Offline

Activity: 431
Merit: 23

Earn from your cryptocurrencies


View Profile
May 12, 2026, 06:20:53 PM
Merited by irfan_pak10 (4)
 #87

HEAD / returns 405 Method Not Allowed (RFC 7231 violation)

RFC 7231 §4.3.2 requires that any resource that supports GET MUST also support HEAD. Currently CDN edge probes, link checkers, monitoring tools, and HEAD-based prefetch fail.

Reproducer
Code:
$ curl -I https://omnisee.io/
HTTP/1.1 405 Method Not Allowed
allow: GET
 
$ curl -s -o /dev/null -w "%{http_code}\n" https://omnisee.io/
200

Impact
•   Breaks monitoring tools, link checkers and CDN edge probes that issue HEAD.

Fix
On Starlette/FastAPI, add a HEAD route that mirrors GET (use methods=["GET","HEAD"]), or have nginx synthesise HEAD by stripping the body from GET.





I actually think this issue is bigger than just an RFC compliance problem. A lot of components rely on
Code:
HEAD
requests before making full
Code:
GET
requests. We are talking about uptime monitors, SEO crawlers, CDN validation systems, performance scanners, SM bots and even some wallet security integrations. Reachability tests for these start at
Code:
HEAD
. It's obvious that some automated systems may assume although incorrectly that the site is down, misconfigured, or blocking traffic. This is simply Because the server currently returns
Code:
405
Method Not Allowed while GET works normally.

The report screenshot also shows the server explicitly advertising allow
Code:
GET
, which confirms the framework routing layer is rejecting
Code:
HEAD
before application logic is reached. You may be aware that some frameworks like FastAPI,
Code:
HEAD
is not always automatically enabled. So what we have here is more of a routing configuration issue than a simple missing method.

Another detail the report doesn't have is caching/CDN behavior. Some CDN edge nodes and cache validators use
Code:
HEAD
requests to validate freshness or content existence without downloading the full response body. Returning
Code:
405
can interfere with cache warmups, health checks and optimization workflows. This can indirectly affect reliability even if users do not immediately notice the problem.

We can also view the report from the information disclosure angle. Returning a framework-generated
Code:
405
instead of handling
Code:
HEAD
may expose differences in backend behavior compared to proxied or CDN-cached responses. If I'm attacking this infrastructure, I'd be testing unsupported HTTP methods and comparing headers, allowed verbs, and response structures.

A practical improvement for this section would be testing all major routes, not just /. Patching only the homepage while API endpoints still reject HEAD wouldn't fully cut it. A good approach would be:

Enable automatic
Code:
HEAD
handling globally for all
Code:
GET
routes.
Verify responses preserve the same headers as
Code:
GET
while stripping only the body.
Ensure CDN/proxy layers do not override or block
Code:
HEAD
.
Regression tests should be added so that future routes inherit proper behavior automatically.

🔐 No KYC Crypto Trading
💸 Earn While You Trade
👉 Join Bridgoro Now
HasanHandy
Newbie
*
Offline

Activity: 22
Merit: 0


View Profile
Today at 02:44:33 PM
 #88

Bech32 address (if it is your first report for round#2): bc1qxl52cgc446jthut9g0fwvx5u3g0k4n29w448ag
Report Title: URLs where HSTS is not enabled: https://omnisee.io/cdn-cgi/images/
Report Details:
Vulnerability Description:
HTTP Strict Transport Security (HSTS) tells a browser that a web site is only accessable using HTTPS. It was detected that your web application doesn't implement HTTP Strict Transport Security (HSTS) as the Strict Transport Security header is missing from the response.

Discovered by HSTS not implemented

The impact of this vulnerability:
HSTS can be used to prevent and/or mitigate some types of man-in-the-middle (MitM) attacks

How to fix this vulnerability:
It's recommended to implement HTTP Strict Transport Security (HSTS) into your web application. Consult web references for more information
ContentWriter
Member
**
Offline

Activity: 431
Merit: 23

Earn from your cryptocurrencies


View Profile
Today at 03:43:38 PM
Merited by irfan_pak10 (1)
 #89

/docs/ 307 redirect downgrades scheme to http://

HTTPS request gets a 307 with Location header pointing to plain http://. HSTS protects browsers, but the server emits an unsafe scheme — root cause: upstream FastAPI does not trust X-Forwarded-Proto.

Reproducer
Code:
$ curl -sI https://omnisee.io/docs/
HTTP/1.1 307 Temporary Redirect
location: http://omnisee.io/docs

Impact
•   Non-HSTS clients (older bots) can be downgraded to plaintext.

Fix
•   Configure Starlette with ProxyHeadersMiddleware so X-Forwarded-Proto is honoured:
Code:
from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
app.add_middleware(ProxyHeadersMiddleware, trusted_hosts="*")

•   Or run uvicorn with --proxy-headers --forwarded-allow-ips '*'.






Nice find. This looks like the app is not trusting X-Forwarded-Proto, so it thinks the original request was HTTP and generates a redirect to http:/  instead of  https://.

Even though HSTS will protect most modern browsers, this can still affect non-HSTS clients  such as bots and crawlers. It can also cause unnecessary HTTP downgrade during redirects. Most likely, the backend (FastAPI/Uvicorn) isn’t correctly reading the proxy headers from the CDN or load balancer, so it thinks the request is HTTP instead of HTTPS.

The simplest fix is to enable proxy header support so the app correctly detects HTTPS behind the proxy.

🔐 No KYC Crypto Trading
💸 Earn While You Trade
👉 Join Bridgoro Now
Pages: « 1 2 3 4 [5]  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!