Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import { isSaaS } from '../../../helpers/app/is-saas.js';
import { Encryptor } from '../../../helpers/encryption/encryptor.js';
import { actionSlackPostMessage } from '../../../helpers/slack/action-slack-post-message.js';
import { isObjectPropertyExists } from '../../../helpers/validators/is-object-property-exists-validator.js';
import { getSsrfSafeRequestConfig } from '../../../helpers/validators/ssrf-safe-http.js';
// TODO: temporarily disabled SSRF/URL safety check in activateTableAction. Restore import to re-enable.
// import { getSsrfSafeRequestConfig } from '../../../helpers/validators/ssrf-safe-http.js';
Comment on lines +16 to +17
Comment on lines +16 to +17

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

Critical: Disabling SSRF protection enables attacks on internal infrastructure in SaaS mode.

The getSsrfSafeRequestConfig() helper provides httpAgent/httpsAgent with DNS lookup guards that block requests to private IPs (127.0.0.1, 10.x.x.x, 192.168.x.x, 169.254.169.254, etc.). Without this protection, a malicious user in SaaS mode can configure a table action URL targeting:

  • Internal services (e.g., http://localhost:8080/admin)
  • Cloud metadata endpoints (e.g., http://169.254.169.254/latest/meta-data/iam/security-credentials/)
  • Private network resources

While timeout and maxRedirects: 0 are preserved, they don't prevent the core SSRF threat—the IP-based filtering is what blocks internal requests.

If this must be disabled temporarily due to a blocking issue, consider:

  1. Adding an allowlist check for tableAction.url against known-safe patterns
  2. Documenting the specific issue requiring this workaround in the TODO
  3. Creating a tracking issue with a deadline for re-enabling

Also applies to: 215-217

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@backend/src/entities/table-actions/table-actions-module/table-action-activation.service.ts`
around lines 16 - 17, The SSRF protection was disabled by removing the
getSsrfSafeRequestConfig import used by activateTableAction; restore SSRF
defenses by re-importing getSsrfSafeRequestConfig and passing its returned
httpAgent/httpsAgent into the HTTP request config used in activateTableAction
(and the related call sites around lines 215-217), so requests are blocked to
private IP ranges; if temporarily unavoidable, add an explicit allowlist check
against tableAction.url and add a TODO linking a tracking issue and deadline
before leaving the helper disabled.

import { ConnectionEntity } from '../../connection/connection.entity.js';
import { EmailService } from '../../email/email/email.service.js';
import { escapeHtml } from '../../email/utils/escape-html.util.js';
Expand Down Expand Up @@ -211,7 +212,9 @@ export class TableActionActivationService {
let result: AxiosResponse<any, any> | undefined;
try {
result = await axios.post(tableAction.url, actionRequestBody, {
...getSsrfSafeRequestConfig(),
// TODO: SSRF/URL safety check temporarily disabled. Restore the line below to re-enable.
// ...getSsrfSafeRequestConfig(),
timeout: 10_000,
Comment on lines +215 to +217
headers: { 'Rocketadmin-Signature': autoadminSignatureHeader, 'Content-Type': 'application/json' },
maxRedirects: 0,
validateStatus: (status) => status <= 599,
Expand Down
Loading