Skip to content

Commit 0eeff7a

Browse files
committed
fix(connectors): rename flag to isPrivateDatabaseHostsAllowed; trim comment
- Rename env-flag const to satisfy the env-flags 'is' prefix CI check (env var ALLOW_PRIVATE_DATABASE_HOSTS is unchanged). - Tighten the postgres pinning comment to a single line.
1 parent 90f6e6f commit 0eeff7a

5 files changed

Lines changed: 14 additions & 12 deletions

File tree

apps/sim/app/api/tools/postgresql/utils.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ export async function createPostgresConnection(config: PostgresConnectionConfig)
1818
: { rejectUnauthorized: false, servername: config.host }
1919

2020
const sql = postgres({
21-
// Always connect to the validated, pinned IP to prevent DNS rebinding between
22-
// host validation and connection. For SSL modes that verify, the original
23-
// hostname is preserved as the TLS servername (SNI) above.
21+
// Pin the validated IP (never the hostname) to prevent DNS rebinding; SNI stays the hostname above.
2422
host: resolvedHost,
2523
port: config.port,
2624
database: config.database,

apps/sim/lib/core/config/env-flags.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ if (isTruthy(env.DISABLE_AUTH)) {
8282
* their database lives on the same private network. Blocked on the hosted platform
8383
* regardless of the env var, mirroring {@link isAuthDisabled}.
8484
*/
85-
export const allowPrivateDatabaseHosts = isTruthy(env.ALLOW_PRIVATE_DATABASE_HOSTS) && !isHosted
85+
export const isPrivateDatabaseHostsAllowed = isTruthy(env.ALLOW_PRIVATE_DATABASE_HOSTS) && !isHosted
8686

8787
if (isTruthy(env.ALLOW_PRIVATE_DATABASE_HOSTS)) {
8888
import('@sim/logger')

apps/sim/lib/core/security/input-validation.server.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { createLogger } from '@sim/logger'
66
import { toError } from '@sim/utils/errors'
77
import * as ipaddr from 'ipaddr.js'
88
import { Agent, type RequestInit as UndiciRequestInit, fetch as undiciFetch } from 'undici'
9-
import { allowPrivateDatabaseHosts, isHosted } from '@/lib/core/config/env-flags'
9+
import { isHosted, isPrivateDatabaseHostsAllowed } from '@/lib/core/config/env-flags'
1010
import { type ValidationResult, validateExternalUrl } from '@/lib/core/security/input-validation'
1111
import { PayloadSizeLimitError } from '@/lib/core/utils/stream-limits'
1212

@@ -156,7 +156,7 @@ export async function validateUrlWithDNS(
156156
* on their private network (e.g. a Docker/Swarm service name that resolves to an
157157
* internal IP). The opt-in only bypasses the private/reserved/loopback block; DNS
158158
* is still resolved so the caller can pin the connection to the resolved IP. The
159-
* bypass is never honored on the hosted platform (see {@link allowPrivateDatabaseHosts}).
159+
* bypass is never honored on the hosted platform (see {@link isPrivateDatabaseHostsAllowed}).
160160
*
161161
* @param host - The database hostname to validate
162162
* @param paramName - Name of the parameter for error messages
@@ -174,18 +174,22 @@ export async function validateDatabaseHost(
174174
const cleanHost =
175175
lowerHost.startsWith('[') && lowerHost.endsWith(']') ? lowerHost.slice(1, -1) : lowerHost
176176

177-
if (cleanHost === 'localhost' && !allowPrivateDatabaseHosts) {
177+
if (cleanHost === 'localhost' && !isPrivateDatabaseHostsAllowed) {
178178
return { isValid: false, error: `${paramName} cannot be localhost` }
179179
}
180180

181-
if (ipaddr.isValid(cleanHost) && isPrivateOrReservedIP(cleanHost) && !allowPrivateDatabaseHosts) {
181+
if (
182+
ipaddr.isValid(cleanHost) &&
183+
isPrivateOrReservedIP(cleanHost) &&
184+
!isPrivateDatabaseHostsAllowed
185+
) {
182186
return { isValid: false, error: `${paramName} cannot be a private IP address` }
183187
}
184188

185189
try {
186190
const { address } = await dns.lookup(cleanHost, { verbatim: true })
187191

188-
if (isPrivateOrReservedIP(address) && !allowPrivateDatabaseHosts) {
192+
if (isPrivateOrReservedIP(address) && !isPrivateDatabaseHostsAllowed) {
189193
logger.warn('Database host resolves to blocked IP address', {
190194
paramName,
191195
hostname: host,

apps/sim/lib/core/security/input-validation.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ describe('validateUrlWithDNS', () => {
765765

766766
describe('validateDatabaseHost', () => {
767767
afterEach(() => {
768-
envFlagsMock.allowPrivateDatabaseHosts = false
768+
envFlagsMock.isPrivateDatabaseHostsAllowed = false
769769
})
770770

771771
describe('default (SSRF guard on)', () => {
@@ -808,7 +808,7 @@ describe('validateDatabaseHost', () => {
808808

809809
describe('self-host opt-in (ALLOW_PRIVATE_DATABASE_HOSTS)', () => {
810810
beforeEach(() => {
811-
envFlagsMock.allowPrivateDatabaseHosts = true
811+
envFlagsMock.isPrivateDatabaseHostsAllowed = true
812812
})
813813

814814
it('allows localhost and still resolves an IP to pin', async () => {

packages/testing/src/mocks/env-flags.mock.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export const envFlagsMock = {
1717
isBillingEnabled: false,
1818
isEmailVerificationEnabled: false,
1919
isAuthDisabled: false,
20-
allowPrivateDatabaseHosts: false,
20+
isPrivateDatabaseHostsAllowed: false,
2121
isRegistrationDisabled: false,
2222
isEmailPasswordEnabled: false,
2323
isTriggerDevEnabled: false,

0 commit comments

Comments
 (0)