Skip to content

Fix/security validate profile image url#382

Open
Sharaf0 wants to merge 23 commits into
acryldata:masterfrom
Sharaf0:fix/security-validate-profile-image-url
Open

Fix/security validate profile image url#382
Sharaf0 wants to merge 23 commits into
acryldata:masterfrom
Sharaf0:fix/security-validate-profile-image-url

Conversation

@Sharaf0

@Sharaf0 Sharaf0 commented Apr 29, 2026

Copy link
Copy Markdown

Summary

Adds server-side validation for pictureLink URL fields on corpUserEditableInfo and corpGroupEditableInfo aspects to prevent browser-side SSRF, credential harvesting, and content injection attacks via the "Edit Profile → Image URL" field.

Previously, any arbitrary URL (including javascript:, data:, file:, or internal network addresses) could be stored as a profile image URL with no validation at any layer.

What Changed

New: UrlValidator (metadata-io)

An AspectPayloadValidator plugin that validates pictureLink URLs before persistence:

  • HTTPS-only: Rejects http://, javascript:, data:, file:, and other non-HTTPS schemes
  • Internal host blocking: Blocks localhost, 127.0.0.1, ::1, 169.254.169.254 (cloud metadata endpoint), and all RFC 1918 private ranges (10.x, 172.16-31.x, 192.168.x)
  • DNS resolution check: Rejects URLs with unresolvable hostnames
  • Default avatar allowed: The relative path assets/… used for default avatars continues to work

Modified: SpringStandardPluginConfiguration (metadata-service/factories)

Registered the UrlValidator bean for corpuser/corpUserEditableInfo and corpGroup/corpGroupEditableInfo on CREATE, CREATE_ENTITY, UPSERT, UPDATE, and PATCH operations.

Updated: docs/how/updating-datahub.md

Added an entry under "Other Notable Changes" documenting the behavioral change.

Testing

  • 12 unit tests covering: valid HTTPS URLs, default avatar path, HTTP rejection, javascript: rejection, data: rejection, file: rejection, localhost blocking, cloud metadata IP blocking, loopback IP blocking, private network IP blocking, corp group validation, and isInternalHost() unit tests
  • All 12 tests pass locally (TestNG + Mockito)

Checklist

  • The PR conforms to DataHub's Contributing Guideline (particularly PR Title Format)
  • Links to related issues (if applicable) — No existing issue; discovered during security audit
  • Tests for the changes have been added/updated (if applicable)
  • Docs related to the changes have been added/updated (if applicable)
  • For any breaking change/potential downtime/deprecation/big changes an entry has been made in Updating DataHub

@Sharaf0 Sharaf0 force-pushed the fix/security-validate-profile-image-url branch from 7c892fb to 15f6eed Compare April 29, 2026 22:01
Sharaf0 added 6 commits May 1, 2026 01:25
Add server-side validation for pictureLink URLs on corpUserEditableInfo
and corpGroupEditableInfo aspects. The new UrlValidator:

- Enforces HTTPS-only scheme (blocks http, javascript, data, file, etc.)
- Blocks internal/private network addresses (localhost, 127.0.0.1, ::1,
  169.254.169.254, RFC1918 ranges) to prevent SSRF attacks
- Allows the default avatar relative path (assets/...)
- Rejects URLs with unresolvable hostnames

Includes 12 unit tests covering valid URLs, scheme enforcement, and
internal host blocking.
…ose() from after the mutation promise chain into the .then() block so the modal stays open when the server rejects the input (e.g. URL validation failure). Previously the modal closed immediately on save, giving the false impression that the change was persisted.
When the mutation to update profile is rejected by the server (e.g.
invalid URL), reset both the React state and antd form fields back to
the original editModalData values. This prevents the rejected value
from persisting in the modal when it is reopened.
Skip validation for empty or blank URLs so users can clear their
profile image. Adds testEmptyPictureLinkAllowed test case.
Add configuration flags for the UrlValidator under
metadataChangeProposal.validation.urlValidation:
- enabled: enable/disable the validator (default: true)
- allowHttp: allow http:// URLs in addition to https:// (default: false)
- extraDenyHosts: additional hostnames/IPs to block
- extraDenyCidrs: reserved for future CIDR-based blocking

Wire configuration through UrlValidationConfig POJO,
MCPValidationConfig, and SpringStandardPluginConfiguration with
@ConditionalOnProperty for the enabled flag.

Add 3 new tests covering allowHttp and extraDenyHosts configuration.
@Sharaf0 Sharaf0 force-pushed the fix/security-validate-profile-image-url branch from 75ebcca to bf29741 Compare April 30, 2026 23:26
Add metadataChangeProposal.validation.urlValidation.* properties
to NON_SENSITIVE_PROPERTIES in PropertiesCollectorConfigurationTest
to fix CI validation.
@Sharaf0 Sharaf0 force-pushed the fix/security-validate-profile-image-url branch from bf29741 to afeb023 Compare April 30, 2026 23:50
AdrianMachado and others added 4 commits May 8, 2026 16:45
…ature-availability stages (datahub-project#17091)

Co-authored-by: Jay <159848059+jayacryl@users.noreply.github.com>
Lombok skips generating setAllowHttp when it sees a hand-written one,
so allowedSchemes stays in sync automatically — no separate buildSchemes()
call to forget. Also removes unused extraDenyCidrs config.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
}

try {
InetAddress address = InetAddress.getByName(host);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTTP request might enable SSRF attack - critical severity
If an attacker can control the URL input leading into this http request, the attack might be able to perform an SSRF attack. This kind of attack is even more dangerous is the application returns the result of the URL fetch to the user. It can serve as an initial access point for an attacker for stealing credentials in the cloud.

Show fix

Remediation: If possible, only allow requests to verified domains. If not, consult the article linked above to learn about other mitigating techniques such as disabling redirects, blocking private IPs and making sure private services have internal authentication. If you return data coming from the request to the user, validate the data before returning it to make sure you don't return random data.

Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

@Sharaf0 Sharaf0 force-pushed the fix/security-validate-profile-image-url branch from 5e7bd21 to 7585b6a Compare May 12, 2026 00:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.