It should not be possible to create or update an env-var with no value set and if an attempt to do so happens the user should be told that it's not allowed
- Dominant language
- JavaScript
- Stars
- 400
- Forks
- 89
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 146
Description
## What happens
Two related defects in instance environment variables, both of which return
HTTP 200 and report success in the UI.
1. **Creating** a hidden variable with an empty value silently discards it. The
variable does not exist afterwards.
2. **Clearing** an existing hidden variable silently does nothing. The previous
value is still in the database and is still passed to the running instance.
The second is the more serious one. Someone who removes a token from a hidden
variable is told it saved, sees an empty field afterwards, and reasonably
believes the secret is gone. It is not.
Non-hidden variables behave correctly in both cases, so this is specific to
`hidden: true`.
## Reproduction
Self-hosted FlowFuse 3.0.2, docker-compose install, fresh instance, reproduced
through the API so the UI is not involved:
```
# 1. create a hidden variable with a blank value
PUT /api/v1/projects/:id
{"settings":{"env":[{"name":"HIDDEN_BLANK","value":"","hidden":true}]}}
-> 200, and the variable list is empty. HIDDEN_BLANK was never created.
# 2. create one with a value, then blank it
PUT ... {"env":[{"name":"TOKEN","value":"abc123","hidden":true}]} -> 200
PUT ... {"env":[{"name":"TOKEN","value":"","hidden":true}]} -> 200
# read the stored row directly, not the API (the API masks hidden values)
SELECT value FROM "ProjectSettings" WHERE "ProjectId" = '...' AND key = 'settings'
-> {"name": "TOKEN", "value": "abc123", "hidden": true}
```
The old value is still there after the blanking call returned 200.
## Control cases
| Case | Result |
|---|---|
| Create hidden variable, empty value | Silently discarded |
| Blank an existing hidden variable | Silently ignored, old value kept |
| Delete the variable, then re-add it empty and hidden | Still discarded |
| Create non-hidden variable, empty value | Works |
| Blank an existing non-hidden variable | Works |
There is no way to end up with a hidden variable whose value is empty, and no
way to clear a hidden variable's value other than deleting the variable.
## Likely cause
An empty value on a hidden variable looks indistinguishable from "the client
did not send the masked value back". `GET` returns `""` for hidden variables,
so the UI cannot round-trip them, and the save path appears to treat an empty
value as "no change supplied". That is a sensible guard for an unchanged masked
field, but it leaves no way to express "clear this", and it also rejects
creation.
## Suggested behaviour
Distinguish "unchanged" from "explicitly emptied" rather than inferring it from
emptiness. Either send an explicit marker for an unchanged masked value, or
have the client omit the key entirely when it was not touched, so that a
present-but-empty value can be taken at face value.
Failing a functional fix, the save should not report success. Silently
discarding a variable, and silently retaining a secret the user believes they
removed, are both worse than an error.
## Environment
- FlowFuse 3.0.2 self-hosted (docker-compose), Postgres 14
- Also observed on FlowFuse Cloud while setting up instance environment
variables
Contributor guide
Research direction
Start with the PUT /api/v1/projects/:id environment-variable save path and the ProjectSettings row described in the report. Reproduce hidden-variable creation and clearing through the API, then trace how masked empty values are distinguished from omitted values. Done means explicit empty values are handled consistently and the API does not report success while retaining or silently discarding data.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, postgresql
- Domain
- api, backend, databases, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100