[TT-14791] log error on missing vault path in api definition#7663
[TT-14791] log error on missing vault path in api definition#7663edsonmichaque merged 16 commits intomasterfrom
Conversation
|
This PR addresses a critical bug that causes the gateway to panic and crash if an API definition contains a A key architectural improvement in this PR is the introduction of a Files Changed Analysis
Architecture & Impact Assessment
sequenceDiagram
participant APILoader
participant VaultClient as SecretReader
participant Gateway
APILoader->>VaultClient: ReadSecret("non/existent/path")
alt Old Behavior (Panic)
VaultClient-->>APILoader: Returns (nil, nil)
APILoader->>APILoader: Accesses secret.Data (nil pointer dereference)
APILoader--xGateway: Panic!
end
alt New Behavior (Graceful Error)
VaultClient-->>APILoader: Returns (nil, nil)
APILoader->>APILoader: Checks if secret is nil
APILoader-->>Gateway: Returns descriptive error
Note right of Gateway: Logs error and continues operation
end
Scope Discovery & Context Expansion
Metadata
Powered by Visor from Probelabs Last updated: 2026-02-02T08:31:44.105Z | Triggered by: pr_updated | Commit: 6667ed0 💡 TIP: You can chat with Visor using |
✅ Security Check PassedNo security issues found – changes LGTM. Architecture Issues (1)
✅ Performance Check PassedNo performance issues found – changes LGTM. ✅ Quality Check PassedNo quality issues found – changes LGTM. Powered by Visor from Probelabs Last updated: 2026-02-02T08:31:47.169Z | Triggered by: pr_updated | Commit: 6667ed0 💡 TIP: You can chat with Visor using |
|
API Changes --- prev.txt 2026-02-02 08:30:19.605032471 +0000
+++ current.txt 2026-02-02 08:30:08.902040415 +0000
@@ -13913,6 +13913,11 @@
func (c *Consul) Store() *consulapi.KV
+type SecretReader interface {
+ ReadSecret(path string) (*vaultapi.Secret, error)
+}
+ SecretReader allows mocking Vault in tests without a real instance.
+
type Store interface {
Get(key string) (string, error)
// Put writes a value to the KV store
@@ -13929,7 +13934,7 @@
type Vault struct {
// Has unexported fields.
}
- Vault is an implementation of a KV store which uses Consul as it's backend
+ Vault is an implementation of a KV store which uses Vault as its backend
func (v *Vault) Client() *vaultapi.Client
@@ -13937,6 +13942,8 @@
func (v *Vault) Put(key string, value string) error
+func (v *Vault) ReadSecret(path string) (*vaultapi.Secret, error)
+
# Package: ./storage/mock
package mock // import "github.com/TykTechnologies/tyk/storage/mock" |
|
Not easy to add test case for this new nil check without broader refactoring. This ticket is a targetted nil check bug fix, the change is low risk vs. the risk introduced by a refactor to add test coverage for 3 lines of code. Test coverage for vault should be a factor when kv interfaces are consolidated (a different piece of work to this bug fix). |
There was a problem hiding this comment.
While it is a small change, we still need to provide coverage. No major refactoring is needed, look at this code snippet right before the change:
secret, err := a.Gw.vaultKVStore.(*kv.Vault).Client().Logical().Read(vaultSecretPath + prefixKeys)
if err != nil {
return err
}This needs to be changed, so that it can return a dummy implementation that can be used for tests.
One way could be to have an extended interface like
type VaultKVStore interface {
kv.Store
Client() *api.Client
}and then add a function to GW that handles the interface/implemetation provision:
func (gw *Gateway) GetVaultKVStore() (vaultStore VaultKVStore, ok bool)Use the dummy implemetation then to setup your tests
|
@pvormste how about just doing the read path? In storage/kv/vault.go: In gateway/api_definition.go: keeps the interface minimal vs. full client |
79de8b4 to
81c32a4
Compare
|
Path traversal check is outside the scope of this ticket, we've already ballooned in complexity vs the initial nil check only. |
|
Note from/to visor - it initially suggested a path traversal risk, then disagreed with the todo. Comment has been removed.
|
edsonmichaque
left a comment
There was a problem hiding this comment.
LGTM!
@pvormste since you raised some questions, would you give an approval if you are happy?
pvormste
left a comment
There was a problem hiding this comment.
Thank you, this looks much better now, great job!
Please note that tests are absolutely required even for such small changes, otherwise we will not be able to catch possible regressions in the future.
|
|
/release to release-5.8 |
Fix gateway panic when API definition contains vault:// reference and vault path does not exist ## Description When an API definition (Classic or OAS) contains a vault:// reference in any string field, the gateway attempts to load secrets from a hardcoded vault path (secret/data/tyk-apis) during API load. If this path does not exist in Vault, the gateway crashes with a nil pointer dereference panic. ## Related Issue https://tyktech.atlassian.net/browse/TT-14791 ## Motivation and Context * Add a nil check for the vault secret response in replaceVaultSecrets() before accessing secret.Data * Return a descriptive error message when the vault path does not exist * The existing error handling in replaceSecrets() will log this error and continue, preventing the panic ## How This Has Been Tested Test cases in jira ## Screenshots (if appropriate) ## Types of changes <!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist <!-- Go over all the following points, and put an `x` in all the boxes that apply --> <!-- If there are no documentation updates required, mark the item as checked. --> <!-- Raise up any additional concerns not covered by the checklist. --> - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why <!---TykTechnologies/jira-linter starts here--> ### Ticket Details <details> <summary> <a href="https://tyktech.atlassian.net/browse/TT-14791" title="TT-14791" target="_blank">TT-14791</a> </summary> | | | |---------|----| | Status | In Code Review | | Summary | [Innersource] Gateway panics when API definition contains vault:// reference and vault path does not exist | Generated at: 2026-02-02 07:50:30 </details> <!---TykTechnologies/jira-linter ends here--> --------- Co-authored-by: Edson Michaque <edson@michaque.com> (cherry picked from commit 94ec558)
|
✅ Cherry-pick successful. A PR was created: #7726 |
… api definition (#7663) (#7726) ### **User description** [TT-14791] log error on missing vault path in api definition (#7663) Fix gateway panic when API definition contains vault:// reference and vault path does not exist ## Description When an API definition (Classic or OAS) contains a vault:// reference in any string field, the gateway attempts to load secrets from a hardcoded vault path (secret/data/tyk-apis) during API load. If this path does not exist in Vault, the gateway crashes with a nil pointer dereference panic. ## Related Issue https://tyktech.atlassian.net/browse/TT-14791 ## Motivation and Context * Add a nil check for the vault secret response in replaceVaultSecrets() before accessing secret.Data * Return a descriptive error message when the vault path does not exist * The existing error handling in replaceSecrets() will log this error and continue, preventing the panic ## How This Has Been Tested Test cases in jira ## Screenshots (if appropriate) ## Types of changes <!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Refactoring or add test (improvements in base code or adds test coverage to functionality) ## Checklist <!-- Go over all the following points, and put an `x` in all the boxes that apply --> <!-- If there are no documentation updates required, mark the item as checked. --> <!-- Raise up any additional concerns not covered by the checklist. --> - [ ] I ensured that the documentation is up to date - [ ] I explained why this PR updates go.mod in detail with reasoning why it's required - [ ] I would like a code coverage CI quality gate exception and have explained why <!---TykTechnologies/jira-linter starts here--> ### Ticket Details <details> <summary> <a href="https://tyktech.atlassian.net/browse/TT-14791" title="TT-14791" target="_blank">TT-14791</a> </summary> | | | |---------|----| | Status | In Code Review | | Summary | [Innersource] Gateway panics when API definition contains vault:// reference and vault path does not exist | Generated at: 2026-02-02 07:50:30 </details> <!---TykTechnologies/jira-linter ends here--> --------- Co-authored-by: Edson Michaque <edson@michaque.com> [TT-14791]: https://tyktech.atlassian.net/browse/TT-14791?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ ___ ### **PR Type** Bug fix, Tests ___ ### **Description** - Prevent panic on missing Vault secrets - Add SecretReader interface for Vault reads - Return descriptive errors for nil data - Add unit tests for Vault edge cases ___ ### Diagram Walkthrough ```mermaid flowchart LR A["API definition contains `vault://` reference"] B["`APIDefinitionLoader.replaceVaultSecrets()`"] C["`kv.SecretReader.ReadSecret()`"] D["Nil/empty secret checks"] E["Return descriptive error (no panic)"] F["Tests: loader + Vault adapter"] A -- "triggers secret resolution" --> B B -- "read from KV store interface" --> C C -- "returns secret / nil / error" --> D D -- "on missing path or data" --> E B -- "validated by" --> F ``` <details> <summary><h3> File Walkthrough</h3></summary> <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Bug fix</strong></td><td><table> <tr> <td> <details> <summary><strong>api_definition.go</strong><dd><code>Guard Vault secret reads to avoid panic</code> </dd></summary> <hr> gateway/api_definition.go <ul><li>Cast <code>vaultKVStore</code> to <code>kv.SecretReader</code><br> <li> Log and error when interface unsupported<br> <li> Handle <code>nil</code> secret and <code>nil</code> <code>secret.Data</code><br> <li> Return clearer Vault-path failure messages</ul> </details> </td> <td><a href="https://github.com/TykTechnologies/tyk/pull/7726/files#diff-0cf80174bbafb36f6d4f4308ebbd971b2833b76a936bad568220aa1a4ba0ee8b">+15/-1</a> </td> </tr> </table></td></tr><tr><td><strong>Tests</strong></td><td><table> <tr> <td> <details> <summary><strong>api_definition_test.go</strong><dd><code>Add replaceVaultSecrets regression and edge tests</code> </dd></summary> <hr> gateway/api_definition_test.go <ul><li>Add mock Vault readers/stores for testing<br> <li> Test missing <code>SecretReader</code> implementation case<br> <li> Test nil secret, nil data, and read errors<br> <li> Test successful <code>vault://</code> replacement behavior</ul> </details> </td> <td><a href="https://github.com/TykTechnologies/tyk/pull/7726/files#diff-2394daab6fdc5f8dc234699c80c0548947ee3d68d2e33858258d73a8b5eb6f44">+166/-0</a> </td> </tr> <tr> <td> <details> <summary><strong>store_test.go</strong><dd><code>Add tests for Vault ReadSecret behavior</code> </dd></summary> <hr> storage/kv/store_test.go <ul><li>Add HTTP-backed tests for <code>Vault.ReadSecret</code><br> <li> Verify success path returns a populated secret<br> <li> Verify 404 maps to <code>(nil, nil)</code> result<br> <li> Verify 500 maps to an error result</ul> </details> </td> <td><a href="https://github.com/TykTechnologies/tyk/pull/7726/files#diff-be6a5fa0dfe83bc6bdaa6cfa76f580e4e6891595b66a6b931d97fa1a2e39a06b">+79/-1</a> </td> </tr> </table></td></tr><tr><td><strong>Enhancement</strong></td><td><table> <tr> <td> <details> <summary><strong>vault.go</strong><dd><code>Add SecretReader abstraction for Vault secret reads</code> </dd></summary> <hr> storage/kv/vault.go <ul><li>Introduce <code>kv.SecretReader</code> interface for secret reads<br> <li> Implement <code>ReadSecret</code> on <code>*Vault</code> via Vault Logical API<br> <li> Enable mocking Vault reads without real client</ul> </details> </td> <td><a href="https://github.com/TykTechnologies/tyk/pull/7726/files#diff-b49ef7901e3657f34a414ff71a5ad1c6665862c42497e59227fc128ea573c47d">+10/-1</a> </td> </tr> </table></td></tr></tr></tbody></table> </details> ___ Co-authored-by: Chris Anderton <chrisanderton@users.noreply.github.com> Co-authored-by: Edson Michaque <edson@michaque.com>



Fix gateway panic when API definition contains vault:// reference and vault path does not exist
Description
When an API definition (Classic or OAS) contains a vault:// reference in any string field, the gateway attempts to load secrets from a hardcoded vault path (secret/data/tyk-apis) during API load. If this path does not exist in Vault, the gateway crashes with a nil pointer dereference panic.
Related Issue
https://tyktech.atlassian.net/browse/TT-14791
Motivation and Context
How This Has Been Tested
Test cases in jira
Screenshots (if appropriate)
Types of changes
Checklist
Ticket Details
TT-14791
Generated at: 2026-02-02 08:29:24