Hackly

Authorized attack-surface
scanning — with ownership gates.

Inventory targets you own, verify DNS ownership, scan linked GitHub repositories (Laravel/PHP-focused SAST & SCA), and review findings from a Filament admin panel. Built with Laravel 13 and Filament 5.

Hackly overview: open findings by severity, new issues per day, issues by scanner and recent scans

Demo workspace · every name, domain and finding is fictional

Product tour

From “is it ours?”
to “it’s fixed”.

A calm, focused dashboard for the whole loop: verify ownership, scan, triage, re-scan. Click any screenshot to zoom in.

Triage findings, not noise.

Every scanner reports into one list, ranked High → Low, with the asset it belongs to.

  • Open, Acknowledged, Fixed and False positive tabs — a false positive needs a note
  • Copy the finding as Markdown or as a prompt for an AI
  • Optional public link, long and unguessable, that you can turn off
  • Regressions reopen automatically
  • Passed checks hidden until you ask for them
Findings list with severity, asset, source and status

Context in one click.

Open a finding in a slide-over: where it lives, which scan saw it last, CVE links, PHP reachability and readable evidence.

  • Reachable vs. unreachable dependencies
  • Noise annotations explained
  • Triage straight from the panel
Finding detail slide-over with evidence and triage actions

Watch scans run live.

Each scanner is its own queued job. Progress, duration and results update in place.

  • Skipped tasks tell you which binary is missing
  • Warning when no queue worker picks up jobs
  • Cancel, run again, export PDF or Markdown
  • In-app notification when your scan finishes
Running scan with live task timeline

Ownership first. Always.

No DNS verification, no scan. Hackly shows the exact TXT record to publish — with copy buttons — and checks it for you.

  • Tokens are stable: reopening never invalidates a published record
  • Optional allowlist and private-IP blocking
  • Authorization reference stored with each target
Guided DNS TXT ownership verification
New scan dialog with profiles

Profiles that explain themselves

Quick, Standard or Deep — each one lists what it runs.

Targets with open issues

Every asset at a glance

Open issues, ownership and last scan for each target and repository.

Repository page

Repositories, too

Semgrep, Trivy, Gitleaks, Checkov, Composer audit & outdated and Laravel checks.

Scanner health page

Scanner health

Which tools the worker can run, queue state and every safety limit.

Dashboard in dark mode

Designed dark mode

Every view — charts included — works in light and dark.

Sign-in page

Locked down

Authenticator-app or email two-factor, recovery codes, encrypted tokens.

Coverage

Targets and repos.
Same control plane.

DAST for verified targets, SAST/SCA for GitHub clones, a penetration test that reuses that DNS check, and compliance packs scored from those scans. Link a domain to its repository and Hackly treats them as one application.

Target scanners

01 DNS / WHOIS dig + whois — records, DNSSEC, CAA, zone transfer and wildcards. quick · standard · deep
02 Mail & TLS SPF, DKIM, DMARC, MTA-STS, TLS-RPT, and the certificate on the domain. quick · standard · deep
03 Port scan nmap top ports with light service detection. quick · standard · deep
04 Tech fingerprint Soft HTTP checks for PHP/Laravel headers, cookies, CORS and debug pages. quick · standard · deep
05 Subdomains & origin Wordlist plus Certificate Transparency. Standard and deep also check whether the origin answers directly, past the edge. standard · deep
06 Path discovery Soft wordlist / Nuclei, plus routes learned from a linked repository. Sensitive paths such as .env and Telescope are findings. Ordinary pages are not. standard · deep
07 Nuclei templates OWASP + PHP/Laravel/dotenv vulnerability templates via nuclei. standard · deep
08 OWASP ZAP DAST Baseline DAST for deep profile — longer timeout, cooldown enforced. deep
09 Penetration test A new DNS TXT every run, then the whole host: Nuclei, ZAP, nikto and wpscan, declared API, logins and ports, plus a deep scan of each linked repository. The scanner IP is shown so it can be allowlisted. WPScan does not guess passwords. engagement

Repository scanners

Clone via PAT → run profile tasks → dedupe, PHP reachability, and noise filters.

01 Semgrep SAST PHP ruleset (p/php) on the shallow clone. standard · deep
02 Trivy SCA Dependency vulnerabilities from lockfiles and images. standard · deep
03 Gitleaks Secret detection across the repository history snapshot. quick · standard · deep
04 Checkov IaC Docker / Terraform / GitHub Actions — skipped when none present. deep
05 Composer + OSV composer audit and OSV CVE lookup when composer.lock exists. quick · standard · deep
06 Composer outdated Dependency health from composer.lock: abandoned packages, direct dependencies a major behind, Laravel out of security support. standard · deep
07 Laravel PHP audit Committed .env, debug packages, Telescope/Horizon hints, mass-assignment risks. quick · standard · deep
08 Checkpoint All 30 Checkpoint checks: Composer and npm CVEs, secrets, SQLi, XSS, CSRF, SSRF, XXE, mass assignment, sessions, supply chain, outdated and abandoned packages. quick · standard · deep
09 Laravel live pentest HTTP probes on linked Targets when “Also deep-scan linked targets” is on. standard · deep

Install

Up in minutes.

PHP 8.3+, Composer, and SQLite (or MySQL / PostgreSQL). A queue worker must be running for scans to execute.

Terminal — bootstrap
composer install
cp .env.example .env
php artisan key:generate
touch database/database.sqlite
php artisan migrate --seed

# optional: fictional demo workspace to explore
php artisan db:seed --class=DemoSeeder
Terminal — run
# serve + queue + logs + vite
composer run dev

# or separately:
php artisan serve
php artisan queue:work  # required
php artisan schedule:work  # cleanup, Sunday digest, daily tool databases
01

Open the app

Visit / — seeded as admin@hackly.test / password. Change it immediately and turn on two-factor authentication.

02

Add a target or a repo

The dashboard checklist walks you through it: add a domain and verify it via DNS TXT, and/or add a read-only GitHub token and register owner/repo.

03

Scan, then triage

Target DAST, repository SAST / SCA, or both via a linked app. A penetration test uses the target's existing DNS verification. Compliance scores what those scans already found. Work the Findings list from High to Low.

Documentation

Reference

Targets, repositories, how a link between them changes DAST and penetration tests, compliance scope, profiles, CLI, the ownership-first security model, and an honest look at Aikido, Detectify and the tools around them.

Overview

Hackly is an orchestration layer for authorized attack-surface and application security scanning. You inventory targets, prove ownership, scan GitHub repositories via PAT, run soft rate-limited jobs, and review normalized findings in Filament.

Architecture
Target (DNS-verified)               Repository (GitHub PAT)
   │                                      │
   ├─ link, from either side or a pentest ┤
   │                                      │
   ├─ Scan (DAST)                         ├─ RepoScan
   │    uses routes from the last clone   │    remembers those routes
   ├─ Penetration test                    │
   │    standing DNS + deep linked scan   │
   └─ Compliance subject                  └─ same line when the two are linked

Jobs use the database queue (no Horizon). A queue worker must be running for scans to execute. Linking is optional — each side can still be scanned on its own. When you do link them, DAST, penetration tests and compliance use the pair.

Compared with other tools

Hackly is a self-hosted orchestrator for the domains and GitHub repositories a Laravel team already operates. Aikido, Detectify, Snyk, Semgrep, GitHub Advanced Security and DefectDojo overlap with it and then diverge. This is a fit comparison, written from Hackly's side. It is not a scan-off. The commercial products move faster than this page.

Read against the public pages in October 2026: Aikido's platform, Aikido pricing, and Detectify. Modules and plan limits change. Those pages say what a subscription includes today.

Aikido

Aikido is a commercial application-security platform. One product covers SAST across major languages, dependency scanning with reachability, secrets, malware and license risk in open source, infrastructure as code, containers, cloud posture, dynamic testing including authenticated DAST, API discovery and fuzzing, attack-surface monitoring, AI pentesting, autofix pull requests, and runtime protection. There is a free tier. Local scanning and a full on-prem deployment exist on paid and government plans. The default is hosted: Aikido clones repositories into short-lived environments, scans them, and throws the clone away.

On the things that make a security platform, Aikido is ahead. It covers languages a PHP ruleset and a set of Laravel checks do not. It opens a pull request with a proposed fix. Hackly can copy a finding as a prompt, and the repository stays as it was. Aikido looks at cloud accounts, Kubernetes, containers and runtime traffic. Hackly does not see AWS, GCP, Azure or a cluster. Authenticated DAST and API fuzzing are products there. A Hackly penetration test can submit one declared test account, once, on a host whose target is already DNS-verified. Aikido reports inside CI. Hackly runs when someone starts a scan: there is no pull-request check and no recurring scan schedule.

Noise handling is smaller here on purpose. Findings are deduplicated across tools, some unreachable PHP dependencies are marked, and placeholder secrets are dropped. That is a heuristic for Laravel apps, not a general false-positive engine. Aikido advertises aggressive noise reduction. This page does not repeat that as a measured result.

Part of Aikido's surface testing is Nuclei-based. Hackly runs Nuclei too, along with nmap, OWASP ZAP, Nikto and WPScan. The engines are not the difference. The difference is everything wrapped around them, and whose machine the job runs on.

Hackly is the tighter fit when the findings have to stay on a server you administer and the apps are Laravel. The license is MIT. Findings, GitHub tokens and raw scanner output stay there. You pay with the host, the binaries and a queue worker. Every domain scan waits for a DNS TXT record that proves control of that name. Aikido's attack-surface module watches assets you connect. Hackly refuses a hostname you cannot publish DNS for. That gate is the reason the tool exists, and it is a limitation when the asset is a tenant you do not control.

Repository scanning is aimed at PHP and Laravel: Composer audit, OSV, abandoned packages, Laravel outside security support, the Checkpoint checks, Semgrep with p/php, Trivy and Gitleaks. A Python or Go monorepo gets a thin result. The external scan is rate-limited on purpose, so a deep run is slow. Aikido's hosted DAST is faster to turn on, and nobody installs ZAP.

The compliance pages score evidence from findings Hackly already stored. They are a worksheet for an auditor. They are not a certification, and they do not collect policies, vendors or access reviews. Aikido is not that product either.

Detectify

Detectify is a hosted attack-surface and application-testing platform. Surface Monitoring keeps a map of domains, subdomains, addresses, technologies and ports, and tests what it finds. Application Scanning is authenticated DAST, with crawling and payload fuzzing. API Scanning covers REST and GraphQL. Internal Scanning reaches systems off the public internet. PCI ASV scanning is an approved-scanning-vendor test for PCI DSS. The payloads come from Detectify's research and a crowdsourced community of hackers, including a large catalogue of subdomain-takeover checks. They say most of what they report never receives a CVE. That is their research claim. Hackly has not reproduced it.

If the job is the public internet, watched continuously, with payloads written by people who look for bugs, Detectify is the specialist. Hackly is not in that race. Subdomain discovery here is a wordlist, certificate-transparency logs and takeover fingerprints. Nothing watches for a new hostname appearing tomorrow, and nothing fuzzes an API the way a dedicated engine does. A penetration test is one authorized run, with one login, then a cooldown. Detectify's application scanning is built to keep going, authenticated, across the surface.

Detectify does not take the repository half of this app. There is no Semgrep, Trivy, Gitleaks or Composer audit in that product, and no Laravel-specific code checks. The service runs on their side. Hackly's PCI DSS page is one of the evidence packs in Compliance. It is not an ASV scan, and a bank that asked for an ASV will not accept it. Use Detectify, or another ASV, when that is the requirement.

The two can sit side by side. Detectify on the public surface you want watched every day. Hackly on the GitHub repository, and on the hosts where you can prove DNS and you want the raw Nuclei, ZAP and Composer output on your own disk. Intruder and Probely sit in the same hosted-external neighbourhood: someone else's payloads, no Laravel SAST.

Choosing between Aikido and Detectify is a separate question. Aikido is the wide platform, from the pull request to the cloud account. Detectify is the external-testing specialist. Hackly is the small self-hosted one. A team that already pays for one of the first two can still want the property Hackly actually has: the scanner output, and the GitHub token, stay on a machine they run.

The rest of the neighbourhood

Tool What it is for Ahead of Hackly Where Hackly still fits
Aikido Hosted platform from code through cloud to runtime. Free tier, paid modules, on-prem on higher plans. Many languages, autofix pull requests, cloud and containers, authenticated DAST, API fuzzing, CI. Your own server, a hard DNS ownership gate, a Laravel and PHP stack you can read.
Detectify Hosted continuous attack surface, authenticated DAST, API fuzzing, PCI ASV. Asset discovery, payload research, subdomain takeover, testing that keeps running. Repository scanning, a self-hosted history, scans that cannot start without DNS proof.
Snyk Commercial developer security: dependencies, SAST, containers, IaC, licenses, fix pull requests. Remediation across package ecosystems, and a workflow developers already live in. Analysis runs at Snyk unless you put a broker in front. Ports, TLS, mail and ZAP against a host you verified. Snyk is a poor substitute for that. Hackly is a poor substitute for Snyk's fix pull requests.
Semgrep SAST, secrets and supply chain, with custom rules and pull-request comments. The rules, the assistant, and languages other than PHP. Hackly shells out to the Semgrep CLI. Semgrep is one task inside a scan that also runs ZAP, Nuclei and Composer. Pointing HACKLY_SEMGREP_CONFIG at another ruleset does not turn this app into Semgrep's platform.
GitHub Advanced Security CodeQL, Dependabot, secret scanning and push protection, on the pull request. The merge gate, with no extra server to run. It does not probe the deployed host or store a DNS ownership check. The host you operate. Hackly never posts a check on the pull request. Using both is a coherent setup: GitHub on the merge, Hackly on the domain.
SonarQube Quality gate and security hotspots. A self-hosted edition exists. Blocking a build, code quality, and broader language support. Anything about the running site: ports, mail, TLS, Nuclei, ZAP. SonarQube has none of that picture.
DefectDojo Open-source system of record. Imports from many scanners, with engagements, SLAs and client reports. Tracking a pentest program over years. It will not verify DNS and then run this pipeline. The scan itself. Triage here is four states and a note, which is enough for one team and thin for a consultancy.

What this page will not pretend

  • Hackly orchestrates nmap, Nuclei, ZAP, Nikto, WPScan, Semgrep, Trivy, Gitleaks, Checkov and Composer. Those projects own the detection. Hackly owns the queue, the history, triage that survives the next scan, the link between a domain and a repository, and the DNS gate.
  • A one-off Nuclei run does not need this application installed.
  • A human penetration test, a GRC suite, a WAF and a cloud-posture product remain separate purchases. The compliance score is not any of those.
  • SAST here is PHP-shaped. Semgrep starts from p/php. Checkpoint and the Laravel checks assume a Laravel tree. Other stacks are second-class, and saying otherwise would be advertising.

Requirements

  • PHP 8.3+
  • Composer
  • SQLite (default) or MySQL / PostgreSQL
  • git (for repository clones)
  • Node.js (optional — only for the Vite dev server; panel styles are plain CSS)
Default admin after seed: / · admin@hackly.test · password

Scanner binaries

Target scanners

Optional but recommended. Without them, related tasks fail gracefully and surface missing-binary errors in the scan UI.

Binary Used for
dig, whois DNS / WHOIS
nmap Ports
nuclei Templates & path discovery
zap.sh Deep DAST, and a longer pass in a penetration test
nikto Web-server checks in a penetration test. The task is skipped when the binary is missing
wpscan WordPress version, plugins, themes and known vulnerabilities. No password guessing. Skipped when missing. HACKLY_WPSCAN_API_TOKEN is optional and only loads vulnerability data
Ubuntu — target tools
sudo bash scripts/install-scanner-binaries-ubuntu.sh
php artisan hackly:check-binaries

Repository scanners

Needed for GitHub repo scanning. Missing tools cause those tasks to be skipped (other tasks still run). Composer/OSV and Hackly Laravel auditors do not require Semgrep/Trivy.

Binary Used for
semgrep PHP SAST
trivy SCA
gitleaks Secrets
checkov IaC
composer composer audit, composer outdated
Ubuntu — repo tools
sudo bash scripts/install-repo-scanners.sh
php artisan hackly:check-binaries
Run hackly:check-binaries as the queue worker user (e.g. www-data). The install script puts tools on /usr/local/bin so they are not trapped in a root-only ~/.local.

Targets

Admin UI

  1. Targets → Add target — enter a domain (a pasted URL is normalized)
  2. Publish the TXT record shown on the target page at your DNS provider
  3. Check DNS — once the token is found the target is unlocked
  4. Start scan — pick a profile. Also scan linked repositories is already on when a repository is linked
  5. Follow progress live on the scan page; triage its findings or export a PDF / Markdown report
  6. The target page groups Findings, Scans and Linked repositories

The DNS dialog shows the scanner IP. Allowlist it if the host drops unknown clients. Set HACKLY_EGRESS_IP when the worker cannot detect its own address. Targets do not need a linked repository.

CLI

Terminal
php artisan hackly:scan example.com --profile=standard
php artisan hackly:scan example.com --include-repos

Repositories

Admin UI

  1. Settings → GitHub tokens → Add token (or create one inline while adding a repository)
  2. Repositories → Add repository — owner/repo or a github.com URL, checked against the GitHub API
  3. Link the Targets where this code is deployed. The same link appears in compliance as one line, and a penetration test scans that code with the host
  4. Scan now — pick a profile. Also deep-scan linked targets is already on when a linked target is verified (DAST plus live Laravel probes)
  5. Review findings and scan history on the repository page; export reports from any scan

Repository findings belong to the repository, not to a target, so a repository can be scanned without any linked domain.

GitHub token permissions

Type Permission
Classic PAT repo (private) or public_repo (public only)
Fine-grained Contents: Read + Metadata: Read on selected repos

Post-processing

  • Cross-tool deduplication (e.g. same package + CVE from Trivy and OSV → one finding)
  • PHP reachability: namespace usage in app/, routes/, config/; require-dev → unreachable; Laravel package auto-discovery
  • Noise filters: placeholder secrets, path out of app scope, configurable rule suppressions
  • Findings store reachability, confidence, noise_filtered, and tools[]

CLI

Terminal
php artisan hackly:repo-scan owner/repo --profile=standard
php artisan hackly:repo-scan owner/repo --include-targets

Penetration tests

Attack surface → Penetration tests is an engagement, not a profile on Start scan. The target must already be DNS-verified and active. That standing check is the authorization: start the test without publishing another TXT record, and without asking anyone to change DNS for this run. A fresh hackly-pentest= record is only required when the target is not already verified. That extra token lasts HACKLY_PENTEST_AUTH_MINUTES (30) and is consumed when the test starts. There is a cooldown of HACKLY_PENTEST_COOLDOWN_HOURS (6) per target.

The authorization screen shows the scanner IP (the same address as the ordinary DNS check). Allowlist it. Set HACKLY_EGRESS_IP if this server should not look the address up itself.

What you can declare

  • Technology: Laravel, PHP, WordPress, Drupal, Django, Rails, Spring, ASP.NET, Node, Next.js, or mixed
  • Swagger / OpenAPI URL, login areas, other URLs, and extra ports. Every URL must stay on the authorized host
  • One test account. Hackly posts that form once and reviews the session cookie. It does not guess passwords
  • Notes, how authentication works, and what is out of scope

What always runs

The declared URLs are extra. The run still covers the whole origin: tech fingerprint, path discovery, TLS, technology surface, the OpenAPI document, the login pages, a fixed professional port set plus the ports you named, Nuclei across Laravel, PHP, frontends, Apache, Nginx and WordPress, WPScan, Nikto, and a longer OWASP ZAP pass. Missing wpscan or nikto skips that task. WPScan is forced only when the technology is WordPress, and it never receives a password list.

API: create the engagement, then POST …/run when the target is already DNS-verified. POST …/authorization and POST …/authorization/check are the fallback for a target that has not passed that check. The payload includes scanner_ip.

Compliance

Security → Compliance scores evidence from scans you already ran. It is not a certification, an attestation, or a legal opinion. A control Hackly cannot observe is out of scope, not a pass.

The posture score starts at 100. Open highs, acknowledged highs, open mediums and lows, unverified targets, and a workspace with assets but no completed scan in 30 days each reduce it. The method is printed on the page and in the report.

Scope

All is the whole workspace. Every other line is one subject:

  • a target with no repository, shown as the domain
  • a repository with no target, shown as owner/repo
  • a linked pair, shown as shop.example.com + acme/shop

The grade, the framework cards and the PDF / Markdown downloads follow that line. A pair includes findings on the domain and findings on that repository.

Packs

DORA, SOC 2, NIS2, ISO/IEC 27001, PCI DSS, GDPR, NIST CSF 2.0, OWASP Top 10, CIS Controls v8, HIPAA, Cyber Essentials, and the Essential Eight. Each control is met, partial, a gap, not assessed, or out of scope. API ids: dora, soc2, nis2, iso-27001, pci-dss, gdpr, nist-csf, owasp-top-10, cis-v8, hipaa, cyber-essentials, essential-eight.

API query subject on /api/v1/posture, /api/v1/compliance and the report routes. Omit it for everything. Otherwise target:{uuid}, repository:{uuid}, or pair:{targetUuid}:{repositoryUuid}. An unknown or unlinked pair is 404.

Findings & triage

Findings collects every issue from target and repository scans, ranked High → Low. Passed checks are recorded too but hidden unless you enable the Passed checks filter. Click a row to open it in a slide-over and triage it, or select many rows and triage them in bulk.

StatusMeaning
OpenReported and not triaged yet
AcknowledgedSomeone owns it — still listed under “Needs attention” on the dashboard
FixedMarked by you; target findings are also closed automatically when a later scan of the same checks no longer reports them
False positiveDismissed, with a required note that stays on the finding. Re-detection keeps it dismissed
A Fixed finding that is detected again is reopened automatically, so regressions surface on their own. Each scan also keeps a snapshot of its own High / Medium / Low counts, so history stays accurate after re-scans.

On the finding, Copy Markdown puts every detail on the clipboard (severity, subject, evidence, and the false-positive note). Copy AI prompt wraps that same write-up in a request for a root cause, a fix, and how to verify it. Share link publishes a read-only page at /f/ plus 40 random characters. Unshare and the old address stops working. The public page can also be fetched as ?format=markdown or ?format=prompt.

Weekly digest

Every Sunday at 08:00 (timezone from HACKLY_DIGEST_TIMEZONE, otherwise the app timezone) Hackly emails every user a digest of the last seven days: posture grade, open findings by severity, what is new, what was fixed or dismissed (with the false-positive note), failed scans, and the situations around the workspace — unverified targets, paused assets, and anything without a completed scan in 30 days. The same snapshot is in the panel notification bell and at GET /api/v1/digest.

The scheduler has to be running. Preview without sending mail:

Terminal
php artisan hackly:digest --dry-run

API

Personal access tokens live on Profile. Each user sees only their own tokens. Send Authorization: Bearer hk_…. Abilities are * (full, can mint tokens), write (changes, and reads), and read. The interactive reference is the API docs, and a running app serves the same spec at /api/docs. Compliance and posture accept subject. Penetration tests are their own resources: create, authorize, check the TXT, then run. scanner_ip is the address to allowlist.

Issue a token from the shell when you do not want to open the panel:

Terminal
php artisan hackly:token you@example.com --ability=read

Independent scan modes

Goal UI CLI
Target only Start scan (toggle off) hackly:scan example.com
Target + repos Also scan linked repositories (on when linked) hackly:scan … --include-repos
Repo only Scan now (toggle off) hackly:repo-scan owner/repo
Repo + targets Also deep-scan linked targets (on when verified) hackly:repo-scan … --include-targets
Penetration test Penetration tests. Start when the target is already verified POST /api/v1/penetration-tests/{id}/run

Laravel live pentest runs only when the repo scan includes linked targets. Repo-only scans skip it. A penetration test’s linked repository scan is a deep code scan and does not start that live probe again.

Scan profiles

Target (DAST)

Profile Tasks
quick dns_info, mail_security, tls_check, port_scan, tech_fingerprint
standard + subdomain_enum, origin_exposure, path_discovery, nuclei_owasp
deep + zap_baseline (cooldown between deep runs on the same target)

Repository (SAST / SCA)

Profile Tasks
quick gitleaks_secrets, composer_osv, laravel_php_audit, checkpoint
standard + semgrep_sast, trivy_sca, composer_outdated, laravel_live_pentest*
deep + checkov_iac

* Live pentest only when linked targets are included. checkpoint runs on every repository profile and records each of the 30 Checkpoint checks. Findings are normalized to LOW / MEDIUM / HIGH.

Penetration test

Not listed on Start scan. Tasks: tech_fingerprint, path_discovery, tls_check, pentest_surface, pentest_api, pentest_login, pentest_ports, nuclei_pentest, wpscan, nikto, zap_pentest, plus a deep repository scan for each linked repository.

Commands

Scans are started manually from the admin UI or CLI — there is no automatic hourly/nightly scan schedule.

Command Purpose
hackly:check-binaries Verify target + repo scanner binaries
hackly:scan {target} Target scan (--profile=, --include-repos)
hackly:repo-scan {repo} Repo scan (--profile=, --include-targets)
hackly:cleanup-outputs Delete old raw scanner outputs
hackly:dispatch-due Re-dispatch leftover pending tasks
hackly:token {email} Issue a personal API token (--ability=full|read|write). Shown once
hackly:digest Send the weekly findings digest now (--dry-run to preview)
hackly:update-databases Refresh Nuclei templates, the Trivy database, and Semgrep rules. Scheduled daily at 03:30
queue:work Process scan jobs
schedule:work Hourly output cleanup, the Sunday digest, and the daily Nuclei / Trivy / Semgrep refresh (or cron schedule:run)

Configuration

Primary config: config/hackly.php — override via .env.

.env
QUEUE_CONNECTION=database
CACHE_STORE=database

# Safety
HACKLY_ALLOWLIST_ONLY=false
HACKLY_ALLOWLIST=example.com,203.0.113.10
HACKLY_ALLOW_PRIVATE_TARGETS=true

# Soft rate limits
HACKLY_PER_TARGET_PER_MINUTE=2
HACKLY_GLOBAL_CONCURRENT=5
HACKLY_JITTER_SECONDS=5
HACKLY_TASK_SPACING_SECONDS=10
HACKLY_DEEP_COOLDOWN_HOURS=24
HACKLY_QUIET_HOURS_ENABLED=false

# Job timeout must exceed longest scanner (ZAP ~900s)
HACKLY_JOB_TIMEOUT=960
DB_QUEUE_RETRY_AFTER=1020

# Target binary paths
HACKLY_NMAP=nmap
HACKLY_NUCLEI=nuclei
# macOS: HACKLY_ZAP=/Applications/ZAP.app/Contents/Java/zap.sh
HACKLY_ZAP=zap.sh
HACKLY_NIKTO=nikto
HACKLY_WPSCAN=wpscan
# HACKLY_WPSCAN_API_TOKEN=
# HACKLY_EGRESS_IP=
# HACKLY_PENTEST_AUTH_MINUTES=30
# HACKLY_PENTEST_COOLDOWN_HOURS=6

# GitHub repository scanning
HACKLY_GIT=git
HACKLY_COMPOSER=composer
HACKLY_SEMGREP=semgrep
HACKLY_TRIVY=trivy
HACKLY_GITLEAKS=gitleaks
HACKLY_CHECKOV=checkov
# HACKLY_SEMGREP_CONFIG=p/php
# HACKLY_OSV_ENABLED=true
# HACKLY_REPO_HIDE_UNREACHABLE=false
# HACKLY_REPO_DROP_NOISE=false

Security model

  • Target scans require ownership verification (DNS TXT). The scanner IP is shown on that screen
  • Penetration tests use that standing check. A second TXT is only required when the target is not already verified, and that token expires and is consumed on start. Declared URLs cannot leave the authorized host
  • Repository scans require a GitHub token with read access to that repo
  • Linking targets and repositories is optional. Linked scans stay on those assets. WPScan does not guess passwords
  • Optional allowlist and private-IP blocking for Targets
  • Soft rate limits, jitter, task spacing, and quiet hours
  • Deep target profile has a cooldown between runs
  • GitHub PATs are stored encrypted at rest (APP_KEY) via the GitHub tokens UI
  • Repo workspace clones are removed after finalize when HACKLY_REPO_CLEANUP=true (default)
  • Admin accounts support TOTP and email multi-factor authentication
  • API tokens are personal. A public finding link is off until you share it, and it does not reveal who published it
Hackly is an orchestration layer — it does not replace responsible disclosure policies or scoped pentest agreements. PHP reachability / noise reduction is heuristic (strong signal for Laravel apps), not a full interprocedural guarantee.

Production tips

  • Set HACKLY_ALLOW_PRIVATE_TARGETS=false
  • Prefer HACKLY_ALLOWLIST_ONLY=true with an explicit allowlist
  • Configure real mail for email 2FA (MAIL_MAILER=…)
  • Change the seeded admin password immediately
  • Store GitHub PATs only via the GitHub tokens UI
  • Run both install scripts on the scan worker host, then hackly:check-binaries as the queue user
  • Set HACKLY_EGRESS_IP to the address operators should allowlist
  • Keep the scheduler running so the Sunday digest is sent and hackly:update-databases refreshes Nuclei, Trivy, and Semgrep data daily
  • Run a persistent queue:work, and schedule:work or cron schedule:run

Source and issues: github.com/andreapollastri/hackly