Skip to content

v1.10.1 — authz hardening (traversal-safe ids, chunked-safe body cap)#14

Merged
wyckit merged 1 commit into
masterfrom
fix/v1.10.1-authz-hardening
Jun 21, 2026
Merged

v1.10.1 — authz hardening (traversal-safe ids, chunked-safe body cap)#14
wyckit merged 1 commit into
masterfrom
fix/v1.10.1-authz-hardening

Conversation

@wyckit

@wyckit wyckit commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Security follow-up on the v1.10.0 authz surface, addressing an automated review finding plus a current service-hardening gap. 232 passing + 3 env-gated skipped.

Fixed

  • Path-traversal / tenant-isolation bypass (MEDIUM, automated review)AuthIds.IsValid accepted . and .. (all-dot ids passed the alphabet check). A ..-shaped tenant id would resolve outside the per-tenant runs root ({runsDir}/t/{tenant}). Now rejects ids that start with ./- or contain no alphanumeric, so ., .., dotfiles, and option-like names are refused.
  • Tenant-path containmentStoreFor re-validates the tenant id and confirms the resolved directory stays under the runs root before constructing the store (defense-in-depth, mirrors FileRunArtifactStore.RunDir).
  • Chunked-body cap bypass — the /api size guard no longer relies only on a declared Content-Length; it also sets Kestrel's MaxRequestBodySize so a chunked or missing-length body is rejected while binding.

Tests

AuthIds accept/reject theories (incl. ., .., .hidden, -rf, path separators), a traversal tenant via proxy headers, and an oversized /api body → 413.

Note on the relayed code review

Findings re: AllowedHosts=*, raw-key floor bypass, draft-recipient postcondition-only, and supply-chain SHA-pinning were already resolved in v1.9.2 — verified on master (appsettings.json:9 is loopback; AuditSigner SignString(byte[])/RawKeyProvider/FixedKeyProvider all call RequireStrongKey; PolicyGate:178 gates the draft pre-creation; ci.yml is SHA-pinned with minimized permissions + SHA256SUMS + attestation). That review appears to have run against a pre-v1.9.2 checkout. KMS/HSM and encrypted/WORM storage remain documented future seams.

🤖 Generated with Claude Code

… body cap

Security follow-up on the v1.10.0 authz surface (232 passing + 3 skipped):

- AuthIds.IsValid rejects ids starting with '.' or '-', or containing no
  alphanumeric — so ".", "..", dotfiles, and option-like names are refused even
  though their characters are in the allowed set. Closes a path-traversal /
  tenant-isolation-bypass risk (a ".."-shaped tenant could resolve outside the
  per-tenant runs root).
- StoreFor re-validates the tenant id and confirms the resolved directory stays
  under the runs root before constructing the store (defense-in-depth).
- The /api body cap no longer trusts only a declared Content-Length: it also sets
  the Kestrel max-request-body limit so a chunked/missing-length body is rejected
  while binding (an omitted/spoofed Content-Length no longer bypasses the 256 KB cap).

Tests: AuthIds accept/reject theories (incl. "." ".." ".hidden" "-rf" separators),
a traversal tenant via proxy headers, and an oversized /api body -> 413.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@wyckit wyckit merged commit 16d3e22 into master Jun 21, 2026
1 check passed
@wyckit wyckit deleted the fix/v1.10.1-authz-hardening branch June 21, 2026 06:45
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