nikto Documentation

Perl repository by @sullo. Docker Compose & container deployment with 11k stars.

10,790 stars Perl Perl 1 file ยท ~4,175 tokens
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy nikto on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name nikto --restart always sullo/nikto:latest

File: README.md

nikto

Nikto web server scanner - https://cirt.net/Nikto2

Full documentation - https://github.com/sullo/nikto/wiki

Run normally:

text
git clone https://github.com/sullo/nikto
# Main script is in program/
cd nikto/program
# Run using the shebang interpreter
./nikto.pl -h http://www.example.com
# Run using perl (if you forget to chmod)
perl nikto.pl -h http://www.example.com

Run as a Docker container from Docker Hub:
docker pull hackllc/nikto:latest

Or from ghcr.io:
docker pull ghcr.io/sullo/nikto:latest

Run as a Docker container from Dockerfile:

bash
git clone https://github.com/sullo/nikto.git
cd nikto
docker build -t hackllc/nikto .
# Call it without arguments to display the full help
docker run --rm hackllc/nikto
# Basic usage
docker run --rm hackllc/nikto -h http://www.example.com
# To save the report in a specific format, mount /tmp as a volume:
docker run --rm -v $(pwd):/tmp hackllc/nikto -h http://www.example.com -o /tmp/out.json

Basic usage:

text
Options:
       -Add-header         Add HTTP headers (can be used multiple times, one per header pair)
       -ask+               Whether to ask about submitting updates
                               yes   Ask about each (default)
                               no    Don't ask, don't send
                               auto  Don't ask, just send
       -check6             Check if IPv6 is working (connects to ipv6.google.com or value set in nikto.conf)
       -Cgidirs+           Scan these CGI dirs: "none", "all", or values like "/cgi/ /cgi-a/"
       -config+            Use this config file
       -Display+           Turn on/off display outputs:
                               1     Show redirects
                               2     Show cookies received
                               3     Show all 200/OK responses
                               4     Show URLs which require authentication
                               D     Debug output
                               E     Display all HTTP errors
                               P     Print progress to STDOUT
                               S     Scrub output of IPs and hostnames
                               V     Verbose output
       -dbcheck           Check database and other key files for syntax errors
       -evasion+          Encoding technique:
                               1     Random URI encoding (non-UTF8)
                               2     Directory self-reference (/./)
                               3     Premature URL ending
                               4     Prepend long random string
                               5     Fake parameter
                               6     TAB as request spacer
                               7     Change the case of the URL
                               8     Use Windows directory separator (\)
                               A     Use a carriage return (0x0d) as a request spacer
                               B     Use binary value 0x0b as a request spacer
        -followredirects   Follow 3xx redirects to new location
        -Format+           Save file (-o) format. Can specify multiple formats separated by commas (e.g., htm,sql,txt,json,xml):
                               csv   Comma-separated-value
                               json  JSON Format
                               htm   HTML Format
                               sql   Generic SQL (see docs for schema)
                               sqld  SQL Direct (directly inserts into MySQL/PostgreSQL database)
                               txt   Plain text
                               xml   XML Format
                               (if not specified the format will be taken from the file extension passed to -output)
                               Note: sqld format requires DB_TYPE, DB_HOST, DB_PORT, DB_NAME in nikto.conf
                                     and NIKTO_DB_USER, NIKTO_DB_PASS environment variables
       -Help              This help information
       -host+             Target host/URL
       -id+               Host authentication to use, format is id:pass or id:pass:realm
       -ipv4              IPv4 Only
       -ipv6              IPv6 Only
       -key+              Client certificate key file
       -list-plugins      List all available plugins, perform no testing
       -maxtime+          Maximum testing time per host (e.g., 1h, 60m, 3600s)
       -mutate+           Guess additional file names:
                               1     Test all files with all root directories
                               2     Guess for password file names
                               3     Enumerate user names via Apache (/~user type requests)
                               4     Enumerate user names via cgiwrap (/cgi-bin/cgiwrap/~user type requests)
                               5     Attempt to brute force sub-domain names, assume that the host name is the parent domain
                               6     Attempt to guess directory names from the supplied dictionary file
       -mutate-options    Provide information for mutates
       -nocheck           Don't check for updates on startup
       -nocookies         Do not use cookies from responses in requests (cookies are stored and sent by default)
       -nointeractive     Disables interactive features
       -nolookup          Disables DNS lookups
       -noslash           Strip trailing slash from URL (e.g., '/admin/' to '/admin')
       -nossl             Disables the use of SSL
       -no404             Disables nikto attempting to guess a 404 page
       -Option            Over-ride an option in nikto.conf, can be issued multiple times
       -output+           Write output to this file ('.' for auto-name)
       -Pause+            Pause between tests (seconds)
       -Platform+         Platform of target (nix, win, all)
       -Plugins+          List of plugins to run (default: ALL)
       -port+             Port to use (default 80)
       -RSAcert+          Client certificate file
       -root+             Prepend root value to all requests, format is /directory
       -Save              Save positive responses to this directory ('.' for auto-name)
       -ssl               Force ssl mode on port
       -Tuning+           Scan tuning:
                               1     Interesting File / Seen in logs
                               2     Misconfiguration / Default File
                               3     Information Disclosure
                               4     Injection (XSS/Script/HTML)
                               5     Remote File Retrieval - Inside Web Root
                               6     Denial of Service
                               7     Remote File Retrieval - Server Wide
                               8     Command Execution / Remote Shell
                               9     SQL Injection
                               0     File Upload
                               a     Authentication Bypass
                               b     Software Identification
                               c     Remote Source Inclusion
                               d     WebService
                               e     Administrative Console
                               x     Reverse Tuning Options (i.e., include all except specified)
       -timeout+          Timeout for requests (default 10 seconds)
       -Userdbs           Load only user databases, not the standard databases
                               all   Disable standard dbs and load only user dbs
                               tests Disable only db_tests and load udb_tests
       -useragent         Force User-Agent instead of pulling from database
       -url+              Target host/URL (alias of -host)
       -useproxy          Use the proxy defined in nikto.conf, or argument http://server:port
       -Version           Print plugin and database versions
       -vhost+            Virtual host (for Host header)
       -404code           Ignore these HTTP codes as negative responses (always). Format is "302,301".
       -404string         Ignore this string in response body content as negative response (always). Can be a regular expression.
            + requires a value

Nikto DSL Matchers

Nikto's test database supports a mini-DSL for matching responses. The following matchers are supported:

  • BODY: and !BODY: โ€” Match or exclude content in the response body.
  • HEADER: and !HEADER: โ€” Match or exclude content in HTTP headers.
  • COOKIE: and !COOKIE: โ€” Match or exclude content in HTTP cookies. (NEW)
  • CODE: and !CODE: โ€” Match or exclude HTTP status codes.

You can combine multiple matchers with && (AND). Example:

text
BODY:login&&!BODY:logout&&HEADER:X-Powered-By&&COOKIE:sessionid

This will match if the response body contains "login", does not contain "logout", the headers include "X-Powered-By", and a cookie named "sessionid" is present.

License

Copyright (C) 2001โ€“2026 Chris Sullo. All rights reserved.

This license notice applies to: Nikto's code only

See COPYING.LibWhisker for LibWhisker licensing information.

Database files are NOT licensed under the GPL and may only be distributed as part of the official Nikto package or installer, for use exclusively with Nikto.

For full licensing terms and commercial use policies, visit:
https://cirt.net/Nikto-Licensing

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

The full license text is available at: https://www.gnu.org/licenses/gpl-3.0.txt

See COPYING for the complete license notice.


File: .github/FUNDING.yml

patreon: sullo


File: .github/ISSUE_TEMPLATE/bug_report.md


name: Bug Report
about: Report an issue found in Nikto
title: 'Bug: '
labels: bug
assignees: ''


Expected behavior

Actual behavior

Steps to reproduce

Nikto version

Run:

text
./nikto.pl -Version

and paste the output here.

Further technical info

E.g. you can obtain Nikto debug output by running -D D and redirecting to a file.
You may also scrub the output of hostnames and IPs by specifying -D DS.


File: .github/ISSUE_TEMPLATE/config.yml

blank_issues_enabled: false


File: .github/ISSUE_TEMPLATE/false_positive_negative_report.md


name: False positive / negative Report
about: Report a false positive / negative found by Nikto
title: 'False Positive/Negative: '
labels: bug
assignees: ''


Output of suspected false positive / negative

Post any useful information like the ID of the test causing the false positive.

Debug output

Run:

text
./nikto.pl -host targethost -Save false_positive

This saves all positive responses to a new false_positive directory. Afterwards look
for the related ID of the false positive / negative and paste it below.


File: .github/ISSUE_TEMPLATE/FeatureRequest.md


name: Feature Request
about: Request a new feature for Nikto
title: 'Feature: '
labels: 'enhancement'
assignees: ''


Description


File: .github/ISSUE_TEMPLATE/TestRequest.md


name: New Test
about: Reqeust a new test in Nikto
title: 'Test Request: '
labels: 'check'
assignees: ''


Description

Path

Matching text (in response)


File: .github/workflows/docker-build-push.yaml

name: Build and Push Docker Image

on:
push:
branches:
- main
tags:
- 'v*'
- '..*' # e.g. 2.6.1 (Nikto release tags omit the leading v)
workflow_dispatch:

permissions:
contents: read
packages: write

jobs:
build-and-push:
runs-on: ubuntu-latest

text
steps:
  - name: Checkout repository
    uses: actions/checkout@v4

  - name: Set up Docker Buildx
    uses: docker/setup-buildx-action@v3

  - name: Log in to GitHub Container Registry
    uses: docker/login-action@v3
    with:
      registry: ghcr.io
      username: ${{ github.actor }}
      password: ${{ secrets.GITHUB_TOKEN }}

  - name: Log in to Docker Hub
    uses: docker/login-action@v3
    with:
      username: ${{ secrets.DOCKERHUB_USERNAME }}
      password: ${{ secrets.DOCKERHUB_TOKEN }}

  - name: Extract metadata for Docker
    id: meta
    uses: docker/metadata-action@v5
    with:
      images: |
        hackllc/nikto
        ghcr.io/${{ github.repository_owner }}/nikto
      flavor: |
        latest=false
      tags: |
        # Every master commit โ†’ floating "rolling" (+ sha for pin-by-commit)
        type=raw,value=rolling,enable={{is_default_branch}}
        type=sha,enable={{is_default_branch}}
        # Manual test runs on a branch โ†’ "test" tag only
        type=raw,value=test,enable=${{ github.event_name == 'workflow_dispatch' && github.ref_type != 'tag' }}
        type=sha,enable=${{ github.event_name == 'workflow_dispatch' && github.ref_type != 'tag' }}
        # Tagged releases โ†’ pinned versions (+ latest = newest release)
        type=semver,pattern={{version}}
        type=raw,value=latest,enable=${{ github.ref_type == 'tag' }}

  - name: Build and push Docker image
    uses: docker/build-push-action@v5
    with:
      context: .
      file: Dockerfile
      push: true
      platforms: linux/amd64,linux/arm64
      tags: ${{ steps.meta.outputs.tags }}
      labels: ${{ steps.meta.outputs.labels }}

File: .github/workflows/update-worker-manifest.yml

name: Update build timestamp + manifest

on:
push:
branches: ["main"]
# Prevent infinite loops: the commit that only updates program/.timestamp
# will NOT trigger this workflow.
paths-ignore:
- "program/.timestamp"

permissions:
contents: write

jobs:
update:
# Extra safety: don't run if somehow triggered by the bot anyway
if: github.actor != 'github-actions[bot]'
runs-on: ubuntu-latest

text
steps:
  - name: Checkout
    uses: actions/checkout@v4
    with:
      fetch-depth: 1

  - name: Compute epoch + parse Nikto version
    id: meta
    shell: bash
    run: |
      set -euo pipefail

      EPOCH="$(git log -1 --format=%ct)"
      echo "epoch=$EPOCH" >> "$GITHUB_OUTPUT"

      # Parse Nikto version from: $VARIABLES{'version'} = "2.6.0";
      VERSION="$(perl -ne 'if(/\$VARIABLES\{\s*["'\''"]version["'\''"]\s*\}\s*=\s*["'\''"]([^"'\''"]+)["'\''"]\s*;/){print $1; exit}' program/nikto.pl)"

      if [ -z "${VERSION:-}" ]; then
        echo "Failed to parse version from program/nikto.pl (\$VARIABLES{version})." >&2
        exit 1
      fi

      echo "version=$VERSION" >> "$GITHUB_OUTPUT"

  - name: Update program/.timestamp
    shell: bash
    run: |
      set -euo pipefail
      mkdir -p program
      echo "${{ steps.meta.outputs.epoch }}" > program/.timestamp

  - name: Commit and push program/.timestamp if changed
    shell: bash
    run: |
      set -euo pipefail

      # Stage first so new files are included
      git add program/.timestamp

      # If staging produced no changes, exit
      if git diff --cached --quiet; then
        echo "program/.timestamp unchanged"
        exit 0
      fi

      git config user.name "github-actions[bot]"
      git config user.email "github-actions[bot]@users.noreply.github.com"
      git commit -m "chore: update program/.timestamp [skip ci]"
      git push

  - name: Update Cloudflare Worker manifest
    shell: bash
    env:
      UPDATE_URL: ${{ secrets.CF_WORKER_UPDATE_URL }}
      UPDATE_TOKEN: ${{ secrets.CF_WORKER_UPDATE_TOKEN }}
      VERSION: ${{ steps.meta.outputs.version }}
      EPOCH: ${{ steps.meta.outputs.epoch }}
    run: |
      set -euo pipefail

      if [ -z "${UPDATE_URL:-}" ] || [ -z "${UPDATE_TOKEN:-}" ]; then
        echo "Missing CF_WORKER_UPDATE_URL or CF_WORKER_UPDATE_TOKEN secrets." >&2
        exit 1
      fi

      curl -fsS -X POST "$UPDATE_URL" \
        -H "Authorization: Bearer $UPDATE_TOKEN" \
        -H "Content-Type: application/json" \
        -d "{\"version\":\"$VERSION\",\"epoch\":$EPOCH}"