Skip to content

VNX-357: Destructive link or button without a confirmation step

Reports Rails link_to/button_to calls that send DELETE with no confirm/turbo_confirm, and anchors with data-method="delete" or data-turbo-method="delete" and no data-confirm, so one click destroys data without warning.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-357
Severity Low
SARIF level note
Kind sast
Languages Ruby, HTML
CWE CWE-357
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:L/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L
Tags insufficient-dangerous-op-warning rails confirmation cwe-357
Source internal/sast/rules/vnx-357.rego

Overview

VNX-357 maps to CWE-357: Insufficient UI Warning of Dangerous Operations. It reports the one place where a missing warning is visible in markup: an element that issues a DELETE request in one click, in a framework that offers a confirmation on the same element, without using it.

  • Rails views and helpers (.erb, .haml, .slim, .rb): link_to / button_to with method: :delete, :method => :delete or data: { turbo_method: :delete }, whose call (followed across continuation lines) has no confirm:, data-confirm or turbo_confirm.
  • HTML and templates: an <a ... data-method="delete"> tag (rails-ujs, jquery-ujs) with no data-confirm or data-turbo-confirm.

Not reported: elements that ask for confirmation, GET/PATCH/POST links, sign-out links (Devise’s destroy_user_session_path, logout_path: a DELETE of the session, not of data), prose, ERB and HTML comments, and buttons wired to a JavaScript handler (onclick=, (click)=, @click=), because whether that handler confirms is decided in code this rule does not see.

Why This Matters

A Delete link next to Edit or Show is one mis-click away from destroying a record, and a row that renders in the wrong place makes that more likely. A confirmation step is the framework’s standard answer, and leaving it off is usually an oversight.

What Gets Flagged

<%# FLAGGED %>
<%= link_to 'Destroy', post, method: :delete %>
<%= button_to "Delete account", user_path(@user), method: :delete %>
<!-- FLAGGED -->
<a href="/admin/users/7" data-method="delete" rel="nofollow">Delete</a>
<%# NOT FLAGGED %>
<%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %>
<%= link_to "Delete", post_path(post), data: { turbo_method: :delete, turbo_confirm: "Delete this post?" } %>

Remediation

  1. Add data: { turbo_confirm: "..." } (Turbo), or data: { confirm: "..." } / data-confirm (rails-ujs) to every destructive link or button.
  2. For irreversible operations, consider a typed confirmation or an undo window instead of a single dialog.

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-357
// nosec vnx-357

Or record an ignore rule: vulnetix ignore add --rule vnx-357 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-357.rego, cli/internal/sast/docs/vnx-357.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.