Skip to main content

Local-first redaction engine for AI egress security

Project description

EgressAI

EgressAI is a local-first redaction engine for AI egress security.

The first package takes text, detects secrets, replaces them with stable placeholders, and returns structured findings without exposing plaintext secret values in the public result.

Install

pip install egressai

The package depends on egressai-detect-secrets for provider-aware secret detection.

Python API

Redact text:

from egressai import RedactionEngine

secret = "sk-proj-" + "a" * 40
engine = RedactionEngine()
result = engine.redact(f"OPENAI_API_KEY={secret}")

print(result.redacted_text)

Output:

OPENAI_API_KEY={{EGRESSAI_SECRET_OPENAI_001}}

Inspect structured findings:

for finding in result.findings:
    print(finding.type, finding.line, finding.column, finding.placeholder)

Output:

secret.openai_api_key 1 16 {{EGRESSAI_SECRET_OPENAI_001}}

Restore redacted text during the same engine session:

restored = engine.restore(result.redacted_text)

The restore map is memory-only and is not included in structured output.

Structured result:

payload = result.to_dict()

The structured output includes:

  • redacted_text
  • findings
  • stats

Each finding includes zero-based character offsets (start, end) plus one-based line and column metadata for locating the sensitive value in files, logs, and pasted diffs.

Plaintext secret values are not included in result.to_dict().

Redact a larger pasted context:

text = """
OPENAI_API_KEY=sk-proj-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
GITHUB_TOKEN=ghp_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
DATABASE_URL=postgres://admin:password@prod.internal:5432/app
"""

result = RedactionEngine().redact(text)
print(result.redacted_text)

Output:

OPENAI_API_KEY={{EGRESSAI_SECRET_OPENAI_001}}
GITHUB_TOKEN={{EGRESSAI_SECRET_GITHUB_001}}
DATABASE_URL={{EGRESSAI_SECRET_DB_URL_001}}

CLI

Redact inline text:

egressai redact "OPENAI_API_KEY=sk-proj-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

Output:

OPENAI_API_KEY={{EGRESSAI_SECRET_OPENAI_001}}

Redact a file:

egressai redact ./prompt.txt

Redact stdin:

cat ./logs.txt | egressai redact

Existing file paths are read from disk. Any other input is treated as literal text, including large multi-line contexts passed as one argument. For very large prompts or logs, stdin is usually the most reliable shell interface.

Return the full redaction result as JSON:

egressai redact --json ./sample.env

Scan without printing redacted text:

egressai scan ./sample.env

Return findings and stats as JSON:

egressai scan --json ./sample.env

Example JSON shape:

{
  "findings": [
    {
      "category": "secret",
      "column": 16,
      "confidence": 0.99,
      "detector": "egressai.openai_key",
      "end": 63,
      "id": "finding_000001",
      "line": 1,
      "placeholder": "{{EGRESSAI_SECRET_OPENAI_001}}",
      "severity": "critical",
      "start": 15,
      "type": "secret.openai_api_key"
    }
  ],
  "stats": {
    "findings_count": 1,
    "pii_count": 0,
    "secrets_count": 1
  }
}

Return one finding per JSON Lines record:

egressai scan --jsonl ./sample.env

Example JSONL record:

{"category":"secret","column":16,"confidence":0.99,"detector":"egressai.openai_key","end":63,"id":"finding_000001","line":1,"placeholder":"{{EGRESSAI_SECRET_OPENAI_001}}","severity":"critical","start":15,"type":"secret.openai_api_key"}

Fail when findings are present:

egressai scan --fail-on-findings ./sample.env

Use a custom placeholder prefix:

egressai redact --placeholder-prefix SAFE ./prompt.txt

Codex Integration

The repo includes a hook-only Codex plugin at plugins/egressai.

The plugin does not include skills. It uses local hooks as the enforcement boundary, but the MVP behavior is allow-and-redact rather than block:

  • UserPromptSubmit redacts sensitive values from user prompts and allows the request.
  • PreToolUse restores known placeholders locally, then reports only redacted hook output.
  • PostToolUse redacts sensitive values from tool outputs before they re-enter context.

Hook placeholder mappings are stored in a local session vault so separate hook invocations can reuse and restore the same placeholders. The vault path defaults to the system temp directory and can be overridden with EGRESSAI_CODEX_VAULT_FILE.

Codex hooks are lifecycle commands. Current public Codex docs describe blocking and feedback behavior, not a guaranteed payload-rewrite contract, so EgressAI emits the sanitized payload in hook feedback and keeps the restore mapping local.

Install the local package before using the hooks:

python3 -m pip install --upgrade "egressai>=0.1.6"

Then add this repository marketplace to Codex, restart Codex, open /plugins, and install EgressAI:

codex plugin marketplace add .

After installing, open /hooks to review and trust the EgressAI hook definitions. A finding should produce a successful hook result with "decision":"allow" and a payload containing EgressAI placeholders, not the plaintext secret.

Larger Context Example

The fixture at tests/fixtures/messy_context.txt contains a pasted support/debug report with a code diff, request headers, curl command, JSON payload, env vars, repeated provider keys, JWTs, database URLs, and an Azure connection string.

Run it through the CLI:

egressai redact tests/fixtures/messy_context.txt

The redacted output preserves the surrounding debugging context while replacing secrets with provider-aware placeholders such as:

OPENAI_API_KEY="{{EGRESSAI_SECRET_OPENAI_001}}"
GITHUB_TOKEN="{{EGRESSAI_SECRET_GITHUB_001}}"
"Authorization": "Bearer {{EGRESSAI_TOKEN_JWT_001}}"
DATABASE_URL="{{EGRESSAI_SECRET_DB_URL_001}}"

Exit Codes

By default, CLI commands exit 0 even when findings are detected.

With --fail-on-findings:

  • exits 0 when no findings are detected
  • exits 1 when findings are detected
  • exits 2 for CLI usage errors

Supported Secret Types

Initial support includes:

  • OpenAI API keys
  • Anthropic API keys
  • Google/Gemini API keys
  • GitHub tokens
  • GitLab tokens
  • AWS access keys
  • Stripe keys
  • Slack tokens
  • npm tokens, including .npmrc auth tokens and NPM_TOKEN=npm_... env values
  • PyPI tokens
  • Hugging Face tokens
  • JWTs, including JWT-like tokens with non-base64url signature suffixes
  • private key blocks
  • database URLs, including JSON-escaped URL values such as postgres:\/\/...
  • Azure connection strings
  • generic .env-style secret assignments

Provider mappings are covered by tests so each supported detector returns the expected EgressAI type, detector name, and placeholder subtype.

The test suite includes a messy real-world fixture with a pasted user report, code diff, curl commands, runtime env vars, JSON payloads, repeated secrets, and multiple provider token types.

Release Notes

0.1.5

  • Added hook-only Codex plugin scaffolding.
  • Added local egressai.codex_hook hook runner and egressai-codex-hook console script.

0.1.4

  • Expanded README examples and usage documentation.

0.1.3

  • Added finding line and column metadata.
  • Added same-session restore support through RedactionEngine.restore().
  • Added a messy real-world fixture corpus.
  • Added JSON-escaped database URL redaction.
  • Added egressai scan --jsonl.

Maintainer Notes

Every user-visible change should update this README in the same change set.

Before publishing:

python3 -m pytest
python3 -m build
python3 -m twine check dist/egressai-*

Publish the current release artifacts:

LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 PYTHONIOENCODING=utf-8 python3 -m twine upload dist/egressai-0.1.5*

Project details


Download files

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

Source Distribution

egressai-0.1.6.tar.gz (21.7 kB view details)

Uploaded Source

Built Distribution

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

egressai-0.1.6-py3-none-any.whl (14.5 kB view details)

Uploaded Python 3

File details

Details for the file egressai-0.1.6.tar.gz.

File metadata

  • Download URL: egressai-0.1.6.tar.gz
  • Upload date:
  • Size: 21.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for egressai-0.1.6.tar.gz
Algorithm Hash digest
SHA256 4429509e3da668d21714135bf0d5f3bd20e87a689a9f7bc876493ce8ef0d477b
MD5 2fdfde73925924d5ca71d750529e2d53
BLAKE2b-256 4e041ebe5e9fef1d65bdcff8e1aff854b58fc2e400ba5865b47d42525a897bfc

See more details on using hashes here.

File details

Details for the file egressai-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: egressai-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 14.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for egressai-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 5c7fde87e59b0c8a6aeff5e3967fae97dbf87da2003e35f225d2a63e2ca3c756
MD5 53ecee323af24aad71f9e508f1694b66
BLAKE2b-256 4f8ca61d04b77cc3ce574575e82c838a64860b830d2e834967bff2da875a0ffc

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 Pingdom Monitoring Sentry Error logging StatusPage Status page