feat(finding): redact sensitive finding values in API (#7500) - #7587
Open
Hedi (heditar) wants to merge 13 commits into
Open
feat(finding): redact sensitive finding values in API (#7500)#7587Hedi (heditar) wants to merge 13 commits into
Hedi (heditar) wants to merge 13 commits into
Conversation
Adds a finding_is_sensitive column and its JPA mapping. Each finding-capable output processor now hardcodes the sensitivity of the finding type it produces: Credentials is the only sensitive one today, since its value is a username:password or username:hash pair, while every other processor emits usernames, hosts, CVEs, ports or free text. A sensitive finding value is redacted whenever the API serializes it (entity, aggregated/related search outputs and finding summary): the identity part is kept so an operator can still tell which account is affected, the secret part is replaced by a mask. The database keeps the cleartext value, which deduplication, correlation and attack paths rely on, so the full value of a sensitive finding cannot be retrieved through the API. Existing credentials findings are backfilled by the migration so already detected credentials are redacted too.
Contributor
|
📖 Documentation check — ✅ Passed 12 functional file(s), 1 doc file(s) changed. No documentation gaps detected. |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses #7500 by introducing a persisted “sensitive” flag on Finding and ensuring sensitive finding values (notably Credentials) are redacted everywhere the REST API serializes them, while keeping the cleartext value in the database for correlation/deduplication.
Changes:
- Add
findings.finding_is_sensitive(migration + entity + repository upsert support) and propagate a per-processor sensitivity decision into persisted findings. - Redact sensitive
finding_valueat serialization time (Jackson serializer forFinding) and in DTO mappings (FindingMapper,findingSummary) while exposingfinding_is_sensitive. - Add/adjust backend tests, update docs, and extend frontend API types to include
finding_is_sensitive(nice coverage with dedicated redactor tests and API assertions).
Reviewed changes
Copilot reviewed 41 out of 42 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| openaev-model/src/main/java/io/openaev/helper/FindingValueSerializer.java | New Jackson serializer that redacts finding_value based on the enclosing Finding sensitivity flag. |
| openaev-model/src/main/java/io/openaev/helper/FindingValueRedactor.java | New redaction utility implementing masking rules (identity-preserving where applicable). |
| openaev-model/src/main/java/io/openaev/database/repository/FindingRepository.java | Extend native upsert to persist/update finding_is_sensitive. |
| openaev-model/src/main/java/io/openaev/database/model/Finding.java | Add finding_is_sensitive field + apply serializer to finding_value. |
| openaev-front/src/utils/api-types.d.ts | Add finding_is_sensitive to relevant frontend API types and clarify docs for redacted values. |
| openaev-api/src/test/java/io/openaev/utils/fixtures/FindingFixture.java | Mark credentials fixture findings as sensitive. |
| openaev-api/src/test/java/io/openaev/rest/finding/FindingServiceTest.java | Update service test calls for the new sensitivity parameter. |
| openaev-api/src/test/java/io/openaev/rest/finding/FindingApiTest.java | Assert API redaction + finding_is_sensitive behavior and verify DB keeps cleartext. |
| openaev-api/src/test/java/io/openaev/output_processor/OutputProcessorIntegrationTest.java | Guard sensitivity matrix across all finding-capable processors. |
| openaev-api/src/test/java/io/openaev/output_processor/CredentialsOutputProcessorTest.java | Assert credentials processor is flagged sensitive. |
| openaev-api/src/test/java/io/openaev/helper/FindingValueRedactorTest.java | New unit tests for redaction rules and entity serialization behavior. |
| openaev-api/src/main/java/io/openaev/utils/mapper/FindingMapper.java | Redact value + expose sensitivity in aggregated/related finding DTOs. |
| openaev-api/src/main/java/io/openaev/rest/finding/form/FindingSummaryOutput.java | Add finding_is_sensitive and clarify that finding_value may be redacted. |
| openaev-api/src/main/java/io/openaev/rest/finding/form/AggregatedFindingOutput.java | Add finding_is_sensitive and clarify redaction semantics in schema docs. |
| openaev-api/src/main/java/io/openaev/rest/finding/FindingWriter.java | Thread sensitivity into persistence calls. |
| openaev-api/src/main/java/io/openaev/rest/finding/FindingService.java | Propagate sensitivity through finding generation and redact in summary output. |
| openaev-api/src/main/java/io/openaev/output_processor/FindingCapableOutputProcessor.java | Add per-processor sensitivity flag and pass it into finding generation (contains a blocking parameter-order bug). |
| openaev-api/src/main/java/io/openaev/output_processor/VulnerabilityOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/UsernameOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/TextOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/SidOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/ShareOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/PortScanOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/PortOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/PasswordPolicyOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/NumberOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/KerberoastableAccountOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/IPv6OutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/IPv4OutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/GroupOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/FileOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/EmailOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/DelegationOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/CVEOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/CredentialsOutputProcessor.java | Pass SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/ComputerOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/AsreproastableAccountOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/AdminUsernameOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/ActionOutputOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/output_processor/AccountWithPasswordNotRequiredOutputProcessor.java | Pass NOT_SENSITIVE to the finding-capable base constructor. |
| openaev-api/src/main/java/io/openaev/migration/V6_20260824180000000__Add_finding_is_sensitive.java | Add and backfill finding_is_sensitive with idempotent DDL/DML. |
| docs/docs/usage/evaluate/findings/findings.md | Document sensitive findings behavior and clarify that secrets are not deleted from DB. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
#7500) Add a convenience constructor on FindingCapableOutputProcessor defaulting to NOT_SENSITIVE so only processors emitting secret material need to opt in explicitly. The type/sensitivity matrix in OutputProcessorIntegrationTest guards the default. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
#7500) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Drop the model-side FindingValueRedactor/FindingValueSerializer pair and keep the redaction in the API layer: FindingService.redact is used by the summary and the search mappers, and the read endpoint redacts the entity in a read only transaction so the cleartext value is never flushed back. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Password policy findings disclose the target password policy (minimum length, complexity, lockout...), which is exploitable material: they are now redacted like credentials, keeping the policy key visible. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Drop the identity-part exception: a sensitive value now always keeps a two character fragment, so a credential value no longer discloses the account name. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
A credential value no longer discloses the account name: each part separated by a colon keeps only a two character fragment, so admin:motdepasse is returned as ad******:mo******. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Hedi (heditar)
marked this pull request as ready for review
August 25, 2026 14:07
…7500) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #7500
Credentials discovered during a simulation were returned — and displayed — in cleartext on the Finding page. Sensitive finding types are now flagged and their value is redacted everywhere the REST API serializes it.
What changed
findings.finding_is_sensitive(defaultfalse), backfilled totruefor existingCredentialsrows.FindingCapableOutputProcessordefaults to non-sensitive; onlyCredentialsOutputProcessoropts in.OutputProcessorIntegrationTestguards the matrix, so declaring a new sensitive type is deliberate.FindingService.redact(...)masks every:-separated part, keeping a two character fragment —admin:motdepasse→ad******:mo******, a part shorter than 5 characters is masked entirely. Applied to the read endpoint, the summary and the search outputs (AggregatedFindingOutput/RelatedFindingOutput), which also exposefinding_is_sensitive.How to test:
Checklist