Skip to content

Harden clients against untrusted resolver responses; fix SecID encoding - #5

Merged
kurtseifried merged 1 commit into
mainfrom
fix/client-untrusted-response-hardening
Jun 22, 2026
Merged

Harden clients against untrusted resolver responses; fix SecID encoding#5
kurtseifried merged 1 commit into
mainfrom
fix/client-untrusted-response-hardening

Conversation

@kurtseifried

Copy link
Copy Markdown
Contributor

Summary

The SecID resolve API response is attacker-influenceable — a hostile, federated, or MITM'd resolver is in the trust model — but the three client SDKs surfaced returned URLs and printed server-supplied strings without validation, and encoded the request SecID with a fragile #%23 string replace. This hardens all three languages and fixes the template that generates new clients.

Audit reference: SecID-2026-06-14-claude-skill (findings F-08, F-09-01, F-10-01, F-10-02, F-10-04, F-10-05).

Changes (python/ · typescript/ · go/)

Finding Fix
F-08 best_url/bestUrl/BestURL validate the returned URL's scheme — http/https only; javascript:/data:/file:/relative rejected.
F-10-02 CLI output (url, message, corrected SecID) stripped of C0/C1 control chars (incl. ESC) → no ANSI-escape injection.
F-10-01 Request encoding switched from #%23 replace to the standard query encoder (quote(safe="") / encodeURIComponent / url.QueryEscape) — encodes #, &, spaces, etc.
F-09-01 Python success-path json.loads wrapped to fail cleanly on malformed/oversized bodies.

Regression tests added in all three languages (Python 24 pass, TS 24 pass, Go suite + 2 new pass).

Template (F-10-04)

skills/build-a-client/BUILD-A-CLIENT.md and PROMPT-TEMPLATE.md previously taught replace("#", "%23") and said nothing about validating the untrusted response — so every future generated client inherited the same gaps. They now teach full query-encoding and untrusted-response handling (scheme validation + output sanitization).

Packaging (F-10-05)

npm package renamed to @cloudsecurityalliance/secid. PyPI name left unchanged (flat namespace; rename TBD). Publishing under the new name + README install-doc updates are a release follow-up, not in this diff.

Notes for review

  • No behavior change for legitimate responses — valid https/http URLs pass through unchanged, and the colon in identifiers like RHSA-2024:1234 is preserved (validation re-parses; it does not re-encode).
  • Authority/scheme validation here is the response-side check; the request-side change is full query-encoding. These are deliberately different (encoding the request param vs. validating a returned URL).

🤖 Generated with Claude Code

The resolve API response is attacker-influenceable (a hostile, federated,
or MITM'd resolver is in scope), but the three client SDKs surfaced URLs
and printed server strings without validation, and encoded the request
SecID with a fragile "#"->"%23" replace.

Across python/, typescript/, go/:
- best_url / bestUrl / BestURL now validate the returned URL's scheme
  (http/https only); javascript:/data:/file:/relative are rejected (F-08).
- CLI output (url, message, corrected SecID) is stripped of C0/C1 control
  characters to prevent ANSI-escape injection (F-10-02).
- Request encoding switched from a hand-rolled "#"->"%23" replace to the
  standard query encoder (quote(safe="") / encodeURIComponent /
  url.QueryEscape), which encodes #, &, spaces, etc. (F-10-01).
- Python success-path json.loads wrapped to fail cleanly (F-09-01).

Regression tests added in all three languages.

Also closes the template that generates new clients (F-10-04):
BUILD-A-CLIENT.md / PROMPT-TEMPLATE.md now teach full query-encoding and
untrusted-response handling instead of the "#"->"%23" replace, so future
generated clients inherit the hardening rather than the gaps.

npm package renamed to @cloudsecurityalliance/secid (F-10-05, npm scope).
PyPI name unchanged (flat namespace; rename TBD).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kurtseifried
kurtseifried merged commit 192c60a into main Jun 22, 2026
12 checks passed
@kurtseifried
kurtseifried deleted the fix/client-untrusted-response-hardening branch June 22, 2026 16:07
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