Summary
When creating or updating a system key with a scope whose environment name contains a colon (e.g. myproject:api:dev), the CLI silently truncates the environment to everything before the second colon (api). The stored scope then points to a non-existing environment, rendering the system key useless for that scope.
kfl run and kfl download are not affected — they accept --env api:dev verbatim and pass it through correctly.
Steps to Reproduce
- Create an environment whose name contains a colon, e.g.
api:dev
- Create a system key scoped to it:
kfl keys create --type system --scope myproject:api:dev --permission read
- Inspect the created key's scopes (e.g. via
kfl keys list)
Result: scope is saved as { project: "myproject", environment: "api" }
Expected: scope is saved as { project: "myproject", environment: "api:dev" }
The key will subsequently fail all scope checks for api:dev and cannot access any secrets in that environment.
Root Cause
Both kfl keys create and kfl keys put split the --scope string using a two-element destructure (packages/cli/src/commands/keys.ts:73 and :110):
const [project, environment] = s.split(":");
"myproject:api:dev".split(":") yields ["myproject", "api", "dev"]. Destructuring into two variables silently drops "dev".
The server performs no re-splitting — it stores exactly what the CLI sends.
Workaround
None. The truncated scope cannot be corrected after the fact without revoking and recreating the key with a direct API call that bypasses the CLI.
Potential Fix
Split on the first colon only, so everything after it is treated as the environment name (packages/cli/src/commands/keys.ts:73 and :110):
const colonIdx = s.indexOf(":");
const project = s.slice(0, colonIdx);
const environment = s.slice(colonIdx + 1);
Apply the same fix to both kfl keys create (line 73) and kfl keys put (line 110).
Also implement: PROJECTS must NOT have any colons in the name, otherwise it might conflict with this behavior.
Summary
When creating or updating a system key with a scope whose environment name contains a colon (e.g.
myproject:api:dev), the CLI silently truncates the environment to everything before the second colon (api). The stored scope then points to a non-existing environment, rendering the system key useless for that scope.kfl runandkfl downloadare not affected — they accept--env api:devverbatim and pass it through correctly.Steps to Reproduce
api:devkfl keys list)Result: scope is saved as
{ project: "myproject", environment: "api" }Expected: scope is saved as
{ project: "myproject", environment: "api:dev" }The key will subsequently fail all scope checks for
api:devand cannot access any secrets in that environment.Root Cause
Both
kfl keys createandkfl keys putsplit the--scopestring using a two-element destructure (packages/cli/src/commands/keys.ts:73and:110):"myproject:api:dev".split(":")yields["myproject", "api", "dev"]. Destructuring into two variables silently drops"dev".The server performs no re-splitting — it stores exactly what the CLI sends.
Workaround
None. The truncated scope cannot be corrected after the fact without revoking and recreating the key with a direct API call that bypasses the CLI.
Potential Fix
Split on the first colon only, so everything after it is treated as the environment name (
packages/cli/src/commands/keys.ts:73and:110):Apply the same fix to both
kfl keys create(line 73) andkfl keys put(line 110).Also implement: PROJECTS must NOT have any colons in the name, otherwise it might conflict with this behavior.