Skip to content

seibel777/tien.app

Tien

CI

Repository: https://github.com/seibel777/tien.app

Tien is a local-first CLI that runs 100% passive security checks on:

  • Repositories (JS/TS-focused) via SAST/SCA/secrets tooling
  • URLs via non-invasive HTTP/TLS/header analysis (GET/HEAD only)

It’s inspired by “pipeline-style” CLIs (scan → encode/merge → report/plot): the scanner emits results, and other commands consume those results to generate reports or visualizations.

Tien does not attempt exploitation. Passive findings are signals + evidence, not proof of compromise.


Goals

  • Single binary (local usage)
  • Passive-only URL checks (no payloads, fuzzing, brute force)
  • Repo + URL from day one
  • Stream-friendly workflows (stdin/stdout, file outputs)
  • Deterministic output (easy diff between runs)
  • Scales locally (concurrency, caching, shard mode)

What Tien does

Repo scan (passive)

  • Secrets detection (tokens/keys committed by mistake)
  • Dependencies vulnerability scanning (SCA)
  • Static rules for insecure patterns (SAST), with a JS/TS focus
  • Normalizes results into a single finding format

URL scan (passive)

Only GET/HEAD and analysis:

  • TLS certificate / HTTPS posture
  • Security headers (CSP/HSTS/etc.)
  • Cookie flags (Secure/HttpOnly/SameSite) when present
  • CORS misconfig patterns
  • /.well-known/security.txt presence
  • Mixed content signals (http assets referenced by https pages)

Hard limits (non-negotiable)

  • No active exploitation
  • No credential guessing / brute force
  • No payload injection testing (XSS/SQLi/etc.)
  • No aggressive crawling or wordlists

If you want active testing, use dedicated tools. Tien stays passive by design.


Status (current)

  • Implemented: config loader, Finding schema, gob/jsonl IO, merge, encode, reports (text/md/sarif/json), HTML plot, diff, URL scan (TLS + headers + cookies + CORS + security.txt + mixed content), host summary, repo scan (gitleaks + osv-scanner + semgrep), caching (repo + optional URL), run history, shard mode, retry + per-target timeout, graceful cancellation, plugin system, policy mode, Prometheus metrics, minimal TUI summary, custom Semgrep rules pack, hybrid gitleaks runner (CLI or Docker fallback).

Stack

Core

  • Go (CLI + pipeline + storage + reports)

Engines (invoked by Tien)

Modes:

  • hybrid (default): use local CLIs when available, fallback to Docker with a warning.
  • cli: require installed CLIs.
  • docker: always run tools in containers.

Repo scan integrates gitleaks, osv-scanner, and semgrep.

Output formats (current)

  • gob (default; compact + fast)
  • jsonl (debug + easy integrations)
  • text report
  • md report
  • sarif report
  • json report
  • html plot

Install

Go install

go install github.com/seibel777/tien.app/cmd/tien@latest
tien --help

Homebrew

brew tap seibel777/tien.app https://github.com/seibel777/tien.app
brew install tien

Requires the tap formula updated with the latest release checksums (see docs/site.md).

NPM

npm i -g @seibel777/tien
tien --help

Requires the npm package to be published (see packages/npm).

GitHub (clone)

git clone https://github.com/seibel777/tien.app.git
cd tien.app
go build -o tien ./cmd/tien
./tien --help

Releases (binary download)

Prebuilt binaries: https://github.com/seibel777/tien.app/releases

Linux amd64 example:

curl -L -o tien https://github.com/seibel777/tien.app/releases/latest/download/tien_linux_amd64
chmod +x tien
./tien --help

macOS arm64 example:

curl -L -o tien https://github.com/seibel777/tien.app/releases/latest/download/tien_darwin_arm64
chmod +x tien
./tien --help

Checksums are published as *.sha256 next to each binary.

Engine dependencies (repo scan)

Option A - installed CLIs Ensure these commands are available in $PATH:

  • gitleaks
  • semgrep
  • osv-scanner

Option B - Docker Install Docker and enable the "docker engine" mode in config (see below).

Don’t mix A and B unless you enjoy environment debugging.


Usage (current)

URL scan (targets via stdin)

cat targets.txt | tien scan url --format gob > url.tien

URL scan (targets file)

tien scan url --targets targets.txt --format jsonl > url.jsonl

Host summary is printed to stderr by default; disable with --summary=false.

URL scan (shard mode)

tien scan url --targets targets.txt --shard 1/5 --format gob > url_shard_1.tien

URL scan with policy mode

tien scan url --targets targets.txt --policy high --format gob > url_policy.tien

URL scan with Prometheus metrics

tien scan url --targets targets.txt --metrics true --metrics-listen 127.0.0.1:9465 --format gob > url.tien

Merge results

tien merge url.tien other.tien > all.tien

Report (text)

tien report --type text all.tien

Report (Markdown)

tien report --type md all.tien > report.md

Report (SARIF)

tien report --type sarif all.tien > tien.sarif

Plot (HTML)

tien plot all.tien > report.html

Encode (JSONL)

tien encode --to jsonl all.tien > all.jsonl

Diff scans

tien diff old.tien new.tien

History (local run index)

tien history --limit 10

Enable history in config or pass --history true to record runs.

Repo scan (gitleaks + osv-scanner + semgrep)

tien scan repo --path . --format gob > repo.tien

Note: osv-scanner and semgrep may require network access for advisories or rules; disable them in config if needed. Repo scans are cached by commit/config/engine versions by default; disable with --cache false. URL cache is optional (ETag/Last-Modified) and disabled by default.

Hybrid gitleaks (CLI or Docker fallback)

tien hybrid --path . > gitleaks.json

Outputs raw gitleaks JSON (not normalized Findings yet). Note: gitleaks returns exit code 1 when leaks are found; tien hybrid treats that as success so you still get output.

Note: URL scanning requires ownership proof by default. Configure safety.proof in your config or disable the requirement explicitly for trusted scopes.


Targets format (URL scan)

targets.txt (one per line):

https://example.com https://app.example.com https://api.example.com

You can also pipe from another tool:

some-generator | tien scan url > url.tien


Configuration

Default path: • macOS/Linux: ~/.config/tien/config.yaml

Example:

repo: engine_mode: "hybrid" # "cli", "docker", or "hybrid" engines: semgrep: enabled: true config: "p/default" # or rules/semgrep/tien-js.yml max_target_bytes: 2000000 image: "returntocorp/semgrep:latest" gitleaks: enabled: true image: "ghcr.io/gitleaks/gitleaks:latest" osv: enabled: true image: "ghcr.io/google/osv-scanner:latest" exclude: - "node_modules/" - "dist/" - ".next/" - "build/" - "**/*.min.js"

url: concurrency: 20 timeout_ms: 8000 max_target_ms: 15000 max_body_kb: 256 follow_redirects: true retry: max_attempts: 2 backoff_ms: 200 checks: tls: true headers: true cookies: true cors: true securitytxt: true mixed_content: true

safety: require_ownership_proof: true allow_localhost_without_proof: true allow_private_ips_without_proof: true proof: method: "http" # "http" or "dns" token: "YOUR_RANDOM_TOKEN"

output: default_format: "gob" redact_secrets_in_evidence: true

cache: dir: "~/.cache/tien" # optional override repo: enabled: true url: enabled: false history: enabled: false

policy: enabled: false min_severity: "high"

metrics: enabled: false listen: "127.0.0.1:9465"

plugins:

  • name: "custom-check" kind: "repo" # or "url" command: "/path/to/plugin" args: ["--flag"] format: "jsonl" timeout_ms: 20000 enabled: false

Plugins (custom checks)

Plugins let you add custom checks without forking Tien. Each plugin is an external command that outputs Findings in JSONL or gob.

Plugin environment variables: • TIEN_PLUGIN_NAMETIEN_PLUGIN_KIND (repo|url) • TIEN_SCAN_TIME (RFC3339) • TIEN_REPO_PATH (repo plugins) • TIEN_TARGETS_FORMAT=lines + TIEN_TARGET_COUNT (url plugins)

URL plugins receive the targets list on stdin (one URL per line). Repo plugins run with the repo path as working directory.


Custom Semgrep rules pack

Use the bundled rules pack in rules/semgrep/tien-js.yml for JS/TS-focused checks. Set:

repo:
  engines:
    semgrep:
      config: "rules/semgrep/tien-js.yml"

Metrics, policy, and TUI

  • Prometheus metrics: tien scan url --metrics true --metrics-listen 127.0.0.1:9465 exposes /metrics.
  • Policy mode: tien scan repo --policy high exits non-zero if findings >= severity.
  • Minimal TUI: add --tui to show a live summary on stderr.

Ownership proof (URL scan safety)

By default, URL scanning requires proof that you control the target to reduce accidental scanning.

Supported methods (recommended): • HTTP: /.well-known/tien-verification must return a token • DNS TXT: tien= on the domain

Config example:

safety: require_ownership_proof: true proof: method: "http" # "http" or "dns" token: "YOUR_RANDOM_TOKEN"

Notes: • localhost and private IPs can be exempted in config • You can disable proof requirement, but that’s on you


Design

Pipeline model

Tien follows a two-step model: 1. scan commands emit a stream of findings (stdout/file) 2. report/plot/encode/merge consume findings and produce outputs

This makes it easy to: • run scans on multiple machines • merge outputs later • keep scanning logic separate from reporting/visualization

Finding schema (single format for repo + url)

Each issue is normalized into a Finding: • id: stable check identifier (url.headers.hsts_missing, repo.secrets.generic, repo.deps.osv) • source: url or repo • target: URL or path:line • severity: info|low|med|high|crit • confidence: low|med|high • title: short human title • description: what was detected and why it matters • evidence: short, redacted proof (headers/snippet/package) • remediation: direct fix guidance • tags: e.g. cwe:, owasp:, category:* • fingerprint: deterministic hash to deduplicate across runs • timestamp: when detected • run_id: run identifier (for comparisons)

Fingerprint rules (must be stable) • URL findings: hash of (id + normalized_host + normalized_path? + key_evidence_fields) • Repo findings: hash of (id + file_path + line + rule_id/package_id)

This enables: • deduplication • diff between runs • stable reporting even with concurrency

See docs/checks.md for the full list of check IDs.

Engines

Repo engines implement: • run external tool • parse tool output (JSON/SARIF where possible) • normalize into Finding

URL checks implement: • fetch (GET/HEAD only) with timeouts and limits • analyze TLS/headers/body (bounded) • emit normalized Finding


Commands overview

tien scan repo

Scans a repo path using configured engines and emits findings. Runs the enabled engines (gitleaks, osv-scanner, semgrep). Supports commit-based caching when enabled.

Common flags: • --path

• --format gob|jsonl • --config • --cache auto|true|false • --history auto|true|false • --policy <severity|off> • --metrics auto|true|false • --metrics-listen • --tui

tien scan url

Reads URLs from stdin (or --targets) and emits findings.

Common flags: • --targets (optional; stdin by default) • --format gob|jsonl • --summary=true|false • --config • --shard N/M • --cache auto|true|false • --history auto|true|false • --policy <severity|off> • --metrics auto|true|false • --metrics-listen • --tui

Config options control concurrency, per-target runtime, retries, redirects, and ownership proof.

tien hybrid

Runs gitleaks using the local CLI or Docker fallback and emits raw JSON.

Common flags: • --path

• --image

tien merge

Merges multiple .tien files into one.

tien report

Generates reports: • --type text|md|sarif|json • --min-severity info|low|med|high|crit • --group-by source|severity|target|none • --only-tags tag1,tag2 • --top

tien encode

Converts formats: • --to gob|jsonl

tien plot

Generates report.html from findings. Common flags: • --min-severity info|low|med|high|crit • --only-tags tag1,tag2

tien diff

Compares two scans and reports new/fixed/changed findings.

tien history

Shows the local run history (when enabled in config).

Common flags: • --format text|json • --limit


Roadmap

See roadmap.md for the phased checklist and optional extensions.

Testing guide: docs/testing.md.


Project layout

tien/ cmd/tien/ # CLI entrypoint internal/app/ # config + wiring internal/cache/ # repo/url caches + history storage internal/history/ # local run history helpers internal/metrics/ # Prometheus metrics collector internal/plugins/ # plugin runner for custom checks internal/scan/ # orchestration + URL/repo scanning internal/engines/repo/ # semgrep/osv/gitleaks wrappers internal/diff/ # scan diffing internal/store/ # gob/jsonl IO + merge internal/report/ # text/md/sarif/json internal/plot/ # html plot pkg/model/ # exported Finding schema pkg/version/ docs/ examples/ rules/semgrep/ .github/workflows/


License

Apache-2.0. See LICENSE.


Links


Disclaimer

Tien is intended for scanning: • code you own • systems you are authorized to assess

Passive scanning reduces risk, but it is still your responsibility to comply with laws, policies, and scope restrictions.

About

A clean, local-first CLI for 100% passive security auditing of JS/TS repos and URLs—secrets, dependency vulns, SAST, TLS/headers/cookies/CORS—built for streamable scan → merge → report workflows.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages