Using the VIP API from a coding agent

How a coding agent uses the Monkeymaxxing VIP API: searching flaws in Debian and Ubuntu packages, and sending a support message to a person at Monkeymaxxing, with curl and one key.

The VIP API is at https://api.monkeymaxxing.com. A coding agent, such as Claude Code or Codex, calls two of its routes:

MMHotline and MMWatchdog call the API's other routes themselves, with the team's system key; an agent never needs those.

The key

The agent sends a key as a bearer token, read from the environment variable MONKEYMAXXING_VIP_API_KEY:

curl --silent \
  --header "Authorization: Bearer $MONKEYMAXXING_VIP_API_KEY" \
  ...

Keys are created on the members' website at vip.monkeymaxxing.com, under Keys. The website shows a new key once.

Never put a key into a repository, a log, or a support message.

Searching flaws in Debian and Ubuntu packages

GET /vulnerabilities/search finds the known flaws in the source packages of one release. This search asks for the flaws in openssh and php8.5 on Ubuntu 26.04 that were published on or after 2026-10-21:

curl --silent --get \
  --header "Authorization: Bearer $MONKEYMAXXING_VIP_API_KEY" \
  --data-urlencode "distribution_release=ubuntu-26.04" \
  --data-urlencode "packages=openssh,php8.5" \
  --data-urlencode "published_since=2026-10-21" \
  https://api.monkeymaxxing.com/vulnerabilities/search

--get puts each field into the query string, and --data-urlencode encodes it, so that + in a name such as gtk+3.0 is not read as a space.

The releases VIP covers

distribution_release Release Free security fixes end
debian-12 Debian 12 (bookworm) 2028-06-30
debian-13 Debian 13 (trixie) 2030-06-30
ubuntu-24.04 Ubuntu 24.04 LTS (noble) 2029-05-31
ubuntu-26.04 Ubuntu 26.04 LTS (resolute) 2031-05-29

VIP adds each new Debian release and Ubuntu LTS release when it comes out. The data comes from Debian's security tracker and Ubuntu's CVE tracker, as OSV.dev publishes them, and from CISA's list of known exploited vulnerabilities. VIP updates it every hour.

The fields

Each field is a query parameter:

Any other parameter is refused with 400 field_invalid. In particular, VIP never takes a version: the agent compares versions on the server itself, so VIP never learns whether a server is patched.

Source package names

Debian and Ubuntu record each flaw against the source package that the binary packages are built from. The binary packages openssh-server and openssh-client are both built from the source package openssh. The source packages of everything installed on a server:

dpkg-query --show --showformat='${source:Package}\n' | sort --unique

The answer

{
  "what_was_searched": "Searched Ubuntu 26.04 source packages in Ubuntu's CVE tracker, including fixes that need Ubuntu Pro, as OSV.dev publishes it, and CISA's list of known exploited vulnerabilities. Not searched: packages from other apt repositories, programs that were downloaded or built from source, container images, and the libraries of your apps.",
  "vulnerability_data_updated_at": "2026-10-26T07:05:12Z",
  "vulnerabilities": [
    {
      "cve_id": "CVE-2026-109618",
      "distribution_release": "ubuntu-26.04",
      "source_package": "php8.5",
      "fixed_version": "8.5.4-0ubuntu1.5",
      "fixed_version_with_ubuntu_pro": null,
      "published_at": "2026-10-21T14:00:00Z",
      "description": "out-of-memory handling can interrupt PHP while internal request data is only partially initialized.",
      "debian_urgency": null,
      "ubuntu_priority": "critical",
      "ubuntu_priority_reason": "This is a remote code execution vulnerability",
      "ubuntu_repository": "main",
      "cvss_vectors": [],
      "cisa_known_exploited_list_entry": null,
      "security_tracker_url": "https://ubuntu.com/security/CVE-2026-109618"
    }
  ],
  "names_not_found_as_source_packages": [],
  "next_page_cursor": null
}

Deciding whether a server is affected

Compare the version on the server with the entry's fixed versions, with dpkg --compare-versions. The installed version of a source package:

dpkg-query --show --showformat='${source:Version}\n' sudo

A server's package is not affected when fixed_version is not null and the installed version is at least fixed_version, or when fixed_version_with_ubuntu_pro is not null and the installed version is at least that. Otherwise it is affected, in one of three cases:

For example, dpkg --compare-versions 1.9.16p2-3 ge 1.9.16p2-3 succeeds, so a Debian 13 server with sudo 1.9.16p2-3 is not affected by a flaw fixed in 1.9.16p2-3.

How serious an affected package is depends on the server: whether it faces the internet, and whether the flawed feature is in use. That judgment is the agent's, because the agent can look at the server.

What VIP does not cover

VIP covers Debian and Ubuntu packages only. It does not cover packages from other apt repositories, programs that were downloaded or built from source, container images, or your app's libraries. Check those in the triage agent's daily software review and in your CI, with a scanner such as Trivy, Dependabot, or osv-scanner.

Sending a support message

When the agent meets a problem with MMX, MMWatchdog, MMHotline, the Fleet conventions, or VIP that the documentation does not solve, it sends a support message. A person at Monkeymaxxing answers by email during US business hours.

curl --silent \
  --header "Authorization: Bearer $MONKEYMAXXING_VIP_API_KEY" \
  --header "Content-Type: application/json" \
  --data @support-message.json \
  https://api.monkeymaxxing.com/support-messages

support-message.json:

{
  "client_support_message_id": "triage-2026-10-26-replica-lag",
  "subject": "db02 stopped replicating after an MMX run",
  "diagnosis": "After `mmx run playbooks/postgres.yml` at 07:40 UTC, db02 stopped replicating. pg_stat_replication on db01 shows no rows. The Postgres log on db02 says: password authentication failed for user \"replicator\".",
  "what_was_tried": "Checked that db02 reaches db01 on port 5432. Ran the playbook again with --dryrun: it plans to remove the line for db02 again."
}

Leave out keys, passwords, and personal data that the problem does not need.

The answer:

{
  "support_message": {
    "support_message_id": "8f14e45fceea167a5a36dedd4bea2543",
    "client_support_message_id": "triage-2026-10-26-replica-lag",
    "accepted_at": "2026-10-26T08:00:00Z",
    "reply_to_email_address": "[email protected]",
    "priority_support": true
  }
}

A team can send at most 10 support messages an hour; the 11th gets 429 rate_limited. A person can always write to [email protected] directly.

Errors

Every error answer has this body:

{
  "error_code": "field_invalid",
  "error_message": "subject must contain 1 to 150 characters.",
  "field": "subject"
}
HTTP status error_code What the agent does
400 field_invalid Fixes the field that field names, then sends the request again
400 distribution_release_not_covered Stops: VIP does not cover that release; the message names the ones it covers
401 credential_rejected Stops and tells its person that the key is wrong or was deleted
403 membership_inactive Stops and tells its person that the team's VIP membership has ended; for support, writes to [email protected]
403 not_allowed Stops: this kind of key may not use this route
429 rate_limited Waits for the seconds in Retry-After, then sends the request again
500 internal_error Sends the request again after a minute
503 try_again_shortly Waits for the seconds in Retry-After, then sends the request again

Every answer carries the header Monkeymaxxing-Vip-Request-Id. Quote it in a support message about a failed request.

What VIP keeps

VIP keeps no search text and no package names from a search. A support message stays in VIP's email outbox until 30 days after it was sent, and then lives only in the support mailbox. The privacy policy has the details, and what VIP includes describes the membership.