This guide covers installing, configuring, and running HarnessGuard in detail. For the short version, see the README quickstart.
HarnessGuard requires Python 3.10+ and has no runtime dependencies.
Install into the current environment:
python -m pip install -e .Run without installing by putting src on the module path:
PYTHONPATH=src python -m harnessguard path/to/agent-projectPowerShell:
$env:PYTHONPATH="src"
python -m harnessguard .Scan a file or a directory. A directory is walked recursively; excluded patterns and file-size limits apply:
harnessguard path/to/agent-project
harnessguard src/harness.pySet the minimum severity that causes a failing exit code:
harnessguard . --severity critical
harnessguard . --severity mediumSeverities, weakest to strongest: info, low, medium, high, critical. The default policy threshold is high.
List every built-in check, its severity, and its category:
harnessguard --list-rules| Flag | Description |
|---|---|
path |
File or directory to scan. Defaults to .. |
--format text |
Human-readable report (default). |
--format json |
Structured JSON report. |
--format sarif |
SARIF 2.1 report for code-scanning tooling. |
--output FILE, -o FILE |
Write the report to a file instead of stdout. |
--severity LEVEL |
Minimum severity that fails the run (info..critical, default high). |
--config FILE |
Path to a .harnessguard.json config. Defaults to the scan root. |
--baseline FILE |
Suppress findings already recorded in the baseline. |
--write-baseline FILE |
Save the current findings as a baseline. |
--list-rules |
Print all built-in checks and exit. |
--no-color |
Disable ANSI color in text output. |
| Code | Meaning |
|---|---|
0 |
Scan completed and no finding reached the severity threshold. |
1 |
Policy failed: at least one finding reached the severity threshold. |
2 |
Scanner, config, or read error. |
Create .harnessguard.json in the scan root:
{
"exclude": ["generated/*", "vendor/*"],
"ignore": ["HG029"],
"max_file_size": 1000000
}A template lives at .harnessguard.example.json.
| Key | Type | Default | Meaning |
|---|---|---|---|
exclude |
string[] | common build/cache dirs | Glob patterns, relative to the scan root. |
ignore |
string[] | [] |
Rule IDs to skip entirely. Prefer only after a security review. |
max_file_size |
int | 1000000 |
Files larger than this many bytes are skipped. |
Suppress one line in any text or config file by including harnessguard: ignore on that line:
app.secret = "sk-live-..." # harnessguard: ignoreAdopt the scanner in an existing project without failing on old findings:
harnessguard . --write-baseline .harnessguard-baseline.json
harnessguard . --baseline .harnessguard-baseline.jsonFingerprints include rule, path, line, and snippet. A finding changes fingerprint when its rule, path, line, or snippet changes, so genuinely new findings reappear even when they land near an old one. Re-run --write-baseline after a deliberate remediation sweep.
Text, for humans:
harnessguard . --format textJSON, for scripts:
harnessguard . --format json --output report.jsonSARIF, for code-scanning platforms:
harnessguard . --format sarif --output harnessguard.sarifEvery finding carries rule ID, name, severity, category, path, line, column, message, suggested fix, and a stable fingerprint.
The repository ships an intentionally vulnerable harness:
$env:PYTHONPATH="src"
python -m harnessguard examples/vulnerable_harness.py --severity highThe demo contains dynamic eval-class sinks, unsafe subprocess use, pickle deserialization, unbounded delegation, code execution enabled, disabled human approval, missing HTTP timeout, environment leakage, and untrusted input concatenated into a prompt. The scan reports each as a finding with a fix hint. Do not deploy this file.
A least-privilege workflow is included at .github/workflows/harnessguard.yml. It scans on every push and pull request and uploads SARIF to GitHub code scanning:
name: HarnessGuard
on:
push:
pull_request:
permissions:
contents: read
security-events: write
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Scan agent harness
run: python -m harnessguard . --severity high --format sarif --output harnessguard.sarif
env:
PYTHONPATH: src
- name: Upload SARIF
if: ${{ always() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }}
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: harnessguard.sarifThe security-events: write permission is required for the SARIF upload. The conditional guard prevents unauthorized uploads from forked pull requests.
Rule IDs are stable API. New rules add new IDs; released IDs never silently change meaning. When you add a detector, add a test that demonstrates the missed unsafe pattern or the false positive first.