← 输入框|github.com|刷新
Skip to content

fix: Restrict UI server CORS to trusted origins - #6986

Merged
jyejare merged 5 commits into
feast-dev:masterfrom
ntkathole:fix-cve-2024-11602-cors-ui
Oct 9, 2026
Merged

jyejare merged 5 commits into
feast-dev:masterfrom
ntkathole:fix-cve-2024-11602-cors-ui

Conversation

@ntkathole

Copy link
Copy Markdown
Member

What this PR does / why we need it:

The Feast UI server configured CORS with allow_origins=["*"] together with allow_credentials=True, so any website a user visited could issue authenticated cross-origin requests to the server and read the responses (CVE-2024-11602 / CWE-346, Origin Validation Error).

The bundled Web UI is served from the same FastAPI app as the API, so it is same-origin and needs no permissive CORS policy. Disable CORS by default and let operators opt in to cross-origin access with an explicit allowlist of trusted origins. Following MLflow's convention, this is exposed as feast ui --cors-allowed-origins or the FEAST_UI_CORS_ALLOWED_ORIGINS environment variable (comma-separated). The wildcard origin is never combined with credentials again.

Which issue(s) this PR fixes:

Fixes #6810

The Feast UI server configured CORS with allow_origins=["*"] together with
allow_credentials=True, so any website a user visited could issue
authenticated cross-origin requests to the server and read the responses
(CVE-2024-11602 / CWE-346, Origin Validation Error).

The bundled Web UI is served from the same FastAPI app as the API, so it is
same-origin and needs no permissive CORS policy. Disable CORS by default and
let operators opt in to cross-origin access with an explicit allowlist of
trusted origins. Following MLflow's convention, this is exposed as
`feast ui --cors-allowed-origins` or the FEAST_UI_CORS_ALLOWED_ORIGINS
environment variable (comma-separated). The wildcard origin is never combined
with credentials again.

Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
@ntkathole ntkathole self-assigned this Oct 9, 2026
@ntkathole
ntkathole requested a review from a team as a code owner October 9, 2026 08:41
@codecov-commenter

codecov-commenter commented Oct 9, 2026 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 50.59%. Comparing base (66c55e3) to head (df8455c).
⚠️ Report is 2 commits behind head on master.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #6986      +/-   ##
==========================================
+ Coverage   49.93%   50.59%   +0.66%     
==========================================
  Files         443      451       +8     
  Lines       55498    56447     +949     
  Branches     8095     8227     +132     
==========================================
+ Hits        27711    28561     +850     
- Misses      25864    25923      +59     
- Partials     1923     1963      +40     
Flag Coverage Δ
go-feature-server 30.58% <ø> (ø)
python-unit 52.04% <100.00%> (+0.68%) ⬆️
Files with missing lines Coverage Δ
sdk/python/feast/cli/ui.py 87.50% <100.00%> (+16.07%) ⬆️
sdk/python/feast/feature_store.py 46.46% <ø> (ø)
sdk/python/feast/ui_server.py 26.82% <100.00%> (+0.38%) ⬆️

... and 19 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f118b47...df8455c. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The unit-test-python jobs install an exact, mutually compatible dependency
set via `uv pip sync` from the pinned pyXX-ci-requirements.txt
(protobuf==7.36.2 alongside grpcio-health-checking==1.84.0, whose generated
code targets protobuf gencode 7.35.1).

The Test Python step then runs `uv run`, which auto-syncs the environment.
Because uv.lock is not committed, that sync re-resolves the uncapped
pyproject dependencies (`protobuf>=4.24.0`) and leaves the environment with
protobuf 6.33.6 while grpcio's health_pb2 still targets gencode 7.35.1. Every
test that imports grpc_health/v1/health.proto (registry/UI/MCP/feature-server
servers) then fails at import time with:

    VersionError: ... grpc_health/v1/health.proto: gencode 7.35.1 runtime
    6.33.6. Runtime version cannot be older than the linked gencode version.

Set UV_NO_SYNC=1 for the step so `uv run` uses the already-installed, pinned
environment instead of re-resolving. This is unrelated to the CORS change in
this PR; it is a pre-existing CI hazard that surfaces for any test importing
the health proto.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
ntkathole and others added 2 commits October 9, 2026 18:12
The previous commit set UV_NO_SYNC only for the unit-test workflow step. The
same protobuf gencode/runtime skew also breaks every other uv-based test
workflow (integration-test-python-local, and the label-gated
integration/remote-rbac/dbt/master/nightly jobs), because they all run
`make install-python-dependencies-ci` (pinned `uv pip sync`) followed by a
`make test-python-*` target that invokes `uv run`, which auto-syncs and
re-resolves the uncapped pyproject deps.

Export UV_NO_SYNC=1 from the Makefile so every `uv run` recipe uses the
already-installed, pinned environment instead of re-resolving. pixi-based
targets (ray/duckdb/registration) are unaffected. This generalizes the
unit-test fix to all uv-based test targets in one place; the unit-test
workflow keeps its step-level env because it also runs a standalone `uv run`
outside make.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>

@jyejare jyejare left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR removes permissive-by-default CORS from the UI server and adds an explicit allowlist option, documentation, and tests—a meaningful security improvement. However, the allowlist still accepts *, which recreates the vulnerable credentialed wildcard behavior, so the security fix is incomplete. The Makefile also disables uv syncing for all Make invocations, not just CI.

Comment on lines +889 to 899
if cors_origins:
app.add_middleware(
CORSMiddleware,
allow_origins=cors_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

_setup_rest_mode(app, store)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new allowlist accepts * without validation. With Starlette's CORSMiddleware and allow_credentials=True, configuring allow_origins=["*"] can reflect the requesting origin while allowing credentials, recreating the security issue this change is intended to fix. Reject * at the server boundary so callers using get_app or serve_ui directly cannot bypass CLI guidance.

Suggested:

Suggested change
if cors_origins:
app.add_middleware(
CORSMiddleware,
allow_origins=cors_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
_setup_rest_mode(app, store)
if cors_origins:
if "*" in cors_origins:
raise ValueError("CORS origins must be explicit; '*' is not allowed")
app.add_middleware(
CORSMiddleware,
allow_origins=cors_origins,
allow_credentials=True,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CVE was the insecure default (* + credentials with no configuration), which this PR fixes — the default is now no CORS. Passing --cors-allowed-origins '*' is an explicit, opt-in operator decision, the same category as Feast's own auth_type=no_auth (shipped and documented, not treated as a CVE) and MLflow's documented dev-only *. Rather than forbid an informed choice, df8455c logs a warning when * is configured and documents it as development-only, so it can't be enabled unknowingly. Keeping explicit * allowed.

Comment thread Makefile
Comment on lines +24 to +32
# CI installs the exact, mutually compatible dependency set via
# `uv pip sync` from the pinned sdk/python/requirements/pyXX-ci-requirements.txt
# (install-python-dependencies-ci). uv.lock is not committed, so a plain
# `uv run` would auto-sync and re-resolve the uncapped pyproject dependencies,
# which can install an inconsistent set -- e.g. protobuf older than the gencode
# baked into grpcio's health_pb2, which then fails the protobuf gencode/runtime
# check at import time. Run every `uv run` target against the already-installed
# environment instead of re-resolving. (pixi-based targets are unaffected.)
export UV_NO_SYNC := 1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This export applies to every use of the Makefile, including local development, so uv run targets will no longer sync missing dependencies for developers. The workflow already sets UV_NO_SYNC for its test step; keep this behavior scoped to CI (or to the specific targets that require it) rather than changing all local Make invocations.

Suggested:

Suggested change
# CI installs the exact, mutually compatible dependency set via
# `uv pip sync` from the pinned sdk/python/requirements/pyXX-ci-requirements.txt
# (install-python-dependencies-ci). uv.lock is not committed, so a plain
# `uv run` would auto-sync and re-resolve the uncapped pyproject dependencies,
# which can install an inconsistent set -- e.g. protobuf older than the gencode
# baked into grpcio's health_pb2, which then fails the protobuf gencode/runtime
# check at import time. Run every `uv run` target against the already-installed
# environment instead of re-resolving. (pixi-based targets are unaffected.)
export UV_NO_SYNC := 1
Remove the global Makefile export and set `UV_NO_SYNC=1` only in the CI step or target that runs against the pre-synced environment.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The auto-sync re-resolution happens on every uv run invocation, not just tests, so the skew can hit any uv target in both CI and local. Scoping to a single CI step would leave integration-test-python-local and the other uv-based workflows broken — they don't set the env. The documented setup installs deps first (make install-python-dependencies-*), so a global UV_NO_SYNC removes no needed capability; it only stops uv run from silently re-resolving the uncommitted lock. Keeping it global for consistency across CI and local.

Comment on lines +370 to 402


def test_cors_allows_only_configured_origins(mock_feature_store):
"""With an explicit allowlist, only trusted origins are echoed back."""
trusted = "https://feast.example.com"
with _cors_client(mock_feature_store, cors_origins=[trusted]) as client:
allowed = client.get("/health", headers={"Origin": trusted})
assertpy.assert_that(
allowed.headers.get("access-control-allow-origin")
).is_equal_to(trusted)

denied = client.get("/health", headers={"Origin": "https://evil.example.com"})
assertpy.assert_that(denied.headers).does_not_contain_key(
"access-control-allow-origin"
)


def test_cors_never_uses_wildcard(mock_feature_store):
"""An untrusted origin is never reflected even when an allowlist is set."""
with _cors_client(
mock_feature_store, cors_origins=["https://feast.example.com"]
) as client:
response = client.get(
"/health", headers={"Origin": "https://attacker.example.com"}
)
assertpy.assert_that(
response.headers.get("access-control-allow-origin")
).is_none()


@patch("feast.ui_server.uvicorn")
@patch("feast.ui_server.get_app")
def test_start_server_dual_stack_binds_prebuilt_socket(mock_get_app, mock_uvicorn):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests verify that an untrusted origin is denied when a specific trusted origin is configured, but they do not cover the dangerous cors_origins=["*"] configuration. Add a test that asserts this configuration is rejected; it will protect the security boundary from being weakened later.

Suggested:

Suggested change
def test_cors_allows_only_configured_origins(mock_feature_store):
"""With an explicit allowlist, only trusted origins are echoed back."""
trusted = "https://feast.example.com"
with _cors_client(mock_feature_store, cors_origins=[trusted]) as client:
allowed = client.get("/health", headers={"Origin": trusted})
assertpy.assert_that(
allowed.headers.get("access-control-allow-origin")
).is_equal_to(trusted)
denied = client.get("/health", headers={"Origin": "https://evil.example.com"})
assertpy.assert_that(denied.headers).does_not_contain_key(
"access-control-allow-origin"
)
def test_cors_never_uses_wildcard(mock_feature_store):
"""An untrusted origin is never reflected even when an allowlist is set."""
with _cors_client(
mock_feature_store, cors_origins=["https://feast.example.com"]
) as client:
response = client.get(
"/health", headers={"Origin": "https://attacker.example.com"}
)
assertpy.assert_that(
response.headers.get("access-control-allow-origin")
).is_none()
@patch("feast.ui_server.uvicorn")
@patch("feast.ui_server.get_app")
def test_start_server_dual_stack_binds_prebuilt_socket(mock_get_app, mock_uvicorn):
def test_wildcard_cors_origin_is_rejected(mock_feature_store):
with pytest.raises(ValueError, match="explicit"):
with _cors_client(mock_feature_store, cors_origins=["*"]):
pass

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the discussion on the get_app comment, we're intentionally allowing an explicit * (documented + warned) rather than rejecting it, so a rejection test doesn't apply. Added test_wildcard_cors_origin_is_allowed_but_warns in df8455c instead, asserting * is honored and emits the warning.

Comment on lines +80 to 83
cors_allowed_origins_list = [
origin.strip() for origin in cors_allowed_origins.split(",") if origin.strip()
]
store = create_feature_store(ctx)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comma-separated values are only trimmed, not checked as origins. Values containing a path (for example, https://app.example.com/ui) will never match a browser's Origin header, which contains only scheme, host, and optional port; this can make an apparently configured UI silently fail cross-origin requests. Validate entries and report malformed origins clearly, ideally at the server boundary so direct API callers receive the same protection.

Suggested:

Suggested change
cors_allowed_origins_list = [
origin.strip() for origin in cors_allowed_origins.split(",") if origin.strip()
]
store = create_feature_store(ctx)
cors_allowed_origins_list = [
origin.strip() for origin in cors_allowed_origins.split(",") if origin.strip()
]
# Validate each entry as an origin (scheme + host, with no path/query/fragment)
# before passing it to the server.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — a value with a path would silently never match the browser Origin. df8455c documents that each origin must be a bare scheme+host[:port] with no path/query/trailing slash. Kept it as documentation to stay lenient on input, but happy to add a strict check at the get_app boundary if you'd prefer.

Address review feedback on the CORS allowlist:

- When `*` is configured (an explicit, opt-in operator choice, like Feast's
  own documented `auth_type=no_auth`), keep honoring it but log a warning:
  with credentials, Starlette reflects the caller's origin for any site, so
  the wildcard is intended for local development only. This keeps the operator
  in control while making the risk visible instead of silent.
- Document that each origin must be a bare scheme+host[:port] with no path or
  trailing slash, since browsers send the Origin header without a path and a
  value like `https://app.example.com/ui` would silently never match.
- Add a unit test asserting `*` is accepted and warns.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
@ntkathole
ntkathole requested a review from jyejare October 9, 2026 14:19
@jyejare
jyejare merged commit 5e7ef3e into feast-dev:master Oct 9, 2026
36 of 38 checks passed
ntkathole pushed a commit that referenced this pull request Oct 13, 2026
# [0.67.0](v0.66.0...v0.67.0) (2026-10-13)

### Bug Fixes

* Allow dill 0.4 so UDF serialization works on Python 3.14 ([#6858](#6858)) ([139704f](139704f))
* Allow serving features while a feature view is MATERIALIZING ([#6789](#6789)) ([e2d7fe2](e2d7fe2)), closes [#6780](#6780)
* Allowlist the pinned commit SHA flagged by detect-secrets ([4b81d18](4b81d18))
* Apply point-in-time filter correctly with the Polars backend ([#6992](#6992)) ([01224d0](01224d0))
* Authorize registry server writes before deserializing UDFs ([e0ef16e](e0ef16e))
* Automate versioned documentation publication ([#6763](#6763)) ([5ad5592](5ad5592)), closes [#6762](#6762)
* Avoid NumPy generic-unit deprecation when importing feast.type_map ([5fea698](5fea698))
* Bind metrics, REST registry, ui, and lineage servers dual-stack ([#6886](#6886)) ([8d2773c](8d2773c))
* Bound Arrow Flight batch size in the offline server ([#6896](#6896)) ([d169238](d169238))
* Compute std and var correctly for tiled aggregations ([213a130](213a130))
* Convert PdfBytes values to protos like ImageBytes ([#6968](#6968)) ([af20fe4](af20fe4))
* Decode fixed_size_list as the matching Feast list value type ([#6944](#6944)) ([8cfe891](8cfe891))
* Do not log /metrics requests from the pre-fork metrics server thread ([7087f1f](7087f1f)), closes [#6928](#6928)
* Don't return from finally blocks in REST registry helpers ([d7cb4d0](d7cb4d0))
* Encode non-finite floats in feature server JSON responses ([#6930](#6930)) ([211ecb8](211ecb8))
* Feature freshness logic updated ([#6765](#6765)) ([f0bc070](f0bc070))
* Fix monitoring auth ([015cc84](015cc84))
* Handle non-nanosecond timestamps in tiled aggregations ([b8989cb](b8989cb))
* Improve feature list column sizing ([#6793](#6793)) ([2573693](2573693))
* Include vector attributes in Field equality ([#6934](#6934)) ([298c3f6](298c3f6))
* Increase feast container probe timeouts to avoid false restarts ([e8dbd50](e8dbd50))
* Infer the tensor type from retrieved values in to_tensor ([a03e323](a03e323))
* Infer timestamps for datetime columns in any unit or timezone ([810391f](810391f))
* Infer vector width when vector_length is undeclared ([0056565](0056565)), closes [#6907](#6907)
* Initialize auth managers in standalone lineage server ([#6873](#6873)) ([ecd0d38](ecd0d38))
* Keep a zero watermark delay threshold on a Kafka source ([e2e28c7](e2e28c7))
* Keep entity rows apart in the ibis point-in-time join ([a87c070](a87c070))
* Keep the BatchFeatureView type and settings when copying it ([#6989](#6989)) ([013fc57](013fc57))
* Keep tiling, offline and stream engine settings when copying a StreamFeatureView ([fac0f88](fac0f88))
* Limit tiled max and min aggregations to the window ([2583c45](2583c45))
* Load Milvus collections once instead of on every query ([#6882](#6882)) ([f9e91fa](f9e91fa))
* Make vector length validation reachable, schema-driven and vectorized ([#6909](#6909)) ([29af8c0](29af8c0)), closes [#6907](#6907)
* Map INT32_LIST, PDF_BYTES and IMAGE_BYTES type names to their ValueType ([8c1e825](8c1e825))
* Map narrow and unsigned Arrow integer types to Feast value types ([#6960](#6960)) ([ae74360](ae74360))
* Map Spark smallint and tinyint columns to INT32 ([9d42729](9d42729))
* Map SQL Server bigint to INT64 and float to DOUBLE ([6d15533](6d15533))
* Map Trino DECIMAL columns to pyarrow decimal128 ([155bc24](155bc24))
* Normalize Arrow-backed dtypes from Ray Dataset.to_pandas() for pyarrow >=25 compatibility ([#6916](#6916)) ([374f1d7](374f1d7))
* **operator:** Set grpc appProtocol on the offline Service port ([f9dcfb5](f9dcfb5))
* Pin expected tensor to same device in online retrieval test ([#6777](#6777)) ([1f2584d](1f2584d))
* Preserve an unset aggregation time window across a proto round-trip ([2000379](2000379))
* Preserve entity row order in precomputed reads ([ce37029](ce37029))
* Pull the MinIO test image from pgsty/minio ([fe27230](fe27230))
* Pull the MinIO test image from quay ([#6838](#6838)) ([367001b](367001b))
* Raise Trino monitoring query errors other than a missing table ([6161766](6161766))
* Read Kafka and Kinesis sources without a batch source from proto ([a620f5c](a620f5c))
* Read naive datetimes as UTC in UnixTimestamp values ([bc703d9](bc703d9))
* Record which storage class wrote a custom_storage payload ([#6988](#6988)) ([c0545f7](c0545f7))
* Refresh the SQL registry cache after deleting a data source ([66c55e3](66c55e3))
* Refresh the SQL registry cache after deleting a permission ([6b212f5](6b212f5))
* Reject unknown resource types and actions in the REST permission API ([a5eaa36](a5eaa36))
* Remove pip install command from Redis GLIDE docstring ([66ff990](66ff990))
* Remove runtime pip install hints from mlflow errors ([dd9f099](dd9f099))
* Remove unsupported vector_len from PostgreSQL tutorial config ([fcc9a85](fcc9a85))
* Repair Chronon operator validation and Pixi CI setup ([#6947](#6947)) ([3710f78](3710f78))
* Report Dask monitoring read errors instead of no data ([81673d9](81673d9))
* Resolve feature view batch source name against registry ([f8883d0](f8883d0))
* Restrict UI server CORS to trusted origins ([#6986](#6986)) ([5e7ef3e](5e7ef3e))
* Return feature_view_metadata from the REST feature server ([#6927](#6927)) ([bc5aeef](bc5aeef))
* Serve aliased on demand feature views in feature services ([823b92e](823b92e))
* Snapshot tag filters in registry cache keys ([81e1546](81e1546))
* Stabilize materialization checks across hour boundaries ([#6948](#6948)) ([acadb17](acadb17))
* Stop the Couchbase online store reporting failed writes as written ([b3f3c98](b3f3c98))
* Support SQL registry dump ([b60f9c7](b60f9c7))
* Treat datetimes with a None utcoffset as naive ([687bee8](687bee8))
* Unwrap SecretStr tokens when building Trino auth objects ([#6771](#6771)) ([922db5c](922db5c))
* Use a valid ShuffleStrategy for the Ray DatasetContext ([6259f5c](6259f5c))
* Use do_exchange for offline server reads to support HPA ([bae07fc](bae07fc))
* Use group_by in Polars backend aggregation ([#6965](#6965)) ([7b9fad2](7b9fad2))
* Use upstream kubectl image as feast-operator CronJob default ([d6cc1dc](d6cc1dc))
* Use UTC end bound and correct docs for disable_event_timestamp ([#6956](#6956)) ([cc07c82](cc07c82)), closes [#6936](#6936)

### Features

* Add a non-JVM read path for Lance data sources ([#6943](#6943)) ([e2a53bb](e2a53bb)), closes [#6925](#6925) [#5782](#5782) [#6909](#6909)
* Add a non-JVM write path for Lance data sources ([#6945](#6945)) ([f754323](f754323)), closes [#6943](#6943) [#6909](#6909)
* Add Chronon online and offline store integrations ([#6188](#6188)) ([dd059c6](dd059c6))
* Add consistency_level to the Milvus online store config ([97296c1](97296c1))
* Add dualStack server option to the Feast operator ([#6887](#6887)) ([725a147](725a147)), closes [#6977](#6977)
* Add Lance optional dependencies ([#6958](#6958)) ([20bc993](20bc993))
* Add LanceFormat table format with version/tag pinning ([1196e22](1196e22)), closes [#5650](#5650)
* Add MLflow as a first-class offline DataSource for Feast ([#6702](#6702)) ([3667772](3667772))
* Add optional GLIDE client for Redis online reads ([#6870](#6870)) ([6e9a532](6e9a532))
* Add quality monitoring features for Trino offline store ([#6779](#6779)) ([9340545](9340545))
* Add SavedDatasetLanceStorage ([1118d3e](1118d3e))
* Add standalone MCP server as a first-class component ([0efab5c](0efab5c)), closes [python-keycloak#623](https://github.com/python-keycloak/issues/623)
* Add structured audit logging for MCP feature server ([#6456](#6456)) ([640ac70](640ac70))
* Add Trino compute engine for batch retrieval and materialization ([#6898](#6898)) ([11a47b4](11a47b4))
* Batch Postgres online reads across feature views ([#6832](#6832)) ([514bee7](514bee7)), closes [#3259](#3259)
* **bigtable:** Make write batch size and concurrency configurable ([#6847](#6847)) ([5388522](5388522))
* Bucket feature count labels in latency metrics ([#6811](#6811)) ([d9ea120](d9ea120))
* Expose runtime version in Feast UI ([#6843](#6843)) ([fa8f06b](fa8f06b))
* Make Milvus index and search params configurable ([ef743ff](ef743ff))
* Offline write batch for IcebergSource ([5be5ed0](5be5ed0))
* OpenLineage consumer improvements - dataset versioning, column lineage, ownership ([69f294e](69f294e))
* **operator:** Add tolerations and nodeSelector to the FeatureStore CR ([#6741](#6741)) ([03dac6f](03dac6f))
* Serve the MCP server dual-stack on --host :: ([4fc9726](4fc9726))
* Support Milvus partition keys in the Milvus online store ([0ed3285](0ed3285))
* Support token, uri and db_name in the Milvus online store ([c5efecd](c5efecd))
* Version-pinning for FeatureService (online + offline) ([#6718](#6718)) ([787845a](787845a))

### Performance Improvements

* Avoid pandas copy in Spark reads ([#6878](#6878)) ([4771156](4771156))
* Decouple metrics HTTP server into a dedicated child process ([#6855](#6855)) ([0b621de](0b621de))
* Reduce online serving hot-path overhead from metrics and audit logging ([5ee7ee3](5ee7ee3))
ntkathole added a commit to opendatahub-io/feast that referenced this pull request Oct 14, 2026
* fix: Increase feast container probe timeouts to avoid false restarts

Signed-off-by: Srihari <svenkata@redhat.com>

* chore: Remove unused hermeto offline tree and sdist requirement locks (feast-dev#6987)

* chore: Remove unused multicloud hermeto offline build tree

Drop sdk/python/feast/infra/feature_servers/multicloud/offline/, which only
supported local hermeto/arrow-from-source and RPM lock offline image builds
and is unused by Makefile CI, GitHub Actions, or the standard feature-server
Dockerfiles. Also clear related .secrets.baseline entries.

Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: Drop unused minimal-sdist requirement locks

Remove py3.10–3.12 minimal-sdist(-build) lockfiles, stop generating them
in lock-python-dependencies-all, and delete the minimal-sdist-build extra.
They only supported hermeto build-from-sdist offline image builds.

Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: Refresh pixi.lock after removing minimal-sdist-build

Keep pixi install --locked in sync with the pyproject.toml optional
dependency change so ray/duckdb CI environments can install.

Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(release): release 0.67.0

# [0.67.0](feast-dev/feast@v0.66.0...v0.67.0) (2026-10-13)

### Bug Fixes

* Allow dill 0.4 so UDF serialization works on Python 3.14 ([feast-dev#6858](feast-dev#6858)) ([139704f](feast-dev@139704f))
* Allow serving features while a feature view is MATERIALIZING ([feast-dev#6789](feast-dev#6789)) ([e2d7fe2](feast-dev@e2d7fe2)), closes [feast-dev#6780](feast-dev#6780)
* Allowlist the pinned commit SHA flagged by detect-secrets ([4b81d18](feast-dev@4b81d18))
* Apply point-in-time filter correctly with the Polars backend ([feast-dev#6992](feast-dev#6992)) ([01224d0](feast-dev@01224d0))
* Authorize registry server writes before deserializing UDFs ([e0ef16e](feast-dev@e0ef16e))
* Automate versioned documentation publication ([feast-dev#6763](feast-dev#6763)) ([5ad5592](feast-dev@5ad5592)), closes [feast-dev#6762](feast-dev#6762)
* Avoid NumPy generic-unit deprecation when importing feast.type_map ([5fea698](feast-dev@5fea698))
* Bind metrics, REST registry, ui, and lineage servers dual-stack ([feast-dev#6886](feast-dev#6886)) ([8d2773c](feast-dev@8d2773c))
* Bound Arrow Flight batch size in the offline server ([feast-dev#6896](feast-dev#6896)) ([d169238](feast-dev@d169238))
* Compute std and var correctly for tiled aggregations ([213a130](feast-dev@213a130))
* Convert PdfBytes values to protos like ImageBytes ([feast-dev#6968](feast-dev#6968)) ([af20fe4](feast-dev@af20fe4))
* Decode fixed_size_list as the matching Feast list value type ([feast-dev#6944](feast-dev#6944)) ([8cfe891](feast-dev@8cfe891))
* Do not log /metrics requests from the pre-fork metrics server thread ([7087f1f](feast-dev@7087f1f)), closes [feast-dev#6928](feast-dev#6928)
* Don't return from finally blocks in REST registry helpers ([d7cb4d0](feast-dev@d7cb4d0))
* Encode non-finite floats in feature server JSON responses ([feast-dev#6930](feast-dev#6930)) ([211ecb8](feast-dev@211ecb8))
* Feature freshness logic updated ([feast-dev#6765](feast-dev#6765)) ([f0bc070](feast-dev@f0bc070))
* Fix monitoring auth ([015cc84](feast-dev@015cc84))
* Handle non-nanosecond timestamps in tiled aggregations ([b8989cb](feast-dev@b8989cb))
* Improve feature list column sizing ([feast-dev#6793](feast-dev#6793)) ([2573693](feast-dev@2573693))
* Include vector attributes in Field equality ([feast-dev#6934](feast-dev#6934)) ([298c3f6](feast-dev@298c3f6))
* Increase feast container probe timeouts to avoid false restarts ([e8dbd50](feast-dev@e8dbd50))
* Infer the tensor type from retrieved values in to_tensor ([a03e323](feast-dev@a03e323))
* Infer timestamps for datetime columns in any unit or timezone ([810391f](feast-dev@810391f))
* Infer vector width when vector_length is undeclared ([0056565](feast-dev@0056565)), closes [feast-dev#6907](feast-dev#6907)
* Initialize auth managers in standalone lineage server ([feast-dev#6873](feast-dev#6873)) ([ecd0d38](feast-dev@ecd0d38))
* Keep a zero watermark delay threshold on a Kafka source ([e2e28c7](feast-dev@e2e28c7))
* Keep entity rows apart in the ibis point-in-time join ([a87c070](feast-dev@a87c070))
* Keep the BatchFeatureView type and settings when copying it ([feast-dev#6989](feast-dev#6989)) ([013fc57](feast-dev@013fc57))
* Keep tiling, offline and stream engine settings when copying a StreamFeatureView ([fac0f88](feast-dev@fac0f88))
* Limit tiled max and min aggregations to the window ([2583c45](feast-dev@2583c45))
* Load Milvus collections once instead of on every query ([feast-dev#6882](feast-dev#6882)) ([f9e91fa](feast-dev@f9e91fa))
* Make vector length validation reachable, schema-driven and vectorized ([feast-dev#6909](feast-dev#6909)) ([29af8c0](feast-dev@29af8c0)), closes [feast-dev#6907](feast-dev#6907)
* Map INT32_LIST, PDF_BYTES and IMAGE_BYTES type names to their ValueType ([8c1e825](feast-dev@8c1e825))
* Map narrow and unsigned Arrow integer types to Feast value types ([feast-dev#6960](feast-dev#6960)) ([ae74360](feast-dev@ae74360))
* Map Spark smallint and tinyint columns to INT32 ([9d42729](feast-dev@9d42729))
* Map SQL Server bigint to INT64 and float to DOUBLE ([6d15533](feast-dev@6d15533))
* Map Trino DECIMAL columns to pyarrow decimal128 ([155bc24](feast-dev@155bc24))
* Normalize Arrow-backed dtypes from Ray Dataset.to_pandas() for pyarrow >=25 compatibility ([feast-dev#6916](feast-dev#6916)) ([374f1d7](feast-dev@374f1d7))
* **operator:** Set grpc appProtocol on the offline Service port ([f9dcfb5](feast-dev@f9dcfb5))
* Pin expected tensor to same device in online retrieval test ([feast-dev#6777](feast-dev#6777)) ([1f2584d](feast-dev@1f2584d))
* Preserve an unset aggregation time window across a proto round-trip ([2000379](feast-dev@2000379))
* Preserve entity row order in precomputed reads ([ce37029](feast-dev@ce37029))
* Pull the MinIO test image from pgsty/minio ([fe27230](feast-dev@fe27230))
* Pull the MinIO test image from quay ([feast-dev#6838](feast-dev#6838)) ([367001b](feast-dev@367001b))
* Raise Trino monitoring query errors other than a missing table ([6161766](feast-dev@6161766))
* Read Kafka and Kinesis sources without a batch source from proto ([a620f5c](feast-dev@a620f5c))
* Read naive datetimes as UTC in UnixTimestamp values ([bc703d9](feast-dev@bc703d9))
* Record which storage class wrote a custom_storage payload ([feast-dev#6988](feast-dev#6988)) ([c0545f7](feast-dev@c0545f7))
* Refresh the SQL registry cache after deleting a data source ([66c55e3](feast-dev@66c55e3))
* Refresh the SQL registry cache after deleting a permission ([6b212f5](feast-dev@6b212f5))
* Reject unknown resource types and actions in the REST permission API ([a5eaa36](feast-dev@a5eaa36))
* Remove pip install command from Redis GLIDE docstring ([66ff990](feast-dev@66ff990))
* Remove runtime pip install hints from mlflow errors ([dd9f099](feast-dev@dd9f099))
* Remove unsupported vector_len from PostgreSQL tutorial config ([fcc9a85](feast-dev@fcc9a85))
* Repair Chronon operator validation and Pixi CI setup ([feast-dev#6947](feast-dev#6947)) ([3710f78](feast-dev@3710f78))
* Report Dask monitoring read errors instead of no data ([81673d9](feast-dev@81673d9))
* Resolve feature view batch source name against registry ([f8883d0](feast-dev@f8883d0))
* Restrict UI server CORS to trusted origins ([feast-dev#6986](feast-dev#6986)) ([5e7ef3e](feast-dev@5e7ef3e))
* Return feature_view_metadata from the REST feature server ([feast-dev#6927](feast-dev#6927)) ([bc5aeef](feast-dev@bc5aeef))
* Serve aliased on demand feature views in feature services ([823b92e](feast-dev@823b92e))
* Snapshot tag filters in registry cache keys ([81e1546](feast-dev@81e1546))
* Stabilize materialization checks across hour boundaries ([feast-dev#6948](feast-dev#6948)) ([acadb17](feast-dev@acadb17))
* Stop the Couchbase online store reporting failed writes as written ([b3f3c98](feast-dev@b3f3c98))
* Support SQL registry dump ([b60f9c7](feast-dev@b60f9c7))
* Treat datetimes with a None utcoffset as naive ([687bee8](feast-dev@687bee8))
* Unwrap SecretStr tokens when building Trino auth objects ([feast-dev#6771](feast-dev#6771)) ([922db5c](feast-dev@922db5c))
* Use a valid ShuffleStrategy for the Ray DatasetContext ([6259f5c](feast-dev@6259f5c))
* Use do_exchange for offline server reads to support HPA ([bae07fc](feast-dev@bae07fc))
* Use group_by in Polars backend aggregation ([feast-dev#6965](feast-dev#6965)) ([7b9fad2](feast-dev@7b9fad2))
* Use upstream kubectl image as feast-operator CronJob default ([d6cc1dc](feast-dev@d6cc1dc))
* Use UTC end bound and correct docs for disable_event_timestamp ([feast-dev#6956](feast-dev#6956)) ([cc07c82](feast-dev@cc07c82)), closes [feast-dev#6936](feast-dev#6936)

### Features

* Add a non-JVM read path for Lance data sources ([feast-dev#6943](feast-dev#6943)) ([e2a53bb](feast-dev@e2a53bb)), closes [feast-dev#6925](feast-dev#6925) [feast-dev#5782](feast-dev#5782) [feast-dev#6909](feast-dev#6909)
* Add a non-JVM write path for Lance data sources ([feast-dev#6945](feast-dev#6945)) ([f754323](feast-dev@f754323)), closes [feast-dev#6943](feast-dev#6943) [feast-dev#6909](feast-dev#6909)
* Add Chronon online and offline store integrations ([feast-dev#6188](feast-dev#6188)) ([dd059c6](feast-dev@dd059c6))
* Add consistency_level to the Milvus online store config ([97296c1](feast-dev@97296c1))
* Add dualStack server option to the Feast operator ([feast-dev#6887](feast-dev#6887)) ([725a147](feast-dev@725a147)), closes [feast-dev#6977](feast-dev#6977)
* Add Lance optional dependencies ([feast-dev#6958](feast-dev#6958)) ([20bc993](feast-dev@20bc993))
* Add LanceFormat table format with version/tag pinning ([1196e22](feast-dev@1196e22)), closes [feast-dev#5650](feast-dev#5650)
* Add MLflow as a first-class offline DataSource for Feast ([feast-dev#6702](feast-dev#6702)) ([3667772](feast-dev@3667772))
* Add optional GLIDE client for Redis online reads ([feast-dev#6870](feast-dev#6870)) ([6e9a532](feast-dev@6e9a532))
* Add quality monitoring features for Trino offline store ([feast-dev#6779](feast-dev#6779)) ([9340545](feast-dev@9340545))
* Add SavedDatasetLanceStorage ([1118d3e](feast-dev@1118d3e))
* Add standalone MCP server as a first-class component ([0efab5c](feast-dev@0efab5c)), closes [python-keycloak#623](https://github.com/python-keycloak/issues/623)
* Add structured audit logging for MCP feature server ([feast-dev#6456](feast-dev#6456)) ([640ac70](feast-dev@640ac70))
* Add Trino compute engine for batch retrieval and materialization ([feast-dev#6898](feast-dev#6898)) ([11a47b4](feast-dev@11a47b4))
* Batch Postgres online reads across feature views ([feast-dev#6832](feast-dev#6832)) ([514bee7](feast-dev@514bee7)), closes [feast-dev#3259](feast-dev#3259)
* **bigtable:** Make write batch size and concurrency configurable ([feast-dev#6847](feast-dev#6847)) ([5388522](feast-dev@5388522))
* Bucket feature count labels in latency metrics ([feast-dev#6811](feast-dev#6811)) ([d9ea120](feast-dev@d9ea120))
* Expose runtime version in Feast UI ([feast-dev#6843](feast-dev#6843)) ([fa8f06b](feast-dev@fa8f06b))
* Make Milvus index and search params configurable ([ef743ff](feast-dev@ef743ff))
* Offline write batch for IcebergSource ([5be5ed0](feast-dev@5be5ed0))
* OpenLineage consumer improvements - dataset versioning, column lineage, ownership ([69f294e](feast-dev@69f294e))
* **operator:** Add tolerations and nodeSelector to the FeatureStore CR ([feast-dev#6741](feast-dev#6741)) ([03dac6f](feast-dev@03dac6f))
* Serve the MCP server dual-stack on --host :: ([4fc9726](feast-dev@4fc9726))
* Support Milvus partition keys in the Milvus online store ([0ed3285](feast-dev@0ed3285))
* Support token, uri and db_name in the Milvus online store ([c5efecd](feast-dev@c5efecd))
* Version-pinning for FeatureService (online + offline) ([feast-dev#6718](feast-dev#6718)) ([787845a](feast-dev@787845a))

### Performance Improvements

* Avoid pandas copy in Spark reads ([feast-dev#6878](feast-dev#6878)) ([4771156](feast-dev@4771156))
* Decouple metrics HTTP server into a dedicated child process ([feast-dev#6855](feast-dev#6855)) ([0b621de](feast-dev@0b621de))
* Reduce online serving hot-path overhead from metrics and audit logging ([5ee7ee3](feast-dev@5ee7ee3))

---------

Signed-off-by: Srihari <svenkata@redhat.com>
Signed-off-by: ntkathole <nikhilkathole2683@gmail.com>
Co-authored-by: Srihari <svenkata@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: feast-ci-bot <feast-ci-bot@willem.co>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Synk vulnerabilities on Feast pip

3 participants