Skip to main content

SEC.PRIV.GRANT_FILE — An account can read and write files as the server

  • Category: security
  • Severity: high
  • Level: 0
  • Confidence: deterministic
  • Downtime class: none — the finding is about a privilege, not about a statement
  • Stability: stable
  • Suites: audit
  • Applies to: MySQL 8.4

What it does

LOAD_FILE() reads any file the MySQL server process can read. SELECT … INTO OUTFILE writes one. Both run as the server's operating-system user, not as the account connecting.

So an injection that reaches an account holding FILE does not have to escalate anywhere. It can read configuration, keys and other applications' data off the same host, and write a file somewhere the host will later execute.

The honest limit: secure_file_priv

How far that actually reaches is decided by a server setting the grant knows nothing about:

secure_file_privWhat FILE can touch
a directoryonly files inside it
the empty stringanything the server user can reach
NULLnothing — both operations are disabled

This finding reports the privilege and points at the setting. It deliberately does not claim a reach it has not measured — the setting is a separate fact, and reporting it here would be a second alarm for a finding that belongs with the server settings.

What it looks like

-- Reads and writes files as the SERVER's operating-system user.
GRANT FILE ON *.* TO 'app'@'10.0.0.%';

What to do about it

-- An application account has no use for it.
REVOKE FILE ON *.* FROM 'app'@'10.0.0.%';

-- And on the server, confine what FILE can reach at all:
-- secure_file_priv = /var/lib/mysql-files (a directory)
-- secure_file_priv = NULL (disabled entirely)

A data-import job that genuinely uses LOAD DATA INFILE is the one case worth checking before revoking — and it is usually better served by LOAD DATA LOCAL INFILE from the client, which needs no server-side privilege at all.

The account SQLens connects as is never reported here.