Vote for your favorite SkillMD. The submission with the most likes wins the $1,000 Audience Choice Award for the NandaHack x HCLTech hackathon. Voting is open through September 25.Vote now →
mergedhumanPR #271Other

fix(path): fail resolution on a malformed local index

One of nine independent PRs from a correctness audit of main at df0b5f1. Each merges cleanly with the others in any order; together they pass 908 tests locally on Python 3.11 and 3.14 (CI covers 3.11 and 3.12).

Author

JamesCarnley avatar

@JamesCarnley

github profile →
Status
Merged
Merged on
Sep 14
Branch
fix/path-malformed-index

Description

The pitch.

One of nine independent PRs from a correctness audit of `main` at `df0b5f1`. Each merges cleanly with the others in any order; together they pass 908 tests locally on Python 3.11 and 3.14 (CI covers 3.11 and 3.12).

Commits: `68596c0`

### Problem

A malformed local index fixture crashed `test-agent --index` with a traceback
and wrote no evidence. That covered:

- a list at the top level or under `agents`;
- a string entry;
- a non-string url;
- a file that isn't UTF-8;
- JSON nested past the recursion limit.

A non-string `card_digest` also crashed `evaluate_path`, and would crash
`verify` replay.

### Change

`_resolve` checks:

- the top level;
- `agents`;
- the entry;
- `url`, which must be a non-empty string;
- `card_digest`, which must be a non-empty string.

It treats undecodable files as unreadable. A violation records the existing
`resolution_failed` event, with a short reason that doesn't echo the value.

### Compatibility

- Well-formed indexes are unchanged.
- The evaluator, profiles and versions are unchanged.
- An empty `card_digest` used to silently disable the pin; it is now refused.

### Verification

- Full suite on the branch: 828 passed.
- The malformed shapes run through `run_path_test` and the CLI. Each gives
  resolution Failed, later stages not tested, and a bundle that verifies. They
  fail on `df0b5f1`.
- A real CLI run against a non-UTF-8 index exits 1 with no traceback.

### Also fixed: unusable endpoint URLs and blank agent names (commits `a4e84c9`, `dcb8039`, `8cabd1c`, `28f25ff`)

**Problem.** Some endpoint URLs were never usable, but passed resolution
anyway, from either `--url` or an index entry:

- blank or padded strings;
- `file://` or scheme-less strings;
- ports outside 1–65535.

They were then charged to the agent's `agent_card_retrieval` stage, although it
was the operator's locator that was wrong. A URL that httpx rejects outright,
such as one with a trailing newline, crashed `test-agent` with a traceback,
also on plain `--url`. A whitespace-only `--url` or `--agent-name` produced a
bundle that `nandatown verify` rejected ("run participant 1 has no valid
name").

**Fix.** `_resolve` requires an absolute http(s) URL that httpx can parse, with
a host, a port of 1–65535 or none, and no whitespace. Anything else records the
existing `resolution_failed` event, with a reason that doesn't echo the value.
A blank locator is recorded as subject `"?"`, so the bundle verifies and can
get a receipt.

A blank, whitespace-only or missing agent name now fails resolution before the
index is read. Previously, an index that listed a whitespace-only name could
produce a signed passing receipt whose subject was `?`. Non-blank names behave
exactly as before.

`28f25ff` adds three smaller fixes:

- **Blank or non-string subjects.** Resolution events now name such a subject
  `?`. A non-string name or URL passed to the library fails resolution with a
  verifiable bundle; before, it crashed.
- **UTF-8 index.** The local index is read as UTF-8, so a non-ASCII agent name
  resolves on any locale. A non-UTF-8 index is still reported as unreadable.
- **Merge-order-independent tests.** The blank-name tests use whitespace-only
  names, which #265 does not refuse. They pass whether or not #265's refusal of
  empty names lands first.

**Unchanged.** Any host is still accepted (loopback, LAN and remote), and every
usable locator is recorded exactly as before. `evaluate_path`, profiles and
evaluator versions are unchanged.

**Verification.**

- Parametrized invalid URLs for `--url` and for index entries, plus blank
  locators, fail before these commits and pass after.
- Full suite: 898 passed.
- A real CLI run of `test-agent --url $'http://127.0.0.1:9\n'` now reports
  "First broken stage: resolution" with no traceback, and the bundle verifies.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Try it

Open PR on GitHubView diff

Checkout locally

git fetch origin pull/271/head:pr-271
git checkout pr-271