Skip to content

Conversation

@victorvhs017
Copy link
Contributor

@victorvhs017 victorvhs017 commented Nov 14, 2025

Description 📣

We are introducing the new proxy command to the CLI.

You can use it like this:

infisical proxy start --domain=http://localhost:8080 --resync-interval=2 --cache-ttl=1 --listen-address=localhost:8081

Here's a quick demonstration

Screenshare.-.2025-11-14.11_16_51.AM.mp4

And a more in-depth documentation can be found here: https://www.notion.so/infisical/Infisical-Proxy-2a9564692229808db6bdd30b73ed041a

Type ✨

  • Bug fix
  • New feature
  • Improvement
  • Breaking change
  • Documentation

Tests 🛠️

If you're running the CLI locally, you can use the debug command to get a snapshot of your in-memory cache:

go run main.go proxy debug --listen-address=localhost:8081

Also, run the proxy start command with the --log-level=debug flag for better observability in the tests.

Tests:

  • Try an invalid domain
    • Should allow the start but the proxy will fail
  • Test all secrets and endpoints V3 and v4
    • The get endpoints should cache and the others should be only proxied
    • Test with different values for expand secret reference, recursive and include_imports params
  • To try the resync you can set the resync-interval to 1 and the cache-ttl to 1
    • It will not sync on the first loop (cache ttl not expired yet) and will sync on the next loop
    • Do some lists and gets
      • Update the secret value
        • After the next sync the value in the cache should have updated
      • Delete the secret
        • After the next sync the cache entry should be evicted
      • Remove the access token
        • After the next sync all entries related to that token should be evicted
      • Remove the identity from the project
        • After the next sync all entries related to that token and project should be evicted
      • Remove the identity permission to access the secret or path
        • After the next sync all entries related to that token and secret or path should be evicted
      • Stop the local infisical instance
        • After the next sync the cache shouldn't change.
  • Stop the proxy server and start it again
    • The cache will be empty
  • Do some lists and gets
    • Do an update, batch update, delete or batch delete on the same path
      • The requests with secrets on that path will be purged accross all tokens
  • In your local, set the rate limit of the app to work on development and lower the limit to something like 5 requests
    • Start your proxy with resync-interval=1 and the cache-ttl=1
    • cache 10 different requests
    • check logs and the debug statements to see the proxy handling the rate limit
      • even when the rate limit is reached, all cachedAt value will rise and steadily, meaning that the entries are being updated
    • Works for SSE requests to like api/v1/events/subscribe/project-events

Testing rate-limiting:

Remove this if statement in the backend/src/server/app.ts file:

image

Victor Santos added 3 commits November 12, 2025 21:19
- Added `proxy.go` to handle proxy server commands, including starting the server and printing cache debug information.
- Introduced a caching mechanism in `cache.go` to store and manage HTTP responses, supporting token-based cache invalidation.
- Implemented resync logic to refresh cached entries based on expiration.
- Added command-line flags for configuring the proxy server's domain, listen address, resync interval, and cache TTL.
- Included a debug endpoint for development mode to retrieve cache information.
- Removed the `startResyncLoop` function from `proxy.go` and moved it to a new `resync.go` file for better organization.
- Enhanced the caching system in `cache.go` to include a compound path index for improved cache entry management and eviction after mutation calls.
- Introduced a new method to handle resync responses, including rate limit handling and entry eviction based on HTTP status codes.
- Updated the proxy server to utilize a streaming client for long-lived connections and improved logging for cache hits and misses.
- Added functionality to purge cache entries based on mutation paths across all tokens.
- Updated the `compoundPathIndex` comment in `cache.go` to clarify its purpose for purging after mutation calls.
- Changed the locking mechanism in `GetFirstRequestForToken` to use a write lock for thread safety.
- Enhanced the `EvictAllEntriesForToken` and `RemoveTokenFromIndex` methods to delete entries from the `compoundPathIndex` when a token is evicted.
- Improved response handling in `handleResyncResponse` by ensuring the response body is closed properly in all cases to prevent resource leaks.
@greptile-apps
Copy link

greptile-apps bot commented Nov 14, 2025

Greptile Overview

Greptile Summary

This PR introduces a new proxy server feature for Infisical CLI that caches secret API responses with intelligent invalidation and background resync capabilities.

Key changes:

  • New infisical proxy start command creates an HTTP proxy server that sits between clients and Infisical API
  • Implements in-memory caching with SHA-256 cache keys based on method + path + query + token
  • Cache invalidation on mutations (PATCH/DELETE) purges affected entries across all tokens
  • Background resync loop validates tokens and refreshes expired cache entries (configurable TTL and interval)
  • Supports streaming endpoints for SSE without buffering
  • Dev-mode debug endpoint for cache inspection

Critical security issues found:

  • SSRF vulnerability: User-controlled --domain flag allows proxying to arbitrary hosts including internal services (packages/cmd/proxy.go:78-81)
  • Path traversal: Unsanitized URL path concatenation could redirect requests to attacker-controlled domains (packages/cmd/proxy.go:165-167)
  • Debug endpoint exposes cached secret values in dev mode
  • Regex without ReDoS protection in error message parsing
  • Incomplete cache purging on mutation when request body extraction fails

Missing documentation: No documentation found in /docs folder explaining how to use this feature.

Confidence Score: 1/5

  • This PR has critical security vulnerabilities (SSRF and path traversal) that could expose secrets to attackers
  • Score reflects two high-severity security issues that enable attackers to redirect authenticated requests to malicious endpoints, potentially leaking secrets and authentication tokens. The SSRF via user-controlled domain flag and path traversal via URL concatenation are exploitable attack vectors that must be fixed before merging
  • packages/cmd/proxy.go requires immediate attention for SSRF and path traversal vulnerabilities in URL handling logic

Important Files Changed

File Analysis

Filename Score Overview
packages/cmd/proxy.go 1/5 New proxy server command with critical SSRF and path traversal vulnerabilities in domain/URL handling, plus cache poisoning risk from mutation logic and debug endpoint exposure
packages/proxy/cache.go 4/5 Thread-safe in-memory cache with compound indexing for secrets; implementation is solid with proper mutex usage and cleanup logic
packages/proxy/resync.go 3/5 Background resync loop with token validation and rate limit handling; has ReDoS vulnerability in regex parsing of error messages

Sequence Diagram

sequenceDiagram
    participant Client
    participant Proxy as Infisical Proxy
    participant Cache
    participant API as Infisical API
    participant ResyncLoop as Background Resync

    Note over Proxy: Server starts with cache-ttl and resync-interval configs
    
    rect rgb(200, 220, 240)
        Note over Client,API: GET Request Flow (Cacheable)
        Client->>Proxy: GET /api/v3/secrets?projectId=x&environment=prod<br/>(Bearer token in header)
        Proxy->>Cache: Check cache with hash(method+path+query+token)
        alt Cache Hit
            Cache-->>Proxy: Return cached response
            Proxy-->>Client: 200 OK (from cache)
        else Cache Miss
            Proxy->>API: Forward GET request to domain
            API-->>Proxy: 200 OK + secrets data
            Proxy->>Cache: Store response with IndexEntry<br/>(projectId, environment, secretPath)
            Proxy-->>Client: 200 OK + secrets data
        end
    end

    rect rgb(240, 220, 200)
        Note over Client,API: PATCH/DELETE Request Flow (Mutation)
        Client->>Proxy: PATCH /api/v3/secrets<br/>(body: projectId, environment, secretPath)
        Proxy->>API: Forward mutation request
        API-->>Proxy: 200 OK
        Proxy->>Cache: PurgeByMutation(projectId, environment, secretPath)<br/>across ALL tokens
        Note over Cache: Invalidates matching entries<br/>for all users/tokens
        Proxy-->>Client: 200 OK
    end

    rect rgb(220, 240, 220)
        Note over ResyncLoop,API: Background Resync Loop (every resync-interval minutes)
        loop Every resync-interval
            ResyncLoop->>Cache: GetAllTokens()
            Cache-->>ResyncLoop: List of tokens
            loop For each token
                ResyncLoop->>Cache: GetFirstRequestForToken(token)
                Cache-->>ResyncLoop: Sample request for token validation
                ResyncLoop->>API: Test request with token
                alt 401 Unauthorized
                    API-->>ResyncLoop: 401
                    ResyncLoop->>Cache: EvictAllEntriesForToken(token)
                    Note over Cache: All entries for expired token removed
                else Valid token
                    API-->>ResyncLoop: Success
                end
            end
            
            ResyncLoop->>Cache: GetExpiredRequests(cacheTTL)
            Cache-->>ResyncLoop: Entries older than cache-ttl
            loop For each expired entry (sorted by age)
                ResyncLoop->>API: Refetch with original request params
                alt 200 OK
                    API-->>ResyncLoop: Fresh data
                    ResyncLoop->>Cache: UpdateResponse(new data, reset timestamp)
                else 401/403/404
                    API-->>ResyncLoop: Auth/Not Found error
                    ResyncLoop->>Cache: EvictEntry(cacheKey)
                else 429 Rate Limited
                    API-->>ResyncLoop: Rate limit (retry-after: N seconds)
                    ResyncLoop->>ResyncLoop: Sleep N+2 seconds, then continue
                else Other errors
                    Note over ResyncLoop,Cache: Keep stale entry for availability
                end
            end
        end
    end
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, 6 comments

Edit Code Review Agent Settings | Greptile

…y server

- Enhanced the `startProxyServer` function in `proxy.go` to log errors when parsing mutation request bodies fails, ensuring better visibility into potential cache issues.
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.

2 participants