Skip to content

pklooster/palisade

Palisade

Open-source supply-chain & container security scanner for source code, npm dependencies, Docker images, GitHub repos, and CI/CD pipelines.

CI License: Apache-2.0 PyPI Python

Palisade is a lightweight, plugin-based scanner that helps developers detect compromised dependencies, vulnerable Docker images, leaked secrets, misconfigured GitHub Actions, and newly disclosed CVEs — early, locally, and without sending your code to a third party.

Designed for: individual developers · small teams · OSS maintainers Not designed for: SaaS-only enterprise compliance workflows. If that's what you want, look at Snyk/Sonatype/Wiz.


What it does

Capability Built-in scanners
npm supply chain Lockfile vuln scan (OSV/GHSA), typosquat detection, postinstall script analysis, obfuscated-code heuristics, malicious-package check
Secrets AWS keys, GitHub PATs, GCP service-account JSON, Slack tokens, JWTs, private keys, generic high-entropy strings — with redaction
Docker Dockerfile static analysis + image layer scan (CVEs on OS packages from dpkg/apk/rpm), running-as-root, unpinned base images, secrets in ENV
GitHub posture Branch protection, CODEOWNERS, unpinned actions, excessive token permissions, missing signed commits
Intel feeds OSV.dev · GitHub Security Advisories · NVD · CISA Known Exploited Vulnerabilities · OpenSSF Scorecard
Output Rich terminal · JSON · SARIF 2.1.0 (GitHub Code Scanning) · Markdown reports
Delivery CLI · GitHub Action · GitHub Issue / Slack / Discord / Webhook notifications

Offline-capable after palisade update-intel. No telemetry. No phone-home.


Quickstart

Install

pip install palisade-scanner
# (the CLI command is `palisade` — the PyPI name is `palisade-scanner`
# because `palisade` was already taken on PyPI by an unrelated project)

# Or, from source:
git clone https://github.com/pklooster/palisade
cd palisade && pip install -e ".[dev]"

Run

# Sync vulnerability intel (run once a day; cached locally in ~/.palisade/intel.db)
palisade update-intel

# Scan a repo
palisade scan repo ./my-project

# Scan a Docker image
palisade scan image my-org/my-app:latest

# Scan a remote GitHub repo (posture + lockfiles via API)
palisade scan github owner/repo

# Emit SARIF for GitHub Code Scanning
palisade scan repo . --format sarif --output palisade.sarif

# Fail CI on high+ severity findings
palisade scan repo . --fail-on high

Use as a GitHub Action

# .github/workflows/security.yml
name: Security scan
on: [push, pull_request]
jobs:
  palisade:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write
    steps:
      - uses: actions/checkout@v4
      - uses: pklooster/palisade/.github/actions/scan@v0.1.0
        with:
          path: .
          fail-on: high

See examples/workflows/ for more.


CLI

palisade scan repo <path>              Scan a local repo (npm + secrets + dockerfile)
palisade scan image <ref>              Scan a Docker image (local or registry)
palisade scan github <owner/repo>      Remote scan via the GitHub API
palisade watch github <owner/repo>     Poll a repo and notify on new findings
palisade update-intel [--feed NAME]    Refresh local vulnerability intel cache
palisade generate-sbom <target>        CycloneDX 1.5 JSON SBOM
palisade audit-config <path>           Posture audit (IaC, workflows, repo settings)
palisade list-scanners                 List loaded scanner plugins
palisade list-feeds | list-reporters | list-notifiers
palisade rules list | explain <id>     Inspect built-in detection rules

Global flags: --format {text,json,sarif,markdown} · --output PATH · --config FILE · --offline · --severity-threshold {critical,high,medium,low,info} · --fail-on LEVEL · --no-color

Exit codes: 0 clean · 1 findings ≥ --fail-on · 2 internal error.


Configuration

Project-level config lives at palisade.yaml in your repo root:

# Annotated example: see examples/palisade.yaml
scanners:
  enabled: [npm, secrets, dockerfile, image, github]
  npm:
    fail_on_postinstall: true
    typosquat_distance: 2
  secrets:
    extra_rules: ./custom-secret-rules.yaml
    exclude_paths: ["docs/**", "tests/fixtures/**"]
intel:
  feeds: [osv, ghsa, kev]
  cache_dir: ~/.palisade
  offline: false
reporters: { format: sarif, output: palisade.sarif }
notifiers:
  github_issue:
    enabled: true
    repo: $GITHUB_REPOSITORY
    severity_threshold: high

Architecture

A thin orchestrator core loads four plugin types via Python entry points:

┌──────────────────────────────────────────────────────────────┐
│                          CLI / Action                         │
└───────────────┬─────────────────────────────────┬────────────┘
                │                                  │
                ▼                                  ▼
        ┌──────────────┐                  ┌────────────────┐
        │ Orchestrator │◄────IntelCache──►│  IntelFeed(s)  │  ← OSV, GHSA, NVD, KEV
        └──────┬───────┘  (SQLite, local) └────────────────┘
               │
        ┌──────┴────────────┐
        ▼                   ▼
┌──────────────┐    ┌──────────────┐
│  Scanner(s)  │    │  Reporter(s) │  → text · JSON · SARIF · MD
└──────┬───────┘    └──────────────┘
       │
       ▼ findings
┌──────────────┐
│  Notifier(s) │  → GitHub Issue · Slack · Discord · Webhook
└──────────────┘

Scanners NEVER hit the network — all vulnerability intel goes through the local SQLite cache. This makes --offline trivial and tests deterministic. See docs/architecture.md.


Writing a plugin

# my_scanner.py
from palisade.scanners.base import Scanner
from palisade.models import Finding, Severity, FileTarget

class MyScanner:
    name = "my-scanner"
    target_kinds = {"repo"}

    def scan(self, target, ctx):
        for path in ctx.workspace.rglob("*.config"):
            if b"DEBUG=true" in path.read_bytes():
                yield Finding(
                    rule_id="my.debug-enabled",
                    scanner=self.name,
                    severity=Severity.MEDIUM,
                    title="Debug mode enabled in config",
                    target=FileTarget(path=str(path.relative_to(ctx.workspace))),
                    remediation="Set DEBUG=false in production configs.",
                )

Register via pyproject.toml:

[project.entry-points."palisade.scanners"]
my-scanner = "my_package.my_scanner:MyScanner"

Full guide: docs/plugin-authors.md.


Threat model

Palisade is designed to be safe to run on untrusted code. It:

  • Parses lockfiles and Dockerfiles statically — never executes postinstall scripts.
  • Reads Docker images by parsing docker save tarballs locally; no container runtime needed.
  • Talks to intel APIs over HTTPS with strict TLS verification; pinned via httpx.
  • Caches all intel locally — supports fully --offline operation.
  • Has zero telemetry.

See docs/threat-model.md for the full STRIDE analysis.


Roadmap

  • v0.1 (this release): CLI, npm/secrets/dockerfile/image/github scanners, OSV+GHSA+KEV feeds, SARIF, GitHub Action.
  • v0.2: PyPI + Maven ecosystems; Sigstore/Rekor verification; CycloneDX 1.6; SLSA provenance.
  • v0.3: IaC scanner (Terraform / Helm / k8s); deep GitHub Actions YAML scan; ML-assisted secret detection.
  • v0.4: watch daemon; differential PR scans; webhook-driven re-scan.
  • v1.0: Stable plugin API; signed releases; community rule packs.

Full roadmap: docs/roadmap.md.


Comparable tools

Palisade is not trying to replace Trivy, Grype, or Semgrep. It complements them by focusing on supply-chain + repo-posture signals with a small, hackable Python codebase that's easy for OSS maintainers to extend.


Contributing

We welcome contributions! See CONTRIBUTING.md for setup, style, and PR guidelines.

For security issues, see SECURITY.md — please do not open public issues for vulnerabilities.


Name

palisade — a defensive wooden wall used to protect a perimeter. The project was almost called tripwire, vigil, or auditron; all good names, none of them as evocative.


License

Apache 2.0 — see LICENSE.

About

Open-source supply-chain & container security scanner for repos, npm, Docker, and CI/CD. Plugin-based, offline-capable, no telemetry.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors