Smart Secrets and Hide Secrets
August 31, 2026 · View on GitHub
Hide Secrets and Hide private data share one redaction pipeline and one set of Preview decisions. Overlapping findings are rendered as non-overlapping segments with an ordered candidate stack. Keeping a secret finding changes that whole occurrence across all of its fragments, while text still covered by non-kept private-data findings remains redacted. The original segment appears only after every candidate in its stack is kept. The full overlap contract is described in HidePrivateData.md.
Smart Secrets is DevProjex's local, deterministic credential-detection engine. Hide Secrets is the opt-in switch that applies its decisions to produced output. It is off by default and adds no scan cost until enabled.
Detected values are replaced in place. The file, path, key name, and surrounding code remain available as context. DevProjex never describes an output as safe or clean: a finding means that a rule matched, while no findings means only that the current rules matched nothing.
Smart Secrets runs locally, uploads no code, uses no model, and never modifies the source tree.
One decided state
The same redaction decisions apply to every output built from the current selection:
- Preview;
- clipboard payloads;
- text, Markdown, JSON, and XML context exports;
- folder copies;
- ZIP copies.
If Preview shows a placeholder, every later output contains that placeholder. A finding kept as-is in Preview returns only that occurrence to its original value; the decision then applies to every output for the rest of the application session. The Preview context menu can apply the same decision in bulk to every occurrence of the rule or to every detected occurrence in the same file, and can hide those occurrences again as one action.
Individual and bulk keep-as-is decisions are intentionally session-only. They are not written to project profiles, so profiles never retain secret fingerprints or source locations. If a finding moves after a file change, it is treated as a new occurrence and redacted again.
Manual mark classes
A manual mark belongs to exactly one redaction class: Secret or Private data. The corresponding switch controls the whole class, including detector findings and manual marks; turning Hide Secrets off reveals Secret marks without changing Private-data marks. Creating a Secret mark in Preview enables Hide Secrets automatically. Persistent marks store only a keyed value identity and their class, never the original value. Store schema v4 migrates every mark created by schema v3 to the Secret class, preserving the behavior it had before classes existed.
Placeholders and identity
Each removed value is replaced with a deterministic placeholder:
DEVPROJEX_REDACTED[telegram-bot-api-token#1]
The rule id describes what matched. The index identifies a value within one produced output. Repeated occurrences of the same value under the same rule reuse the same index across files; different values receive different indexes.
Two detection tiers
The engine combines two complementary tiers.
Provider rules
DevProjex ships a reviewed managed port of the default Gitleaks
v8.30.1 configuration:
- 221 content rules recognize provider-shaped credentials in selected text;
- the one path-only PKCS#12 rule is intentionally excluded because a filename or opaque binary payload cannot be redacted in place;
- keyword prescreening limits which bounded regular expressions inspect a file;
- entropy thresholds and upstream allowlists preserve the pinned rule semantics;
gitleaks:allowsuppresses findings on that line;- expressions use the managed non-backtracking .NET engine with a timeout.
Scope-aware configuration rules
Gitleaks is deliberately conservative with short and low-entropy values. Smart Secrets therefore adds a structured tier for places where a key name and file shape are stronger evidence:
- credential URIs for PostgreSQL, MySQL, MongoDB, Redis, AMQP, and HTTP(S);
- ADO.NET and JDBC-style connection strings;
.env*and.npmrcassignments;ENVandARG KEY=valueassignments in Dockerfile and Containerfile variants; the legacyENV KEY valueform is also supported. A space-delimitedARG KEY valueis not treated as an assignment because Docker's ARG grammar defines onlyARG KEYandARG KEY=value;AuthorizationandProxy-Authorizationcredentials in.httpand.restrequest files, with the authentication scheme left visible;- every
Cookiepair value and the initialSet-Cookiepair value in.httpand.restrequest files; cookie names remain visible, andSet-Cookieattributes such asPath,HttpOnly, andMax-Agestay visible; - password fields in
.pgpass,pgpass.conf,.netrc, and_netrc; appsettings*.json,*.config,application*.yml,application*.yaml,*.tfvars,docker-compose*.yml, anddocker-compose*.yamlvalues;- quoted assignments in
settings.py.
Credential URIs and connection strings redact only the password segment. Host,
user, database, scheme, and other surrounding values remain visible. Credential
URIs on RFC 2606 documentation hosts (example.com, example.net,
example.org, their subdomains, and the .test, .example, and .invalid
TLDs) are not redacted. localhost is intentionally still inspected because
development credentials can be real secrets.
The structured tier reuses Smart Ignore's project-scope resolver and root facts.
The nearest marked project owns its descendants, so stack-specific vocabulary
does not leak between sibling or nested projects in a monorepo. Ordinary source
assignments such as var password = "test123" are outside this tier; provider-
shaped credentials in source remain covered by Gitleaks rules.
References and placeholders such as ${DB_PASSWORD}, $(DbPassword),
%DB_PASSWORD%, {{ secret }}, <password>, and empty values are not redacted.
Common template values such as changeme, your-password-here, replace_me,
placeholder, null, none, your-api-key-here-style templates, and repeated
non-numeric characters are also ignored. These checks match whole values or
interpolation syntax, never a substring inside an otherwise credential-shaped
value. Weak literal values such as password, admin, 0000, and 123456
still match in recognized configuration shapes.
The provider tier intentionally preserves Gitleaks' upstream substring-based stopwords, including their false-negative trade-off. The scope-aware tier does not copy that behaviour: its placeholder allowlist is whole-value only.
Smart Ignore and Smart Secrets share an engine shape but have opposite failure biases. Smart Ignore leaves a directory visible when artifact evidence is missing, because hiding source is the expensive error. In a recognized configuration shape, Smart Secrets redacts a sensitive literal when further evidence is missing, because a missed credential can leave the user's control and a false positive can be reversed per occurrence in Preview.
The pinned TOML is embedded and verified by SHA-256 before compilation. DevProjex
does not bundle or launch Gitleaks and has no native scanning dependency.
Attribution is recorded in
THIRD-PARTY-NOTICES.md.
Text, binary files, and limits
Only selected text files are inspected. Binary files are not scanned and pass through unchanged in folder and ZIP copies; context documents continue to mark them as binary without embedding their bytes.
A selected text file above 16 MiB is not scanned, and what happens next depends on what
the surface produces. Documents — preview, clipboard, and every context format — omit
its text and mark the entry, which is what they already do for a file that large with
Hide Secrets off. A folder or ZIP project copy reproduces bytes rather than rendering
them, so it leaves the file out of the copy entirely and names it in
DEVPROJEX-NOTICE.txt under the copy's root; the rest of the project is copied
normally. One unreadable file therefore costs that file, never the whole operation.
Detection errors and regex timeouts still stop the operation on every surface. Text that
was never inspected is never emitted, an uninspected file is never passed off as
inspected, and a file left out of a copy is always named.
The count scan stores compact spans, rule ids, file fingerprints, and hashed value identities in a bounded LRU cache. It does not retain complete source or redacted strings. Changed files are rescanned individually; unchanged files reuse their findings. Full transformed content is produced lazily for Preview or export, and temporary data is removed after completion or cancellation.
Folder and ZIP copies
With Hide Secrets enabled, a project copy is intentionally not byte-for-byte
faithful to the source. Matching text changes, and the copy may not build or run.
Desktop and TUI confirm this, and CLI --dry-run
reports it before writing.
Directory structure, included empty folders, timestamps, and binary bytes retain the normal project-copy contract. The destination remains outside the source project, and the source stays read-only.
Counts and interaction
Hide Secrets has its own content-transformation section; it is not a path filter and never changes the tree, Smart Ignore, Git mode, roots, or extensions.
No count is shown before a completed scan. During inspection the existing status
surface reports scanning. After completion, the label shows the number of
detected values; when keep-as-is decisions leave fewer values hidden, it shows
the detected and still-hidden counts side by side, and the row's status
indicator reports both numbers in text. A zero-result label explicitly
says that no values were detected; it does not claim that the selection is safe.
analyze reports matched and redacted counts under the same contract.
In Desktop Preview, click a highlighted occurrence to toggle keep-as-is, or move
between findings with Alt+↓ / Alt+↑ (⌥ on macOS) and toggle the active
one with Enter. The Preview scrollbar marks every line with a finding and
scrolls to the line when a marker is clicked; a marker does not disappear when
its finding is kept as-is. In Terminal Workspace,
[ and ] navigate findings and Enter or Space toggles the active
occurrence.
CLI
Use the dedicated additive option:
devprojex export context . --hide-secrets --format markdown -o ../context.md
devprojex export project . --hide-secrets --as zip -o ../project-redacted.zip --dry-run
devprojex analyze . --hide-secrets --findings --fail-on-findings
analyze --findings lists the effective findings as rule id, category, relative
path, and one-based source line — never the detected value — and
--fail-on-findings returns a policy exit code when any effective finding
exists, so a pipeline can gate on redaction before exporting.
--hide-secrets does not replace the --exclude collection. The v5 token
--exclude hide-secrets remains accepted for compatibility, but is hidden from
new help and completion output. An explicit --hide-secrets false disables a
value inherited through a profile or the legacy token for that invocation.
MCP
In MCP server mode (devprojex mcp) secret redaction is not a switch: it is
always enabled for returned file content, stored context packs, and search —
matching runs against the redacted text, not the original. There is no server
flag to disable it, and tool schemas intentionally expose no redaction controls,
so neither a configuration mistake nor the connected agent can turn it off.
Private-data redaction remains a separate, opt-in server flag; see
McpServer.md for the full security model.
The missing schema control guarantees that an agent cannot disable the redaction
pass. Detection itself covers common secret formats but remains heuristic, not a
guarantee. Review each pack before publishing it outside your environment.
Some known documentation and placeholder values in provider rules, including
AWS-shaped keys containing EXAMPLE and bodies made from alphabetic sequences,
are intentionally allowlisted in line with upstream Gitleaks rules to reduce
fixture and example noise. This provider-tier exception does not exempt every
credential-shaped assignment: scope-aware configuration detection still evaluates
those values, and real secret formats remain subject to detection and redaction.
Updating the rule source
A provider-rule update is a reviewed source change, not a runtime download:
- pin a Gitleaks release;
- replace the embedded
config/gitleaks.tomlsource; - update the expected SHA-256 and reviewed rule counts;
- regenerate the attributed corpus fixture;
- run positive, negative, timeout, determinism, scope, and cross-output tests;
- review RE2-to-.NET differences and every newly path-only rule.
Identical input, selection, overrides, and application version produce identical decisions.