Try the interactive demo · Security policy
IssueSafe sanitizes developer logs and creates shareable bug reports without uploading anything. Its deterministic, local-first workflow is deliberately reviewable:
Raw log → detect common sensitive patterns → review redactions → export
IssueSafe detects common sensitive patterns. Review the result before sharing.
Logs copied into issues, chats, support tickets, and AI assistants can contain authorization headers, credentials, identities, network addresses, or local usernames. Cleaning those logs by hand is slow and easy to get wrong. Fully automatic redaction is not a trustworthy guarantee either: a broad pattern can remove useful context, while an unfamiliar secret can pass through.
IssueSafe occupies the useful middle. It finds a conservative set of common patterns, assigns stable placeholders, and gives you an explicit review step. It is not a replacement for Gitleaks or GitHub secret scanning, a compliance product, a hosted log platform, or an AI classifier.
IssueSafe requires Node.js 22 or newer and is published on npm as @aminhanifm/issuesafe.
npm install --global @aminhanifm/issuesafe
issuesafe --versionRun without a global install:
npx @aminhanifm/issuesafe --version# Sanitized text to stdout
issuesafe sanitize application.log
# File output (existing files are protected)
issuesafe sanitize application.log --output application.safe.log
# Standard input and versioned JSON
cat application.log | issuesafe sanitize --stdin --format json
# Standard input to sanitized text
cat application.log | issuesafe sanitize --stdin
# Keep diagnostically useful IP addresses and emails
issuesafe sanitize application.log --disable ip,email
# GitHub-ready Markdown
issuesafe issue application.log --title "Application fails during startup"
issuesafe issue application.log --output bug-report.md
# Deliberately replace an existing output
issuesafe sanitize application.log --output application.safe.log --forceNormal output goes to stdout; errors go to stderr. Successful processing returns 0. Invalid usage and processing failures return 2. --no-color, --help, and --version are supported. IssueSafe never prints the sensitive input as part of an error message.
The static browser application uses the same framework-independent engine as the CLI.
- Paste a log, choose a synthetic scenario, or load a UTF-8
.log,.txt, or.jsonfile up to 2 MiB. - Compare original and sanitized views. Affected lines are highlighted without HTML injection.
- Keep or redact each finding, or toggle a whole category. IP findings can remain visible when they are useful for debugging.
- Copy or download a sanitized log or a GitHub-ready Markdown issue.
- Clear the input to discard all in-memory review state.
The application does not copy automatically. It does not write raw input to local storage, session storage, cookies, IndexedDB, URLs, or analytics. It makes no runtime network requests after the page loads.
| Category | Conservative detection |
|---|---|
| Authorization | Bearer, Basic, API-key-style, proxy authorization, and common API-key headers |
| JWT | Three-part JWT-shaped values |
| Private keys | Complete PEM-style private-key blocks |
| Cookies and sessions | Cookie, Set-Cookie, and common session assignments |
| URL parameters | token, access_token, api_key, key, secret, password, session, signature, auth |
| Conventional email-address shapes | |
| IP addresses | Valid IPv4 and common IPv6 shapes; category can be disabled |
| Home paths | Username portion of C:\Users\…, /Users/…, and /home/… |
| Credentials | Common assignments and credentials embedded in supported database URLs |
Authorization: Bearer fake_documentation_token
requester: developer@example.invalid
GET https://api.example.invalid/orders?access_token=synthetic_only
Authorization: Bearer [TOKEN_1]
requester: [EMAIL_1]
GET https://api.example.invalid/orders?access_token=[TOKEN_2]
Repeated values receive the same in-memory placeholder during one analysis. Different values in the same placeholder family increment deterministically. The private mapping resets for every analysis and never appears in exported results.
- Browser processing is local and the hosted application has no backend.
- Raw logs are not uploaded, retained, or placed in browser storage.
- The core engine has no React, browser, or Node dependency.
- The versioned public result never includes original matched values.
- Overlap resolution is explicit and deterministic: private-key blocks outrank their contents; authorization and cookie detections outrank generic matches.
- User-provided content is rendered as text, not injected as HTML.
- Samples and tests use synthetic values,
example.invaliddomains, and documentation address ranges.
These are implementation properties, not a claim that output is completely safe. A compromised credential must be revoked or rotated; redacting it from a report does not remediate exposure. Read the threat model and reporting policy.
Pattern matching has false positives and false negatives. In particular:
- Custom credential names, opaque vendor formats, secrets split across lines, and transformed or encrypted values may not be detected.
- An arbitrary JWT-shaped value, IP address, email-like identifier, or home-path segment may be benign.
- Cookie headers are redacted as a unit, which can remove non-sensitive cookie debugging context.
- IPv6 recognition is intentionally conservative and does not cover every valid presentation.
- File decoding in the browser accepts UTF-8 only; the CLI expects UTF-8 text.
- IssueSafe does not scan source repositories, history, binary files, archives, or remote systems.
Always review surrounding text and rotate exposed credentials.
import {
analyzeLog,
applyRedactions,
createIssueReport,
type AnalysisResult,
type Finding,
} from "@aminhanifm/issuesafe";
const result: AnalysisResult = analyzeLog(rawLog, {
disabledCategories: ["ip"],
});
const selected: Finding[] = result.findings.map((finding) => ({
...finding,
enabled: finding.category !== "email",
}));
const sanitized = applyRedactions(rawLog, selected);
const markdown = createIssueReport(
{ ...result, sanitizedText: sanitized, findings: selected },
{ title: "Application fails during startup", reviewed: true },
);The AnalysisResult schema is versioned separately from the package. Within 0.x, documented exported types and behavior are treated as stable but may receive breaking changes in a minor release with changelog notice. Public findings include location, category, detector ID, placeholder, and enabled state; never the matched value.
src/core/ deterministic detectors, overlap resolution, reporting
src/cli/ Node-only file/stdin/stdout adapter using Commander
demo/src/ React review interface; imports the same core directly
test/ detector, redaction, reporting, and CLI tests
docs/ release and design artifacts
The core package depends only on language primitives. Detectors produce private candidates; priority-based overlap resolution chooses non-overlapping ranges; placeholders are assigned after resolution; the public result is then built and sanitized.
npm ci
npm run dev
npm run format
npm run lint
npm run typecheck
npm test
npm run test:coverage
npm run build
npm run build:demo
npm run pack:dry-run
npm run verify:package
npm run checkverify:package creates a tarball in a temporary directory, installs it as a consumer, and exercises the installed CLI. CI runs on Node.js 22 and 24 on Ubuntu and Windows.
Focused issues and pull requests are welcome. Read CONTRIBUTING.md, the Code of Conduct, and SECURITY.md before submitting. Never include real credentials or private logs in fixtures, issues, or screenshots.
- Additional conservative vendor-specific token shapes backed by public documentation
- Import/export of redaction decisions without original values
- Expanded accessibility and cross-browser regression coverage
IssueSafe is available under the MIT License.