Skip to content

/calculate_demo is unauthenticated and exposed cross-origin #1463

@MaxGhenis

Description

@MaxGhenis

Summary

/<country_id>/calculate_demo is unauthenticated and exposes full calculation capability to any caller. Combined with the wide-open CORS configuration, this is an open invitation to drive-by abuse from any website.

Location

policyengine_household_api/api.py:87-90

@app.route("/<country_id>/calculate_demo", methods=["POST"])
@limiter.limit("1 per second")
def calculate_demo(country_id):
    return get_calculate(country_id)

What goes wrong

The route has only a rate limit (@limiter.limit("1 per second")) - no @require_auth_if_enabled() decorator. The handler delegates to get_calculate, which exposes the full household calculation capability, including policy reforms and AI explainer pipelines.

Because CORS(app) at line 43 leaves origins wide open (see separate issue on CORS), any third-party site can invoke this endpoint from a user's browser. Even with a 1 req/s rate limit per IP, this is trivially abused from a botnet or a popular site with many concurrent visitors.

Suggested fix

Apply @require_auth_if_enabled() to the route (consistent with /calculate and /ai-analysis), or remove the route entirely per the tracking issue for demo-endpoint removal.

Severity

High - unauthenticated compute endpoint exposed cross-origin.

Relates to

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity issue

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions