Skip to content

Security hardening: mediums/lows from 2026-07-01 review #31

Description

@davidcrowe

From the 2026-07-01 OSS security review. HIGH (ReDoS in transformabl-core email regex) fixed in #30. Remaining:

proxyabl-core/src/auth.ts:57verifyAccessToken doesn't pin algorithms (identifiabl-core correctly pins RS256) and audience is optional → alg-confusion surface + cross-service token replay when audience unset. Pin algorithms:['RS256']; require/warn on audience. Same optional-audience in tool-gateway.ts:394/759.
proxyabl-core/src/security.ts:150 → execute.ts:57 — SSRF DNS-rebinding TOCTOU: assertUrlSafe validates resolved IPs, then fetch re-resolves (IP not pinned to socket). Pin validated IP via custom undici dispatcher. Also add 100.64/10, 192.0.0/24, 198.18/15 to isPrivateIpv4.
validatabl-core/src/scopes.ts:30hasScope interpolates scope into new RegExp unescaped → regex injection/ReDoS + . matches any char (user.read ~ userXread). Use exact split(' ').includes(scope).
identifiabl-core & proxyabl-core — tokens with no exp accepted forever. Require exp (jose requiredClaims:['exp']).
limitabl-core budgetTracker — pre-flight check doesn't reserve estimated cost → concurrent requests all pass, spend exceeds maxSpend; also all limiters in-memory (per-instance) so effective limit = N×configured on multi-instance. Reserve-on-preflight + document/provide shared-store adapter.
proxyabl/src/middleware.ts:10req.path.split('/').pop() → '' on trailing slash → scope check skipped (fail-open). Derive tool robustly, deny when undetermined.
proxyabl/src/tool-gateway.ts — shipped default secrets ('dev-only-change-me') + non-constant-time bearer compare + X-Forwarded-For rate-limit key. Delete dead tool-gateway.ts from published build or gut defaults; timingSafeEqual; key limiter on req.ip.
transformabl-core/normalize.ts — incomplete invisible-char set (misses U+00AD soft-hyphen, bidi marks) + no NFKC → redaction bypass. Expand set + NFKC.
validatabl-core/decision.ts:65 — decision({}) fail-open (documented); policy.ts:140 resolveField walks arbitrary dotted paths incl. prototype.
Supply-chain: align jose version skew (identifiabl ^5 vs identifiabl-core ^6).

Done well (trust page): identifiabl-core JWT verification (RS256-pinned, aud mandatory), proxyabl-core SSRF guard (resolves all A/AAAA, IPv4-mapped-v6, redirect:manual), sanitizeCost + single-line JSON audit logging, clean supply chain (no install scripts, files:['dist']).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions