---
title: "MGS1027: a secret grant is malformed"
description: Fires when magus.secret.endpoint is handed a declaration that cannot safely scope a credential - a missing field, a wildcard or non-ASCII host, an illegal header name. The declaration decides where a credential is forwarded, so magus refuses it rather than guessing.
tags: [MGS1027, magusfile, secrets, credentials, grant, endpoint, injection]
---

# MGS1027: a secret grant is malformed

A grant was declared but cannot be used:

```text
magus\secret.endpoint: secret grant "op://vault/openai/key": host "*.openai.com" contains
a wildcard; declare one grant per destination
```

## Why this is refused rather than repaired

A [grant](../../../concepts/secrets.md) is the single declaration that decides **where a
credential is forwarded**. The loopback endpoint sends to the host it names and nowhere
else, so a declaration magus cannot read exactly is one it cannot honor.

So a grant magus cannot interpret exactly is not a grant it can enforce approximately.
Guessing at one of these would either widen the scope silently or narrow it to nothing, and
both failures are invisible at the point they matter:

- A grant that is **too wide** sends a live credential somewhere you did not name.
- A grant that matches **nothing** sends every request unauthenticated, forever, and surfaces
  as an unexplained `401` from the far end with nothing pointing back at the declaration.

The second is the reason this fires eagerly, at declaration, rather than at the first
request.

## What triggers it

| Cause                               | Example                                   | Fix                                                                                                                                                                                      |
| ----------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Missing `ref`, `host`, or `header`  | `SecretGrant{ host = "api.example.com" }` | Supply all three.                                                                                                                                                                        |
| A wildcard host                     | `host = "*.example.com"`                  | Declare one grant per destination. A pattern reads as convenience until a subdomain someone else controls satisfies it.                                                                  |
| A URL or userinfo instead of a host | `host = "https://api.example.com/v1"`     | Use a bare `host[:port]`.                                                                                                                                                                |
| A non-ASCII host                    | `host = "exämple.com"`                    | Punycode it yourself. magus will not guess an encoding for the one field that decides where a credential may go - case folding a non-ASCII host lets a lookalike name satisfy the grant. |
| An illegal header name              | `header = "X Api Key"`                    | Use a valid HTTP field name. Left to the transport, this fails at request time, far from the line that declared it.                                                                      |
| Whitespace or a newline in a field  | `host = " api.example.com"`               | Remove it. Leading space used to validate and then match nothing.                                                                                                                        |
| A non-`str` field value             | `host = 42`                               | Buzz does not type-check object field literals, so this compiles; the grant is where it is caught.                                                                                       |

## Resolution

Fix the declaration the message names. The error carries the reference and the offending
value, so it points at one line:

```buzz
object SecretGrant {
    ref: str = "",
    host: str = "",
    header: str = "",
    prefix: str = "",
}

final OPENAI = SecretGrant{
    ref    = "op://vault/openai/key",
    host   = "api.openai.com",
    header = "Authorization",
    prefix = "Bearer ",
};
```

## See also

- [Secrets](../../../concepts/secrets.md) - grants, endpoints, and what they do and do not
  protect against
- [MGS1026](MGS1026.md) - a cacheable target reaches for a credential, grants included
- [MGS2011](../sandbox/MGS2011.md) - a secret too short to mask
