This release includes 4 security fixes for security teams reviewing exposed deployments.
Topics
+6 more
ReleasePort's take
Moderate signalThe release adds several security hardening changes: it strips unsafe URI schemes from markdown links, sanitizes text to remove script and style tags, enforces a file‑extension allow‑list in FileManager.SaveFile, validates disclosure URLs by origin, and upgrades the Bcl.Memory dependency to remediate CVE-2024-43485.
Why it matters: These mitigations directly reduce injection, upload, and SSRF risks; upgrading Bcl.Memory addresses CVE-2024-43485 (CVSS 8.1) which must be patched in all deployments using that library.
Summary
AI summaryBroad release touches Operator UX, Holdings / 13F, MCP tools, and Web portal.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| Security | Critical |
Strip javascript and other non-http(s) URI schemes from markdown links. Strip javascript and other non-http(s) URI schemes from markdown links. Source: llm_adapter@2026-05-25 Confidence: high |
— |
| Security | Critical |
Clean text removes script, style tags and comments to prevent injection. Clean text removes script, style tags and comments to prevent injection. Source: llm_adapter@2026-05-25 Confidence: high |
— |
| Security | High |
Enforce file‑extension allow‑list in FileManager.SaveFile to block unsafe uploads. Enforce file‑extension allow‑list in FileManager.SaveFile to block unsafe uploads. Source: llm_adapter@2026-05-25 Confidence: high |
— |
| Security | High |
Validate disclosure URLs by origin to close SSRF bypass. Validate disclosure URLs by origin to close SSRF bypass. Source: llm_adapter@2026-05-25 Confidence: high |
— |
| Security | High |
Upgrade Bcl.Memory dependency to remediate CVE-2024-43485. Upgrade Bcl.Memory dependency to remediate CVE-2024-43485. Source: llm_adapter@2026-05-25 Confidence: high |
— |
| Feature | Low |
Add near‑real‑time 13F‑HR ingestion alongside quarterly bulk backfill. Add near‑real‑time 13F‑HR ingestion alongside quarterly bulk backfill. Source: llm_adapter@2026-05-25 Confidence: high |
— |
| Feature | Low |
/Holdings/Activity provides market-wide quarterly leaderboards (Top Buys, Top Sells, New Positions, Sold-out Positions) with CSV export. /Holdings/Activity provides market-wide quarterly leaderboards (Top Buys, Top Sells, New Positions, Sold-out Positions) with CSV export. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
/Holdings/MostHeld ranks stocks by number of institutional filers and shows quarter-over-quarter deltas. /Holdings/MostHeld ranks stocks by number of institutional filers and shows quarter-over-quarter deltas. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
/Holdings/Screener offers cross-sectional holdings filtering with CSV export and configurable comparison quarter. /Holdings/Screener offers cross-sectional holdings filtering with CSV export and configurable comparison quarter. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
/Institutions provides a browseable, searchable index of all 13F filers with position count and total dollar value. /Institutions provides a browseable, searchable index of all 13F filers with position count and total dollar value. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
/Institutions/Compare shows side‑by‑side overlap view between two filers with Jaccard and dollar‑weighted metrics. /Institutions/Compare shows side‑by‑side overlap view between two filers with Jaccard and dollar‑weighted metrics. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
/Institutions/Combined presents a consensus portfolio across 2‑25 filers ranked by holder count and combined value. /Institutions/Combined presents a consensus portfolio across 2‑25 filers ranked by holder count and combined value. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
/Institutions/{cik}/Backtest adds holdings backtesting with cumulative‑return chart, rebalance trail, CAGR and max drawdown. /Institutions/{cik}/Backtest adds holdings backtesting with cumulative‑return chart, rebalance trail, CAGR and max drawdown. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
Redesign institution profile with portfolio summary header, industry/sector allocation card, and Latest Quarter Activity grouping. Redesign institution profile with portfolio summary header, industry/sector allocation card, and Latest Quarter Activity grouping. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
Stock Holdings tab groups quarterly position changes (Initiated, Increased, Reduced, Exited, Unchanged) and shows Top Buyers / Top Sellers cards. Stock Holdings tab groups quarterly position changes (Initiated, Increased, Reduced, Exited, Unchanged) and shows Top Buyers / Top Sellers cards. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
Add per‑stock holders CSV download, institution portfolio CSV download, and market‑wide activity CSV downloads. Add per‑stock holders CSV download, institution portfolio CSV download, and market‑wide activity CSV downloads. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
MCP tools (GetTopBuyersSellers, GetMarketWide13FActivity, GetMostHeldStocks, etc.) expose holdings analytics via API. MCP tools (GetTopBuyersSellers, GetMarketWide13FActivity, GetMostHeldStocks, etc.) expose holdings analytics via API. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
SEC Company Facts API ingests every XBRL fact into FinancialFact with per‑period identity. SEC Company Facts API ingests every XBRL fact into FinancialFact with per‑period identity. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
Standalone and Inline XBRL parsers extract dimensional facts using new FinancialFactDimension schema. Standalone and Inline XBRL parsers extract dimensional facts using new FinancialFactDimension schema. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
"Financial Statements" tab renders Income Statement, Balance Sheet, Cash Flow with period selectors. "Financial Statements" tab renders Income Statement, Balance Sheet, Cash Flow with period selectors. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
MCP `GetFinancialStatement`, `GetFinancialFact`, and `CompareFinancialFact` expose financial data via API. MCP `GetFinancialStatement`, `GetFinancialFact`, and `CompareFinancialFact` expose financial data via API. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
Detect fiscal year‑end from SEC submissions and map any date to a company's fiscal quarter/year. Detect fiscal year‑end from SEC submissions and map any date to a company's fiscal quarter/year. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
Add sector taxonomy with Industry.SectorId foreign key on stock metadata. Add sector taxonomy with Industry.SectorId foreign key on stock metadata. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
Ingest Yahoo `assetProfile` to populate industry, sector, market cap, and description on CommonStock. Ingest Yahoo `assetProfile` to populate industry, sector, market cap, and description on CommonStock. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
Title‑case ALL-CAPS company names from SEC EDGAR feed for consistent display. Title‑case ALL-CAPS company names from SEC EDGAR feed for consistent display. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
Add Stochastic Oscillator (%K/%D), Average True Range (ATR), and On‑Balance Volume (OBV) technical indicators via MCP. Add Stochastic Oscillator (%K/%D), Average True Range (ATR), and On‑Balance Volume (OBV) technical indicators via MCP. Source: granite4.1:30b@2026-05-25-audit Confidence: high |
— |
| Feature | Low |
Redesign global search with filter sidebar, date range, sort options, instant results, and support for institutions, insiders, congress members. Redesign global search with filter sidebar, date range, sort options, instant results, and support for institutions, insiders, congress members. Source: granite4.1:30b@2026-05-25-audit Confidence: low |
— |
| Feature | Low |
Navbar reshuffle groups Economic Data, Futures, Market under a “More” dropdown; mobile menu stays flat. Navbar reshuffle groups Economic Data, Futures, Market under a “More” dropdown; mobile menu stays flat. Source: granite4.1:30b@2026-05-25-audit Confidence: low |
— |
| Feature | Low |
Stocks browser adds sort selector and minimum market‑cap filter persisted across pagination. Stocks browser adds sort selector and minimum market‑cap filter persisted across pagination. Source: granite4.1:30b@2026-05-25-audit Confidence: low |
— |
| Feature | Low |
Live activity feed at /Status/Activity renders scraper SSE stream with pause/resume toggle and screen‑reader region. Live activity feed at /Status/Activity renders scraper SSE stream with pause/resume toggle and screen‑reader region. Source: granite4.1:30b@2026-05-25-audit Confidence: low |
— |
| Feature | Low |
Many accessibility improvements: table headers, ARIA labels, heading hierarchy fixes, chart landmarks, search landmark, etc. Many accessibility improvements: table headers, ARIA labels, heading hierarchy fixes, chart landmarks, search landmark, etc. Source: granite4.1:30b@2026-05-25-audit Confidence: low |
— |
| Feature | Low |
Version‑check banner on web portal shows newer GitHub release with copy‑to‑clipboard buttons functional. Version‑check banner on web portal shows newer GitHub release with copy‑to‑clipboard buttons functional. Source: granite4.1:30b@2026-05-25-audit Confidence: low |
— |
| Bugfix | Medium |
Holdings scrapers skip stale CommonStock IDs instead of throwing FK errors. Holdings scrapers skip stale CommonStock IDs instead of throwing FK errors. Source: llm_adapter@2026-05-25 Confidence: high |
— |
| Bugfix | Medium |
Holdings worker wakes on StockCusipChanged event, reducing re‑processing delay. Holdings worker wakes on StockCusipChanged event, reducing re‑processing delay. Source: llm_adapter@2026-05-25 Confidence: high |
— |
| Bugfix | Medium |
Suppress stack traces for 404 FTD archive files to clean logs. Suppress stack traces for 404 FTD archive files to clean logs. Source: llm_adapter@2026-05-25 Confidence: high |
— |
| Bugfix | Medium |
Fix fiscal‑year/period calculation for SEC XBRL facts to avoid collisions. Fix fiscal‑year/period calculation for SEC XBRL facts to avoid collisions. Source: llm_adapter@2026-05-25 Confidence: high |
— |
Full changelog
Added
Holdings / 13F
- Near-real-time 13F-HR ingestion — picks up new 13F filings shortly after
publication alongside the existing quarterly bulk backfill, so the holdings
side of the portal catches up to recent filings within minutes instead of
waiting for the next bulk window. /Holdings/Activity— market-wide quarterly leaderboards (Top Buys / Top
Sells / New Positions / Sold-out Positions) for any 13F quarter, with a CSV
export covering all four boards./Holdings/MostHeld— 13F breadth ranking. Stocks ranked by number of
institutional filers reporting them, with quarter-over-quarter delta filers,
total reported value, delta value, and percentage of the 13F universe. 100
rows per page, sortable by filers / Δ filers / value./Holdings/Screener— cross-sectional holdings screener with criteria
(filer count, delta filer count, total value, delta value, percent of
float, new / sold-out positions, industry), CSV export, and configurable
comparison quarter./Institutions— browseable, searchable index of every 13F filer with
per-filer position count and total dollar value at the latest 13F quarter.
Sort by name, position count desc, or value desc./Institutions/Compare— side-by-side overlap view between two filers,
with Jaccard and dollar-weighted overlap metrics and a per-stock comparison
table./Institutions/Combined— consensus-portfolio view across 2-25 filers,
ranking stocks by how many of the selected funds hold them and combined
dollar value./Institutions/{cik}/Backtest— institution holdings backtest with a
Chart.js cumulative-return chart against a benchmark (default S&P 500),
rebalance trail, and CAGR / max-drawdown stats.- Institution profile redesign — portfolio summary header (reported AUM,
position count, top-10 / top-25 concentration, QoQ turnover, quarters
reported), industry / sector allocation card, and a Latest Quarter
Activity section grouping holdings into Initiated / Increased / Reduced /
Exited buckets. - Stock Holdings tab — quarterly position-change grouping (Initiated /
Increased / Reduced / Exited / Unchanged) plus Top Buyers / Top Sellers
cards, with negative deltas rendered consistently as-$X(not$-X). - Per-stock holders CSV download, institution portfolio CSV download, and
market-wide activity CSV downloads.
MCP tools (Holdings)
GetTopBuyersSellers— institutions that moved the most on a stock
quarter over quarter.GetMarketWide13FActivity— universe-wide buys / sells / new / sold-out
leaderboards for a quarter.GetMostHeldStocks— cross-sectional 13F breadth ranking.GetInstitutionSummary— AUM, positions, top-N concentration, QoQ
turnover for one filer.GetInstitutionSectorAllocation— portfolio grouped by industry /
sector with percent of portfolio.GetInstitutionQuarterlyActivity— Initiated / Increased / Reduced /
Exited buckets per filer.GetFundOverlap— Jaccard and dollar-weighted overlap between two
funds.GetConsensusHoldings— combined picks across 2-25 funds with a
minFundsthreshold.
SEC Financial Facts (XBRL)
- SEC Company Facts API ingestion — every reported XBRL fact for every
CIK, persisted intoFinancialFactwith per-period identity. - Standalone and Inline XBRL parsers for dimensional fact extraction, plus
a newFinancialFactDimensionschema for downstream dimensional queries. - "Financial Statements" tab on the stock detail page rendering Income
Statement / Balance Sheet / Cash Flow with period selectors. - MCP
GetFinancialStatement— full statement for one company / period. - MCP
GetFinancialFact— concept time series for one company. - MCP
CompareFinancialFact— peer comparison across multiple tickers. - Fiscal year-end detection for companies. The SEC document scraper now
reads EDGAR's submissionsfiscalYearEndfield and persists
FiscalYearEndMonth/FiscalYearEndDayonCommonStock(sourced
entirely from public SEC data, no extra request on the common path —
the metadata fetch primes the submissions cache reused by the filings
fetch). A newFiscalCalendarhelper maps any date to a company's
fiscal quarter/year, so off-calendar filers (e.g. Apple ≈ September,
Microsoft = June) are no longer misrepresented by calendar-quarter
math.
Stock metadata
- Sector taxonomy +
Industry.SectorIdforeign key. - Yahoo
assetProfileingestion — populates Industry, Sector, market
capitalisation, and the company description onCommonStock. - ALL-CAPS company names from the SEC EDGAR feed are now title-cased on
ingest (so "APPLE INC" displays as "Apple Inc").
Technical indicators (Yahoo prices)
- Stochastic Oscillator (
%K/%D). - Average True Range (ATR).
- On-Balance Volume (OBV).
- All three exposed via MCP alongside the existing SMA / RSI / MACD.
Global search
- Redesigned global search with a filter sidebar, category scope filter,
date-range filter, sort (relevance / name), result-count summary, and a
visible clear button. - Instant as-you-type results with keyboard navigation;
/shortcut
focuses the navbar search; a recoverable empty state when a category
filter hides every hit. - Search now resolves institution, insider, and congress-member profiles
in addition to stocks and filings.
Web portal
- Navbar reshuffle —
Home · Stocks · Institutions · More ▾ · MCP · Status. TheMoredropdown groups Economic Data, Futures, and Market
so the row stays readable on medium viewports; the mobile menu keeps a
flat list. - Stocks browser — sort selector and minimum-market-cap filter, with
filters carried across pagination links. - Live activity feed at
/Status/Activityrendering a scraper SSE
stream (paused / resumed via a toggle, screen-reader live region). - Skip-to-main-content link in the shared layout.
- Many accessibility improvements: table headers + accessible names on
every data table, ARIA labels on icon-only buttons, corrected heading
hierarchy across stock / institution / status / login / market /
EconomicData / Cftc pages,role=img+aria-labelon chart canvases,
search-formrole=searchlandmarks, labelled mobile-nav hamburger,
rel=noopener + aria-label on external GitHub links. - Status page Live activity entry-point is now a solid green pill with a
pulsing indicator (was a near-invisible ghost button). /Home/Connectcopy-to-clipboard buttons now actually copy.- Web portal checks GitHub Releases and shows a banner when a newer
version is available, displaying the new and current versions with
links to the "Updating" guide and an in-app rendered changelog. The
check is cached, runs off the request path, fails silently, and can be
disabled with theCHECK_FOR_UPDATESenvironment variable (default
true).
Messaging infrastructure
- MassTransit on Postgres SQL transport with the EF outbox pattern,
composed in every host (web / MCP / worker) and test fixture. StockCusipChangedevent published fromCommonStockManager.SetCusip
and consumed by the Holdings scraper to invalidateProcessedDataSet
rows and immediately re-process pending 13F data sets, instead of
waiting up to 24 hours for the next worker cycle.ScraperActivitycontract published by every scraper, consumed by the
web's in-process broadcaster and surfaced on the live activity feed.
Fixed
Holdings ingestion
- The Yahoo, FTD, and FinancialFacts scrapers now guard against the
parentCommonStockdisappearing between the per-cycle ticker-map
read and the per-batch write. Without the guard, a cold-start tick
alongside CompanySync tripsFK_*_CommonStock_CommonStockIdrepeatedly
and the activity feed fills with errors; the scrapers now skip stale
IDs gracefully and log a warning instead of dropping rows for
surviving stocks alongside the orphan. - The Holdings worker now wakes on
StockCusipChangedinstead of
waiting for the next ≤24h cycle, and retries a tracked-CUSIP miss
instead of permanently marking the data set as processed. - Pre-2021 FTD ZIP files (
cnsfails20*) routinely 404 because SEC moved
their archive. The handler already logs these as a warning, but used
to also dump theHttpRequestException's stack trace, making
cold-start logs look full of unhandled errors. The stack trace is now
suppressed — the warning line carries the only useful signal.
SEC / XBRL
FinancialFactsImportServicewas reading SEC's filing-levelfy/
fpfields as each fact's period identity, but SEC stamps every
comparable-year value inside one filing with the filing's fiscal
year (a FY2024 10-K carrying three years of revenue tags all three
rowsfy=2024, fp=FY). The resulting collision at the natural unique
index made downstream consumers filter ambiguously by(FiscalYear, FiscalPeriod), surfacing wrong figures on the web Financials tab,
MCPGetFinancialStatement/CompareFinancialFact, and the MCP
GetFinancialFacttime series.FiscalYear/FiscalPeriodare now
derived fromPeriodStart/PeriodEndagainst
CommonStock.FiscalYearEndMonth/FiscalYearEndDayvia a new
FiscalPeriodResolver(handles 52/53-week filer drift, leap-year FYE
clamps, half-year and nine-month cumulatives, and falls back to the
pre-fix behaviour when the company's FYE is unknown). Existing
FinancialFactrows in any deployed database still carry the pre-fix
identity — to refresh, stop the worker, drop theFinancialFact
andFinancialFactsSyncStatustables, and restart; the scraper will
re-ingest from the SEC HTTP cache without re-downloading.- iXBRL facts whose scale would overflow
decimalare now dropped
instead of failing the import. - BM25 chunk-search SQL bounded with a 5s command timeout.
- Network failures during document fetching are now retried (transient)
rather than recorded as errors; expected legacy/malformed ownership
XML no longer surfaces as a reported error.
Yahoo
- Incomplete OHLC rows are skipped instead of emitting impossible bars;
AdjustedClosefalls back toClosewhen Yahoo returns a null hole. - Bars are dated on the exchange-local calendar via
meta.gmtoffset
instead of UTC, fixing one-day drift on non-US tickers. - Yahoo column access is bounded for ragged chart payloads.
- 429 and 5xx responses are retried with backoff across the Yahoo,
SEC, FINRA, House, and Senate clients.
Web / culture
- All date parsers (FRED observations, SEC filings, Form 4 transaction
date, congress disclosures, FTD file names, holdings ISO dates) now
useInvariantCultureto keep imports deterministic on machines with
comma-decimal locales. StocksController.Indexclamps non-positivepageto 1 (was a 500
from a negativeOFFSET).HomeController.Errorclamps the status code to the valid HTTP
range.StatisticsExtensions.SafeRoundreturns null for out-of-decimal-range
doubles.Equibles.Web.ComputeRsireturns 100 for a zero-loss window (was
NaN).- The home-page title no longer duplicates the Equibles brand.
CsvExportService.Format(DateOnly)pinned to invariant culture.HoldingsExportController.Activityreturns 404 when the selected
date has no prior quarter.
Operator UX
- Embedding service healthcheck used
curl, which is not present in
theollama/ollamaimage, leaving the container permanently
unhealthyand preventingembedding-pull/worker-embedding(and
thus the entire vector embedding profile) from starting. Switched the
probe toollama list. EmbeddingConfigis now properly bound on startup, so the embedding
worker actually runs when the profile is enabled.- Embedding chunk failures are isolated per chunk; systemic outages
back off instead of looping. - Worker now skips and retries soon when the tracked universe is empty
at cold start, instead of repeatedly attempting empty cycles. Sec:ContactEmailis rejected when whitespace-only.- Live activity feed shows newest events at the top of the list.
Security
- Markdown link URI scheme allow-list —
javascript:(and other
non-http(s) schemes) in user-controlled markdown are now stripped
before render. ChunkingStrategy.CleanTextstrips<script>/<style>/ comment
nodes before chunking, blocking script injection through document
text.FileManager.SaveFileenforces anAcceptedExtensionsallow-list.IsValidDisclosureUrluses an origin-based check instead of
substring matching, closing an SSRF bypass on Congress disclosure
URLs.IsSafeFilenameswitched to a bare-name allow-list.DocumentTextTools.HighlightKeywordguards against empty-keyword
loops (DoS).ErrorManager.Createuses surrogate-pair-safe truncation.- Search query control characters are stripped before being written to
application logs. - Bcl.Memory transitive dependency upgraded to remediate
CVE-2024-43485.
Security Fixes
- Markdown link URI scheme allow‑list strips non‑http(s) schemes (e.g., javascript:).
- FileManager.SaveFile enforces an AcceptedExtensions allow‑list.
- IsValidDisclosureUrl now performs origin‑based check to close SSRF bypass on Congress disclosure URLs.
- Bcl.Memory dependency upgraded to remediate CVE-2024-43485.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About daniel3303/Equibles](https:
All releases →Beta — feedback welcome: [email protected]