Skip to content

fix(core): Accept mixed dot and bracket notation in external secret expressions#28563

Open
jeanibarz wants to merge 1 commit inton8n-io:masterfrom
jeanibarz:fix/28516-external-secrets-mixed-notation
Open

fix(core): Accept mixed dot and bracket notation in external secret expressions#28563
jeanibarz wants to merge 1 commit inton8n-io:masterfrom
jeanibarz:fix/28516-external-secrets-mixed-notation

Conversation

@jeanibarz
Copy link
Copy Markdown
Contributor

Summary

Credentials using the external secrets vault can't be saved when an expression combines dot and bracket notation, e.g. $secrets.azureKeyVault["postgres-n8n-data"]. The save request fails with Could not find a valid external secret vault name, and the only workaround is to rewrite every affected expression as pure bracket notation.

The root cause is in extractProviderKeysFromExpression in packages/cli/src/credentials/external-secrets.utils.ts. The dot-notation regex uses a (?=\.) lookahead, so it requires the character after the provider key to be another dot. A mixed expression like $secrets.azureKeyVault["postgres-n8n-data"] has [ there, so neither the dot regex nor the bracket regex (which expects $secrets['vault']) matches, and extractProviderKeysFromExpression returns []. validateAccessToReferencedSecretProviders in credentials/validation.ts then treats the expression as having no valid provider and throws.

This regression was introduced by #25406 (release 2.9.0) when the validator was added.

The fix

Widen the dot-notation lookahead from (?=\.) to (?=[.\[]), so it accepts either further dot access ($secrets.vault.key) or a transition into bracket notation ($secrets.vault["key"]). The new regex is a strict superset of the old one, so existing working expressions are unaffected.

Key decisions

  • Only the dot regex was widened. Pure bracket notation ($secrets["vault"]["key"]) already works via the separate bracket regex, so no change there. The analogous mirror-image case $secrets["vault"].key is a separate shape that would need its own fix — I'm intentionally not scope-creeping into it here.
  • Single-file change. Only external-secrets.utils.ts needs to change; containsExternalSecretExpression and validation.ts don't require updates because they already detect the $secrets. prefix and dispatch to the extractor.

Tests

Added five unit tests in external-secrets.utils.test.ts covering the new surface:

  • Double-quoted bracket key with hyphenated secret name (exact reproducer from the report)
  • Single-quoted bracket key variant
  • Hyphenated provider name with bracket access ($secrets.my-vault["key"])
  • Bracket access followed by further dot access ($secrets.vault["key"].subfield)
  • Multiple providers in one expression mixing both forms

All five fail on master and pass with the fix. The existing 12 tests in external-secrets.utils.test.ts and 39 tests in credentials/validation.test.ts remain green.

Related Linear tickets, Github issues, and Community forum posts

closes #28516

Review / Merge checklist

  • PR title and summary are descriptive
  • Tests included
  • Docs updated or follow-up ticket created (n/a — no public API change)
  • Backport label if urgent fix

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

Architecture diagram
sequenceDiagram
    participant UI as Client / API Caller
    participant CS as Credentials Service
    participant VAL as Validator (validation.ts)
    participant UT as Utils (external-secrets.utils.ts)

    Note over UI,UT: Request to save credentials with expression:<br/>$secrets.azureKeyVault["postgres-n8n-data"]

    UI->>CS: Save Credentials Request
    CS->>VAL: validateAccessToReferencedSecretProviders(expression)
    
    VAL->>UT: extractProviderKeysFromExpression(expression)
    
    Note over UT: CHANGED: Regex now looks ahead for<br/>either "." or "[" after provider name
    UT->>UT: Match $secrets.(${PROVIDER_KEY_PATTERN})(?=[.\[])
    
    alt Successful Match (Fixed Path)
        UT-->>VAL: Return ["azureKeyVault"]
        VAL->VAL: Verify user has access to "azureKeyVault"
        VAL-->>CS: Validation Success
        CS-->>UI: 200 OK (Credentials Saved)
    else No Match (Regression/Error Path)
        UT-->>VAL: Return []
        VAL-->>CS: Throw "Could not find a valid external secret vault name"
        CS-->>UI: 400 Bad Request / Error
    end
Loading

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Breaking change in 2.9.0 when saving/sharing Credentials, using external vault

1 participant