Skip to content

Security and Privacy

Failed SSH logins by IP and user

kelora examples/sshd_auth.log --input-year 2024 \
  --filter 'e.msg.starts_with("Failed password")' \
  -e 'e.ip = e.msg.extract_ip(); e.user = e.msg.extract_regex("for (?:invalid user )?(\\S+)", 1)' \
  --freq ip --freq user
ip           (3 values):
  value          count
  203.0.113.77       4
  198.51.100.23      2
  192.0.2.200        1
user         (4 values):
  value   count
  root        3
  admin       2
  oracle      1
  test        1

Read JWT claims

parse_jwt() decodes a token without verifying the signature — for debugging, not for trusting:

kelora examples/auth-logs.jsonl \
  -e 'let t = e.token.parse_jwt(); e.sub = t.claims.sub; e.role = t.claims.role; e.expires = t.expires_at' \
  -k timestamp,sub,role,expires
timestamp='2024-01-15T10:00:00Z' sub='user123' role='admin'
  expires='2024-11-21T01:46:40+00:00'
timestamp='2024-01-15T10:05:00Z' sub='user456' role='user'
  expires='2024-11-21T02:46:40+00:00'
timestamp='2024-01-15T10:10:00Z' sub='user789' role='guest'
  expires='2023-11-14T22:13:20+00:00'
timestamp='2024-01-15T10:15:00Z' sub='user111' role='moderator'
  expires='2024-11-21T03:46:40+00:00'

Requests from one network

kelora examples/web_access.log --filter 'e.ip.is_in_cidr("198.51.100.0/24")' -k ip,path,status
ip='198.51.100.77' path='/api/reports' status=500
ip='198.51.100.88' path='/api/upload' status=413
ip='198.51.100.99' path='/api/analytics?date=2025-01-15&metric=views' status=200

Mask addresses inside free text

kelora examples/email_logs.log -f 'cols:ts level *msg' -e 'e.msg = e.msg.normalized(["email", "ipv4"])' -n 3
ts='2025-01-15T10:23:45Z' level='INFO'
  msg='Email sent from <email> to <email> subject="Welcome"'
ts='2025-01-15T10:24:12Z' level='INFO'
  msg='Email received from <email> to <email> subject="Support Request"'
ts='2025-01-15T10:24:33Z' level='WARN'
  msg='Bounced email to <email> reason="Domain not found"'

Consistent pseudonyms

The same input gives the same alias as long as KELORA_SECRET stays the same, so you can still count, join, and follow a user across files:

KELORA_SECRET=change-me kelora examples/user-data.jsonl \
  -e 'e.user = pseudonym(e.email, "user"); e.email = (); e.ip = e.ip.mask_ip(1)' -k user,action,ip
user='g8tM8VSw0JPXBMVPhDpsj0Zf' action='login' ip='192.168.1.0'
user='VBFT1D7bynhXWHogMn2-JsRh' action='purchase' ip='10.0.5.0'
user='MaUceTZy9kaE5V2HOavznCDY' action='view' ip='172.16.88.0'
user='Tq9oFjjc-1WvdC9mCHqAC5YQ' action='logout' ip='192.168.1.0'
user='4q0StVl3bHi6gqkOSXZzOA8f' action='login' ip='10.0.5.0'

Drop sensitive fields

-K token,password hides fields from the output; e.token = () in --exec removes them before later stages and summaries see them.