Skip to main content

janus-sec

Tests

A terminal-first credential exposure auditor.

Your SSH keys, AWS credentials, and kube config are only as safe as their file permissions. A chmod 644 typo, a bad tarball extraction, or a cloud sync tool can quietly leave a private key readable by every user on your machine — and there's usually no warning until something goes wrong.

janus-sec scans the credential files you already have, tells you exactly what's wrong and why it matters, and fixes it with one confirmed keystroke. Nothing leaves your machine — no network calls, no file content is ever read, no sudo.

$ janus-sec
Scanned 4 file(s), 8 not present.

[HIGH] /home/user/.ssh/id_rsa
    Issue:  world_readable (mode 644)
    Why:    This file is readable by any local user on this machine.
            Credential files should only be readable by their owner.
    Fix:    chmod 600 /home/user/.ssh/id_rsa

[MEDIUM] /home/user/.aws/credentials
    Issue:  group_readable (mode 640)
    Why:    This file is readable by group 'docker', which is not your
            primary group. Other accounts in that group can read this file.
    Fix:    chmod 600 /home/user/.aws/credentials

2 finding(s) total, 1 HIGH risk.

Why this exists

The underlying check here is genuinely simple — find ~/.ssh -perm /077 does most of the mechanical work in one line. That's not the point. The gap janus-sec closes isn't "how do I check this," it's "I never thought to check this, and if I did, I wouldn't trust a one-off command to tell me what to do about it or keep a record that I did it."

Concretely, what a one-liner doesn't give you:

  • An explanation. -rw-r--r-- means nothing to most people at a glance. "This private key is readable by any local user on this machine" changes behavior.
  • The right fix for each file type. SSH keys, known_hosts, AWS credentials, and kube configs don't all want the same target mode.
  • A safe way to apply it. Confirmation by default, --dry-run to preview, and a re-check immediately before writing (the file you looked at when scanning might not be the file you're about to change).
  • A record. An append-only audit log of every fix, so "what did I change and when" has a real answer.
  • A CI gate. --ci exits non-zero on any HIGH-risk finding, so this can fail a pipeline, not just print a warning nobody reads.

What it checks

Check Risk Auto-fix?
World-readable / world-writable HIGH Yes
Owned by a different user HIGH No — would require sudo, out of scope
Group-readable (non-primary group) MEDIUM Yes
Symlink pointing outside its expected directory MEDIUM No — target choice is a judgment call

Scans by default: ~/.ssh/*, ~/.aws/*, ~/.kube/config, ~/.npmrc, ~/.git-credentials, ~/.docker/config.json. Missing files are silently skipped, not errors — most people won't have all of these.

Safety properties

  • No network access, ever.
  • Never reads file contents — only metadata (permissions, ownership). It can't tell you if a secret has leaked; it tells you if the file is more exposed than it should be.
  • Never elevates privileges. No sudo, no chown. If a fix would require that, janus-sec reports the problem and stops — it doesn't attempt it.
  • Every fix requires confirmation (or an explicit --yes for scripted use), and --dry-run previews changes with zero side effects.
  • Append-only audit log of every fix applied, at ~/.local/state/janus-sec/audit.log.

Install

pip install janus-sec

Or from source, for development:

git clone https://github.com/A-S-Manoj/janus-sec.git
cd janus-sec
python3 -m venv .venv && source .venv/bin/activate
pip install -e .

Usage

# Scan (also the default with no arguments - read-only, safe to run any time)
janus-sec
janus-sec scan

# Interactive TUI
janus-sec tui

# Machine-readable output
janus-sec scan --format json

# CI mode: exit 1 if any HIGH-risk finding exists
janus-sec scan --ci

# Fix everything fixable, with confirmation
janus-sec fix

# Fix one specific file
janus-sec fix ~/.ssh/id_rsa

# Preview fixes without changing anything
janus-sec fix --dry-run

# Skip the confirmation prompt (for scripts)
janus-sec fix --yes

Configuration

~/.config/janus-sec/config.toml (optional — everything works with no config file at all):

# Suppress a specific check on a specific file - not the whole file,
# just that one issue, so other real problems on it still get caught.
[[ignore]]
path = "/home/user/.ssh/known_hosts"
check_type = "group_readable"
note = "shared dev box, group access is intentional"

# Treat a group as known-safe, machine-wide.
[[allowlist]]
group = "wheel"
action = "suppress"   # or "downgrade_to_low"
note = "trusted admin group on my machines"

Development

Same setup as above, plus test dependencies:

pip install pytest pytest-asyncio
pytest -v

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

janus_sec-0.1.1.tar.gz (27.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

janus_sec-0.1.1-py3-none-any.whl (24.8 kB view details)

Uploaded Python 3

File details

Details for the file janus_sec-0.1.1.tar.gz.

File metadata

  • Download URL: janus_sec-0.1.1.tar.gz
  • Upload date:
  • Size: 27.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for janus_sec-0.1.1.tar.gz
Algorithm Hash digest
SHA256 f7d6ff0c6630266d66eee3b0e8cd64e8d03416dbd75b756f638c058fc6f3299d
MD5 010653fe636857e2eee9fd1bfd08dccc
BLAKE2b-256 a518ecee9268430ebe7fa3ce4392be106f93d3dd2888e6ae6413e033cf802a55

See more details on using hashes here.

File details

Details for the file janus_sec-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: janus_sec-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 24.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for janus_sec-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2ad16cf10f96a122ef94d7c0d29802c7601c617f3aaeddc80d5aab6768efdc9a
MD5 647265746f6328e1f08cfd67bf1cbd04
BLAKE2b-256 68c91ad60989146fbae90a203c4e184a8d29de5380195a0c7fe993f33bc44aed

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page