Skip to content

fix: refuse HMAC mint when API auth is unset - #28

Draft
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-management-9673
Draft

cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-management-9673

Conversation

@cursor

@cursor cursor Bot commented Aug 30, 2026 •

Copy link
Copy Markdown
Contributor

Bug and impact

When AEGIS_APPROVE_KEY is set but AEGIS_API_KEY is not, POST /api/approve/mint is an unauthenticated HMAC signing oracle. Anyone who can reach the port can mint a valid G2/G3 token for any bundle hash, then POST /api/preflight/promote with that token. The promotion record stores method=hmac-sha256 as if a real approver signed it.

Pinned AEGIS_SEAL_KEY already refuses to start without API auth. HMAC mint was the same class of hole and was not gated.

Root cause

T1 #9/#10 added HMAC tokens and X-Aegis-Key, plus SystemExit for a pinned seal key without an API key. The mint route only required the HMAC key to be configured. _guard_api() is a no-op when AEGIS_API_KEY is unset, so the signing endpoint stayed open.

Fix

  • SystemExit at startup if AEGIS_APPROVE_KEY is set and AEGIS_API_KEY is not (same pattern as seals).
  • 503 on mint if HMAC is configured after import without API auth (env is read live).
  • API tests: mint is 503 without API auth; mint without X-Aegis-Key is 401; bound mint+promote still works when both keys are set.

Validation

python -m aegis.tests.api_test — 45 checks PASS
python -m aegis.tests.tokens_test — 17 checks PASS
python -m aegis.tests.promote_test 200 — PASS (HMAC random refused, bound token ok)

Open in Web View Automation 

Summary by Sourcery

Require API authentication for HMAC approval minting to prevent unauthenticated token issuance.

Bug Fixes:

  • Prevent HMAC approval tokens from being minted when API authentication is not configured, eliminating the unauthenticated signing oracle.

Enhancements:

  • Require API authentication both at startup and at request time whenever HMAC approval signing is enabled.
  • Update API behavior and operator documentation to reflect the authentication requirement for HMAC minting.

Documentation:

  • Document that AEGIS_APPROVE_KEY requires AEGIS_API_KEY and that the mint endpoint returns 503 without API authentication.

Tests:

  • Extend API coverage for startup refusal, request-time 503 responses, missing API headers, and successful authenticated HMAC minting and promotion.

@sourcery-ai

sourcery-ai Bot commented Aug 30, 2026

Copy link
Copy Markdown

Reviewer's Guide

Prevents an unauthenticated HMAC signing oracle by requiring API authentication whenever AEGIS_APPROVE_KEY is configured, enforcing the rule both at startup and for live environment changes, with API tests and documentation updated accordingly.

Sequence diagram for authenticated HMAC approval minting

sequenceDiagram
    participant Client
    participant Flask as serve.py
    participant Auth as _api_key()
    participant Tokens as mint_token()

    Client->>Flask: POST /api/approve/mint
    Flask->>Flask: hmac_configured()
    alt HMAC key unset
        Flask-->>Client: 503 HMAC minting refused
    else HMAC key configured
        Flask->>Auth: _api_key()
        alt API key unset
            Flask-->>Client: 503 unauthenticated HMAC mint refused
        else API key configured
            Flask->>Flask: _guard_api()
            alt X-Aegis-Key missing or invalid
                Flask-->>Client: 401 unauthorized
            else API key valid
                Flask->>Tokens: mint_token()
                Tokens-->>Flask: bound HMAC token
                Flask-->>Client: 200 token
            end
        end
    end
Loading

Flow diagram for HMAC authentication startup enforcement

flowchart TD
    A[Server import] --> B["_load_signer()"]
    B --> C["load_approve_key()"]
    C --> D["_require_api_key_for_hmac()"]
    D --> E{"hmac_configured() and no _api_key()?"}
    E -->|Yes| F[SystemExit]
    E -->|No| G[Start server]
Loading

File-Level Changes

Change Details Files
Gate HMAC approval minting on API authentication at startup and request time.
  • Abort startup when AEGIS_APPROVE_KEY is configured without AEGIS_API_KEY.
  • Return HTTP 503 if the HMAC key appears after import but API authentication is still unset.
  • Preserve the existing 503 response when HMAC minting is unconfigured.
serve.py
Expand API coverage for secure HMAC minting and authenticated promotion.
  • Verify unauthenticated HMAC mint requests return 503 and the startup guard raises SystemExit.
  • Verify keyed mint requests require X-Aegis-Key and succeed when both keys are configured.
  • Verify the resulting bound token can still be used for promotion with API authentication.
tests/api_test.py
Document the new configuration requirement and signing-oracle mitigation.
  • Describe the startup and endpoint behavior when approval HMAC is configured without API auth.
  • Update configuration, endpoint, phase, and server responsibility documentation.
CHANGELOG.md
docs/DEVELOPER.md
docs/PHASES.md
docs/index.html

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

AEGIS_APPROVE_KEY without AEGIS_API_KEY left POST /api/approve/mint
open as a signing oracle: anyone who could reach the port could mint
valid G2/G3 tokens for any bundle hash. Match the existing seal-key
gate — SystemExit at start and 503 on mint.

Co-authored-by: georgy75 <georgy75@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant