Skip to content

Security Issue: Using "Blocked Countries" allows any user from a non-blocked country to access the application #261

@kernel-sanders

Description

@kernel-sanders

TLDR

Any time a country block is used in a Dockflare access policy, the tunnel will be open to any non-blocked country, regardless of other restrictions (email, IP, etc).

Issue

When dockflare creates an Access Policy that includes Blocked Countries those countries are passed to the backend and eventually end up in the _parse_and_build_policy_from_form function. If countries are defined here, a new policy is appended to the policy array with a bypass decision.

The Cloudflare Zero Trust Documentation on Bypass rules has a large warning about using this decision.

The key part of this warning is When making Bypass policies, you will not be able to apply certain identity-based selectors (such as email).

Thus, if a user creates a policy that both restricts users to a list of emails AND enables "Blocked Countries" dockflare acts in a way the user does not expect. It allows any user from a non-blocked country to access the application, bypassing the "Allowed Emails or Domains" the user had set. This is not what a user expects, and I believe it is a security issue, as users will expose applications they thought were restricted to specified users to entire countries.

Test/Proof of claim

To test this, I created the following policy:

Image

The 1 country allowed is the US (I clicked Allow US Only). Note that this rule should restrict the application to users with *@badsectorlabs.com email addresses.

I configured httpbin with the following docker compose file:

services:
  httpbin:
    image: kennethreitz/httpbin
    container_name: httpbin
    restart: unless-stopped
    logging:
      driver: "json-file"
      options:
        max-size: "500k"
        max-file: "1"
    networks:
      - cloudflare-net
    labels:
      - "dockflare.enable=true"
      - "dockflare.hostname=httpbin.badsectorlabs.com"
      - "dockflare.service=http://httpbin:80"
      - "dockflare.access.group=bsl-users"
networks:
  cloudflare-net:
    name: cloudflare-net
    external: true

The tunnel was created successfully:

Image

And it shows in Cloudflare Zero Trust:

Image

The critical warning is Note: Access will evaluate policies with Bypass and Service Auth actions first. Then, policies are evaluated in top-to-bottom order. Thus, the bypass rule is not after the Allow defined users but actually the first to evaluate, and if it hits, it will stop processing any further rules. Thus if you an a US IP address, you can access https://httpbin.badsectorlabs.com despite the Allow defined users rule.

Despite curl not having any cloudflare auth, I can curl httpbin and get a response from a US IP address:

$ curl -v https://httpbin.badsectorlabs.com/get
* Host httpbin.badsectorlabs.com:443 was resolved.
---8K----SSL info cut-----8K-----
> GET /get HTTP/2
> Host: httpbin.badsectorlabs.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/2 200
< date: Tue, 30 Sep 2025 23:36:19 GMT
< content-type: application/json
< content-length: 539
< access-control-allow-credentials: true
< access-control-allow-origin: *
< server: cloudflare
< cf-cache-status: DYNAMIC
< nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800}
< report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=1n7Bz%2B0rkRxD4XN0651t4vw2rqzGK9yIXQLsEi3w7tg8xWS5V4TuEEhJn6EhVuPfRY7qgDLW4i9U6AY0c9aMbw6mGNYQNJhXUMfy1dOjGVEbATdjHyIY"}]}
< cf-ray: 98778ab33e08f13a-ORD
< alt-svc: h3=":443"; ma=86400
<
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, br",
    "Cdn-Loop": "cloudflare; loops=1",
    "Cf-Connecting-Ip": "[REDACTED US IP ADDRESS]",
    "Cf-Ipcountry": "US",
    "Cf-Ray": "98778ab33e08f13a-ORD",
    "Cf-Visitor": "{\"scheme\":\"https\"}",
    "Cf-Warp-Tag-Id": "6720234c-698c-4e1e-bf0e-99d7a24b95b4",
    "Connection": "keep-alive",
    "Host": "httpbin.badsectorlabs.com",
    "User-Agent": "curl/8.7.1"
  },
  "origin": "[REDACTED US IP ADDRESS]",
  "url": "https://httpbin.badsectorlabs.com/get"
}
* Connection #0 to host httpbin.badsectorlabs.com left intact

According to git blame this has been an issue since 2.1.4: https://github.com/ChrispyBacon-dev/DockFlare/blame/stable/dockflare/app/web/routes.py#L1682

Mitigation

Removing Blocked Countries from an access policy enforces the emails/domain/IP restrictions as expected.

Suggested Fix

Simply change the policy from bypass to block. Review other uses of bypass such as the defined IP policy, and carefully document the effect if bypass is intended (i.e. any traffic from that IP is allowed, regardless of other policy elements like allowed emails).

Thanks

Dockflare is a very useful application. Thank you for creating and maintaining it!

Metadata

Metadata

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions