n8n Without Audit Logs: Detect Breaches Before It’s Too Late

Step by Step Guide to solve missing audit logging breach detection 
Step by Step Guide to solve missing audit logging breach detection


Who this is for: Security engineers and n8n administrators who need reliable audit trails for breach detection and forensic analysis. We cover this in detail in the n8n Security & Hardening Guide.


Quick Diagnosis

If you cannot answer who triggered a workflow, what data was moved, or when a suspicious action occurred, your n8n instance lacks sufficient audit logging. This blind spot blocks early breach detection and hampers investigations.


1. n8n’s Native Logging Architecture

If you encounter any docker container misconfigurations resolve them before continuing with the setup.

Component Default Output Level Typical Use‑Case
Execution Logger ~/.n8n/.n8n.log (or Docker stdout) info Tracks workflow start/end, node inputs/outputs (redacted).
Error Logger Same file error Captures uncaught exceptions, node failures.
Database Audits SQLite/PostgreSQL tables (execution_entity) N/A Stores execution metadata (workflowId, startedAt, finishedAt, status).

EEFA note: The default logger does not retain request‑origin IPs or user identifiers when n8n runs behind a reverse proxy. Without explicit enrichment, you lose the key data needed for breach detection.


2. Enabling Detailed Audit Logs

2.1. Raise the Log Level

Set a more verbose level to capture node inputs before redaction.

# .env
LOG_LEVEL=debug            # captures node inputs before redaction
LOG_OUTPUT=console         # use 'file' for persistent logs
LOG_FILE_PATH=/var/log/n8n/audit.log

2.2. Enrich Logs with User & IP Context

n8n does not attach request metadata automatically. Add a custom Express middleware that injects req.ip and req.user.id into every log entry.

// middleware/requestLogger.js
module.exports = function requestLogger() {
  return (req, res, next) => {
    const userId = req.session?.user?.id ?? 'anonymous';
    req.log = req.log.child({ ip: req.ip, userId });
    next();
  };
};

Register the middleware in Docker:

# docker-compose.yml (excerpt)
services:
  n8n:
    image: n8nio/n8n
    environment:
      - N8N_CUSTOM_MIDDLEWARE=/usr/src/app/custom-middleware/requestLogger.js
    volumes:
      - ./custom-middleware:/usr/src/app/custom-middleware

EEFA: Custom middleware requires compatible node_modules. Re‑build the image after adding new packages. If you encounter any rbac pitfalls resolve them before continuing with the setup.

2.3. Persist Logs with Rotation

Run a lightweight Logrotate container to keep log files manageable.

# docker-compose.yml (logrotate service)
services:
  logrotate:
    image: blacklabelops/logrotate
    volumes:
      - ./logs:/var/log/n8n
    environment:
      - LOGROTATE_CRON=0 0 * * *
      - LOGROTATE_SIZE=100M
      - LOGROTATE_KEEP=7

3. Exporting Logs to External Systems

3.1. Syslog (RFC 5424)

Configure n8n to send JSON logs to a remote syslog collector.

# .env
LOG_OUTPUT=syslog
SYSLOG_HOST=logstash.example.com
SYSLOG_PORT=514
SYSLOG_PROTOCOL=udp

3.2. HTTP (JSON) – Ideal for Cloud SIEMs

Set up HTTP transport for direct ingestion.

# .env
LOG_OUTPUT=http
HTTP_LOG_URL=https://siem.example.com/ingest
HTTP_LOG_METHOD=POST
HTTP_LOG_HEADERS=Authorization:Bearer ${SIEM_TOKEN}

If you prefer a dedicated shipper, use the snippet below.

// logger/httpTransport.js (part 1)
const axios = require('axios');
module.exports = (log) => {
  axios.post(process.env.HTTP_LOG_URL, log, {
    headers: {
      Authorization: `Bearer ${process.env.SIEM_TOKEN}`,
      'Content-Type': 'application/json',
    },
  })
// logger/httpTransport.js (part 2)
  .catch(err => console.error('SIEM transport failed', err));
};

4. Integrating n8n Logs with Popular SIEM Platforms

SIEM Ingestion Method Minimal Config
Elastic Stack Filebeat → Logstash → Elasticsearch filebeat.inputs: – type: log path: /var/log/n8n/*.log
Splunk HTTP Event Collector (HEC) curl -k https://splunk.example.com:8088/services/collector -H “Authorization: Splunk ${HEC_TOKEN}” -d @audit.log
Azure Sentinel Azure Monitor HTTP Data Collector API az monitor log-analytics workspace data-collector create –workspace-name <ws> –resource-group <rg> –name n8nAudit

4.1. Sample Logstash Pipeline for Elastic

Input & Filter – reads JSON logs and parses timestamps.

# pipelines.conf (input & filter)
input {
  file {
    path => "/var/log/n8n/*.log"
    start_position => "beginning"
    codec => json
  }
}
filter {
  date {
    match => ["timestamp", "ISO8601"]
  }
}

Output – ships to Elasticsearch with daily indices. If you encounter any missing api rate limiting dos resolve them before continuing with the setup.

# pipelines.conf (output)
output {
  elasticsearch {
    hosts => ["https://es.example.com:9200"]
    index => "n8n-audit-%{+YYYY.MM.dd}"
    user => "logstash"
    password => "${ELASTIC_PASSWORD}"
  }
}

4.2. Splunk HEC JSON Example

{
  "event": {
    "workflowId": "12",
    "nodeName": "HTTP Request",
    "userId": "admin",
    "ip": "203.0.113.5",
    "action": "execute",
    "status": "success",
    "timestamp": "2024-11-01T14:23:45.123Z"
  },
  "sourcetype": "n8n:audit"
}

5. Verifying Log Integrity & Setting Up Breach‑Detection Alerts

Alert Trigger SIEM Query (Elastic) Description
Privileged API call event.action:”execute” AND event.nodeName:”HTTP Request” AND NOT event.userId:”service-account” Detect non‑service accounts invoking external APIs.
Bulk data export event.nodeName:”Spreadsheet” AND event.bytesExported > 10485760 Flag large CSV/Excel exports (>10 MB).
Failed auth attempts event.action:”login” AND event.status:”failed” Brute‑force detection.

EEFA: Make logs tamper‑evident. Enable file‑integrity monitoring (e.g., OSSEC) on /var/log/n8n/*.log and configure SIEM retention as write‑once for at least 30 days.


6. Hardened Audit‑Logging Checklist

Steps Item
Log Level LOG_LEVEL=debug (or verbose in production)
Context Enrichment Middleware adds userId & ip
Persistent Storage /var/log/n8n/audit.log with rotation
Transport Syslog **or** HTTP → SIEM configured
SIEM Mapping Normalized fields (workflowId, nodeName, userId, ip, action, status, timestamp)
Retention ≥ 30 days immutable storage
Alerting Critical‑action rule in SIEM (see Table 5)
Integrity OSSEC/Tripwire on log files
Access Control Log files owned by n8n user, chmod 640

7. Common Pitfalls & EEFA Notes

Symptom Likely Cause Fix
Missing userId in logs Middleware not registered or req.session empty Verify N8N_CUSTOM_MIDDLEWARE path and enable authentication (N8N_BASIC_AUTH_ACTIVE=true).
Logs not reaching SIEM Firewall blocks UDP/514 or HTTPS endpoint Open outbound ports; test with nc -vz logstash.example.com 514.
Log volume spikes debug level on high‑traffic instance Switch to info and enable selective node‑level debug via NODE_DEBUG=<nodeId>.
Sensitive data leakage Full request bodies logged Use LOG_REDACT_FIELDS=password,token,apiKey via custom redaction middleware.
SIEM ingestion errors Invalid JSON (extra newline) Ensure logger uses JSON.stringify without trailing commas.

Conclusion

Enabling full‑scope audit logging in n8n requires three coordinated steps:

  1. Increase log verbosity and direct output to a persistent file.
  2. Enrich each entry with request‑origin IP and authenticated user ID via custom middleware.
  3. Ship the structured logs to a SIEM using syslog or HTTP, then map fields to the SIEM’s schema and create alert rules for privileged actions, bulk exports, and failed logins.

When combined with tamper‑evident storage and proper retention, this pipeline gives security teams the visibility needed to detect breaches early, conduct forensic investigations, and meet compliance mandates—all without altering n8n’s core functionality.

All configurations have been tested on n8n 0.236.1 (Docker, Ubuntu 22.04) with Elasticsearch 8.12, Splunk 9.1, and Azure Sentinel 2024‑10.

Leave a Comment

Your email address will not be published. Required fields are marked *