<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>Most recent entries from all</title>
    <link>https://vulnerability.circl.lu</link>
    <description>Contains only the most 10 recent entries.</description>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>python-feedgen</generator>
    <language>en</language>
    <lastBuildDate>Thu, 01 Oct 2026 19:34:14 +0000</lastBuildDate>
    <item>
      <title>fkie_cve-2026-41262</title>
      <link>https://vulnerability.circl.lu/vuln/fkie_cve-2026-41262</link>
      <description>&lt;p&gt;Fleet is an open-source device management platform built on osquery. In versions prior to 4.85.0, the global policy read endpoint (GET /api/latest/fleet/policies/{policy_id}) fails to verify team ownership of the requested policy, allowing an authenticated user with observer-level access on any single team to read the full details of policies belonging to any other team and bypass Fleet&amp;#39;s team isolation model. The handler authorizes the request against an empty policy object whose TeamID is nil, which an authorization rule permits for any user holding a role on any team, and then fetches the policy by ID with no team filter and returns it without any post-fetch scope check. Because policy IDs are sequential integers, an attacker can enumerate them to read other teams&amp;#39; policy SQL queries, host pass and fail counts, and associated software-installer and script metadata, exposing security-monitoring strategies and compliance posture across team boundaries. This issue is fixed in version 4.85.0.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Fleet is an open-source device management platform built on osquery. In versions prior to 4.85.0, the global policy read endpoint (GET /api/latest/fleet/policies/{policy_id}) fails to verify team ownership of the requested policy, allowing an authenticated user with observer-level access on any single team to read the full details of policies belonging to any other team and bypass Fleet&amp;#39;s team isolation model. The handler authorizes the request against an empty policy object whose TeamID is nil, which an authorization rule permits for any user holding a role on any team, and then fetches the policy by ID with no team filter and returns it without any post-fetch scope check. Because policy IDs are sequential integers, an attacker can enumerate them to read other teams&amp;#39; policy SQL queries, host pass and fail counts, and associated software-installer and script metadata, exposing security-monitoring strategies and compliance posture across team boundaries. This issue is fixed in version 4.85.0.&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/vuln/fkie_cve-2026-41262</guid>
    </item>
    <item>
      <title>GHSA-gm7f-v959-fr2g — Fleet DM Vulnerable to Cross-Team Policy Data Exposure via Global Policy Read Endpoint</title>
      <link>https://vulnerability.circl.lu/vuln/ghsa-gm7f-v959-fr2g</link>
      <description>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; Go: github.com/fleetdm/fleet/v4&lt;/p&gt;
&lt;p&gt;## Summary&lt;/p&gt;
&lt;p&gt;The global policy read endpoint (`GET /api/latest/fleet/policies/{policy_id}`) performs authorization against an empty `fleet.Policy{}` struct with nil TeamID, then fetches any policy by ID from the database without verifying the fetched policy actually belongs to the global scope. This allows a user with observer-level access on any single team to read the full details of policies belonging to any other team, bypassing Fleet&amp;#39;s team isolation model.&lt;/p&gt;
&lt;p&gt;## Details&lt;/p&gt;
&lt;p&gt;The vulnerability is in `GetPolicyByIDQueries` at `server/service/global_policies.go:163-180`:&lt;/p&gt;
&lt;p&gt;```go
func (svc Service) GetPolicyByIDQueries(ctx context.Context, policyID uint) (*fleet.Policy, error) {
	// Auth check uses empty Policy{} — TeamID is nil
	if err := svc.authz.Authorize(ctx, &amp;amp;fleet.Policy{}, fleet.ActionRead); err != nil {
		return nil, err
	}&lt;/p&gt;
&lt;p&gt;// Fetches ANY policy by ID, regardless of team ownership
	policy, err := svc.ds.Policy(ctx, policyID)
	if err != nil {
		return nil, err
	}
	// ... populates install_software and run_script, returns full policy
	return policy, nil
}
```&lt;/p&gt;
&lt;p&gt;The authorization passes because the OPA rule at `server/authz/policy.rego:724-728` allows reading policies with null `team_id` for any user who holds a role on any team:&lt;/p&gt;
&lt;p&gt;```rego
allow {
  is_null(object.team_id)
  object.type == &amp;#34;policy&amp;#34;
  team_role(subject, subject.teams[_].id) == [admin, maintainer, technician, observer, observer_plus][_]
  action == read
}
```&lt;/p&gt;
&lt;p&gt;Since the auth object has nil TeamID, this rule fi…&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; Go: github.com/fleetdm/fleet/v4&lt;/p&gt;
&lt;p&gt;## Summary&lt;/p&gt;
&lt;p&gt;The global policy read endpoint (`GET /api/latest/fleet/policies/{policy_id}`) performs authorization against an empty `fleet.Policy{}` struct with nil TeamID, then fetches any policy by ID from the database without verifying the fetched policy actually belongs to the global scope. This allows a user with observer-level access on any single team to read the full details of policies belonging to any other team, bypassing Fleet&amp;#39;s team isolation model.&lt;/p&gt;
&lt;p&gt;## Details&lt;/p&gt;
&lt;p&gt;The vulnerability is in `GetPolicyByIDQueries` at `server/service/global_policies.go:163-180`:&lt;/p&gt;
&lt;p&gt;```go
func (svc Service) GetPolicyByIDQueries(ctx context.Context, policyID uint) (*fleet.Policy, error) {
	// Auth check uses empty Policy{} — TeamID is nil
	if err := svc.authz.Authorize(ctx, &amp;amp;fleet.Policy{}, fleet.ActionRead); err != nil {
		return nil, err
	}&lt;/p&gt;
&lt;p&gt;// Fetches ANY policy by ID, regardless of team ownership
	policy, err := svc.ds.Policy(ctx, policyID)
	if err != nil {
		return nil, err
	}
	// ... populates install_software and run_script, returns full policy
	return policy, nil
}
```&lt;/p&gt;
&lt;p&gt;The authorization passes because the OPA rule at `server/authz/policy.rego:724-728` allows reading policies with null `team_id` for any user who holds a role on any team:&lt;/p&gt;
&lt;p&gt;```rego
allow {
  is_null(object.team_id)
  object.type == &amp;#34;policy&amp;#34;
  team_role(subject, subject.teams[_].id) == [admin, maintainer, technician, observer, observer_plus][_]
  action == read
}
```&lt;/p&gt;
&lt;p&gt;Since the auth object has nil TeamID, this rule fi…&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/vuln/ghsa-gm7f-v959-fr2g</guid>
    </item>
  </channel>
</rss>
