@strapi/admin 5.56.0 → 5.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/admin/src/components/Filters.js +1 -1
- package/dist/admin/admin/src/components/Filters.js.map +1 -1
- package/dist/admin/admin/src/components/Filters.mjs +1 -1
- package/dist/admin/admin/src/components/Filters.mjs.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Boolean.js +3 -2
- package/dist/admin/admin/src/components/FormInputs/Boolean.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Boolean.mjs +3 -2
- package/dist/admin/admin/src/components/FormInputs/Boolean.mjs.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Enumeration.js +2 -2
- package/dist/admin/admin/src/components/FormInputs/Enumeration.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Enumeration.mjs +2 -2
- package/dist/admin/admin/src/components/FormInputs/Enumeration.mjs.map +1 -1
- package/dist/admin/admin/src/components/MediaLibraryBanner.js +38 -2
- package/dist/admin/admin/src/components/MediaLibraryBanner.js.map +1 -1
- package/dist/admin/admin/src/components/MediaLibraryBanner.mjs +18 -2
- package/dist/admin/admin/src/components/MediaLibraryBanner.mjs.map +1 -1
- package/dist/admin/admin/src/components/RelativeTime.js +9 -0
- package/dist/admin/admin/src/components/RelativeTime.js.map +1 -1
- package/dist/admin/admin/src/components/RelativeTime.mjs +10 -1
- package/dist/admin/admin/src/components/RelativeTime.mjs.map +1 -1
- package/dist/admin/admin/src/components/TopBanners.js +52 -0
- package/dist/admin/admin/src/components/TopBanners.js.map +1 -0
- package/dist/admin/admin/src/components/TopBanners.mjs +30 -0
- package/dist/admin/admin/src/components/TopBanners.mjs.map +1 -0
- package/dist/admin/admin/src/constants.js +14 -0
- package/dist/admin/admin/src/constants.js.map +1 -1
- package/dist/admin/admin/src/constants.mjs +14 -0
- package/dist/admin/admin/src/constants.mjs.map +1 -1
- package/dist/admin/admin/src/features/Tracking.js +28 -8
- package/dist/admin/admin/src/features/Tracking.js.map +1 -1
- package/dist/admin/admin/src/features/Tracking.mjs +29 -10
- package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.js +4 -20
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.js.map +1 -1
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs +4 -20
- package/dist/admin/admin/src/layouts/AuthenticatedLayout.mjs.map +1 -1
- package/dist/admin/admin/src/layouts/useAuthenticatedAccessTracking.js +59 -0
- package/dist/admin/admin/src/layouts/useAuthenticatedAccessTracking.js.map +1 -0
- package/dist/admin/admin/src/layouts/useAuthenticatedAccessTracking.mjs +37 -0
- package/dist/admin/admin/src/layouts/useAuthenticatedAccessTracking.mjs.map +1 -0
- package/dist/admin/admin/src/pages/Auth/components/ResetPassword.js +6 -12
- package/dist/admin/admin/src/pages/Auth/components/ResetPassword.js.map +1 -1
- package/dist/admin/admin/src/pages/Auth/components/ResetPassword.mjs +6 -12
- package/dist/admin/admin/src/pages/Auth/components/ResetPassword.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/SettingsNav.js +10 -2
- package/dist/admin/admin/src/pages/Settings/components/SettingsNav.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/components/SettingsNav.mjs +10 -2
- package/dist/admin/admin/src/pages/Settings/components/SettingsNav.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.js +6 -56
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.js.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.mjs +6 -56
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.js +217 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.js.map +1 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.mjs +195 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.mjs.map +1 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.js +185 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.js.map +1 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.mjs +162 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.mjs.map +1 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.js +342 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.js.map +1 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.mjs +320 -0
- package/dist/admin/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.mjs.map +1 -0
- package/dist/admin/admin/src/services/admin.js +11 -1
- package/dist/admin/admin/src/services/admin.js.map +1 -1
- package/dist/admin/admin/src/services/admin.mjs +11 -2
- package/dist/admin/admin/src/services/admin.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +76 -4
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +76 -4
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/admin/src/utils/browserStrapi.js +1 -1
- package/dist/admin/admin/src/utils/browserStrapi.js.map +1 -1
- package/dist/admin/admin/src/utils/browserStrapi.mjs +1 -1
- package/dist/admin/admin/src/utils/browserStrapi.mjs.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.js +27 -3
- package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
- package/dist/admin/admin/src/utils/getFetchClient.mjs +26 -3
- package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js +52 -22
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs +53 -23
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.js +16 -29
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.mjs +18 -31
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AdminSeatInfo.mjs.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.js +473 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.js.map +1 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.mjs +471 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.mjs.map +1 -0
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js +8 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.js.map +1 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs +8 -1
- package/dist/admin/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.mjs.map +1 -1
- package/dist/admin/index.js +1 -0
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/shared/utils/get-project-type.js +49 -0
- package/dist/admin/shared/utils/get-project-type.js.map +1 -0
- package/dist/admin/shared/utils/get-project-type.mjs +46 -0
- package/dist/admin/shared/utils/get-project-type.mjs.map +1 -0
- package/dist/admin/src/components/MediaLibraryBanner.d.ts +10 -1
- package/dist/admin/src/components/TopBanners.d.ts +8 -0
- package/dist/admin/src/constants.d.ts +10 -0
- package/dist/admin/src/features/Tracking.d.ts +12 -1
- package/dist/admin/src/layouts/useAuthenticatedAccessTracking.d.ts +6 -0
- package/dist/admin/src/pages/Settings/pages/ApplicationInfo/ApplicationInfoPage.d.ts +1 -1
- package/dist/admin/src/pages/Settings/pages/ApplicationInfo/components/DiagnosticSnapshotModal.d.ts +12 -0
- package/dist/admin/src/pages/Settings/pages/ApplicationInfo/components/PlanCard.d.ts +14 -0
- package/dist/admin/src/pages/Settings/pages/ApplicationInfo/components/SupportCard.d.ts +2 -0
- package/dist/admin/src/services/admin.d.ts +2 -2
- package/dist/admin/src/types/permissions.d.ts +1 -0
- package/dist/admin/src/utils/getFetchClient.d.ts +25 -0
- package/dist/ee/admin/src/hooks/useLicenseLimits.d.ts +29 -0
- package/dist/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/AIUsage.d.ts +6 -1
- package/dist/ee/admin/src/pages/SettingsPage/pages/ApplicationInfoPage/components/LicenseInfo.d.ts +2 -0
- package/dist/ee/admin/src/pages/SettingsPage/pages/AuditLogs/utils/getActionTypesDefaultMessages.d.ts +7 -0
- package/dist/ee/server/src/audit-logs/entitlements.d.ts +8 -0
- package/dist/ee/server/src/audit-logs/entitlements.d.ts.map +1 -0
- package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts +16 -0
- package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/admin.d.ts +36 -10
- package/dist/ee/server/src/controllers/admin.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/authentication-utils/middlewares.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/authentication-utils/utils.d.ts +8 -2
- package/dist/ee/server/src/controllers/authentication-utils/utils.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/authentication.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/index.d.ts +36 -10
- package/dist/ee/server/src/controllers/index.d.ts.map +1 -1
- package/dist/ee/server/src/controllers/user.d.ts.map +1 -1
- package/dist/ee/server/src/index.d.ts +40 -11
- package/dist/ee/server/src/index.d.ts.map +1 -1
- package/dist/ee/server/src/services/index.d.ts +4 -1
- package/dist/ee/server/src/services/index.d.ts.map +1 -1
- package/dist/ee/server/src/services/metrics.d.ts.map +1 -1
- package/dist/ee/server/src/services/persist-tables.d.ts.map +1 -1
- package/dist/ee/server/src/services/seat-enforcement.d.ts +3 -1
- package/dist/ee/server/src/services/seat-enforcement.d.ts.map +1 -1
- package/dist/server/ee/server/src/audit-logs/entitlements.js +25 -0
- package/dist/server/ee/server/src/audit-logs/entitlements.js.map +1 -0
- package/dist/server/ee/server/src/audit-logs/entitlements.mjs +23 -0
- package/dist/server/ee/server/src/audit-logs/entitlements.mjs.map +1 -0
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.js +20 -8
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.js.map +1 -1
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs +19 -9
- package/dist/server/ee/server/src/audit-logs/services/lifecycles.mjs.map +1 -1
- package/dist/server/ee/server/src/controllers/admin.js +79 -7
- package/dist/server/ee/server/src/controllers/admin.js.map +1 -1
- package/dist/server/ee/server/src/controllers/admin.mjs +79 -7
- package/dist/server/ee/server/src/controllers/admin.mjs.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js +28 -10
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs +28 -10
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/utils.js +2 -2
- package/dist/server/ee/server/src/controllers/authentication-utils/utils.js.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/utils.mjs +2 -2
- package/dist/server/ee/server/src/controllers/authentication-utils/utils.mjs.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication.js +11 -11
- package/dist/server/ee/server/src/controllers/authentication.js.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication.mjs +11 -11
- package/dist/server/ee/server/src/controllers/authentication.mjs.map +1 -1
- package/dist/server/ee/server/src/controllers/user.js +7 -8
- package/dist/server/ee/server/src/controllers/user.js.map +1 -1
- package/dist/server/ee/server/src/controllers/user.mjs +8 -9
- package/dist/server/ee/server/src/controllers/user.mjs.map +1 -1
- package/dist/server/ee/server/src/index.js +2 -0
- package/dist/server/ee/server/src/index.js.map +1 -1
- package/dist/server/ee/server/src/index.mjs +2 -0
- package/dist/server/ee/server/src/index.mjs.map +1 -1
- package/dist/server/ee/server/src/services/metrics.js +9 -7
- package/dist/server/ee/server/src/services/metrics.js.map +1 -1
- package/dist/server/ee/server/src/services/metrics.mjs +9 -7
- package/dist/server/ee/server/src/services/metrics.mjs.map +1 -1
- package/dist/server/ee/server/src/services/persist-tables.js +3 -4
- package/dist/server/ee/server/src/services/persist-tables.js.map +1 -1
- package/dist/server/ee/server/src/services/persist-tables.mjs +3 -4
- package/dist/server/ee/server/src/services/persist-tables.mjs.map +1 -1
- package/dist/server/ee/server/src/services/role.js +2 -2
- package/dist/server/ee/server/src/services/role.js.map +1 -1
- package/dist/server/ee/server/src/services/role.mjs +1 -1
- package/dist/server/ee/server/src/services/role.mjs.map +1 -1
- package/dist/server/ee/server/src/services/seat-enforcement.js +20 -20
- package/dist/server/ee/server/src/services/seat-enforcement.js.map +1 -1
- package/dist/server/ee/server/src/services/seat-enforcement.mjs +20 -20
- package/dist/server/ee/server/src/services/seat-enforcement.mjs.map +1 -1
- package/dist/server/ee/server/src/services/user.js +1 -2
- package/dist/server/ee/server/src/services/user.js.map +1 -1
- package/dist/server/ee/server/src/services/user.mjs +2 -3
- package/dist/server/ee/server/src/services/user.mjs.map +1 -1
- package/dist/server/ee/server/src/utils/sso-lock.js +2 -2
- package/dist/server/ee/server/src/utils/sso-lock.js.map +1 -1
- package/dist/server/ee/server/src/utils/sso-lock.mjs +1 -1
- package/dist/server/ee/server/src/utils/sso-lock.mjs.map +1 -1
- package/dist/server/server/src/audit-logs/admin-users.js +3 -3
- package/dist/server/server/src/audit-logs/admin-users.js.map +1 -1
- package/dist/server/server/src/audit-logs/admin-users.mjs +2 -2
- package/dist/server/server/src/audit-logs/admin-users.mjs.map +1 -1
- package/dist/server/server/src/audit-logs/auth.js +72 -0
- package/dist/server/server/src/audit-logs/auth.js.map +1 -0
- package/dist/server/server/src/audit-logs/auth.mjs +67 -0
- package/dist/server/server/src/audit-logs/auth.mjs.map +1 -0
- package/dist/server/server/src/audit-logs/tokens.js +3 -3
- package/dist/server/server/src/audit-logs/tokens.js.map +1 -1
- package/dist/server/server/src/audit-logs/tokens.mjs +2 -2
- package/dist/server/server/src/audit-logs/tokens.mjs.map +1 -1
- package/dist/server/server/src/audit-logs/webhooks.js +2 -2
- package/dist/server/server/src/audit-logs/webhooks.js.map +1 -1
- package/dist/server/server/src/audit-logs/webhooks.mjs +1 -1
- package/dist/server/server/src/audit-logs/webhooks.mjs.map +1 -1
- package/dist/server/server/src/bootstrap.js +6 -4
- package/dist/server/server/src/bootstrap.js.map +1 -1
- package/dist/server/server/src/bootstrap.mjs +6 -4
- package/dist/server/server/src/bootstrap.mjs.map +1 -1
- package/dist/server/server/src/config/admin-actions.js +7 -0
- package/dist/server/server/src/config/admin-actions.js.map +1 -1
- package/dist/server/server/src/config/admin-actions.mjs +7 -0
- package/dist/server/server/src/config/admin-actions.mjs.map +1 -1
- package/dist/server/server/src/controllers/admin-token.js +8 -8
- package/dist/server/server/src/controllers/admin-token.js.map +1 -1
- package/dist/server/server/src/controllers/admin-token.mjs +4 -4
- package/dist/server/server/src/controllers/admin-token.mjs.map +1 -1
- package/dist/server/server/src/controllers/admin.js +9 -5
- package/dist/server/server/src/controllers/admin.js.map +1 -1
- package/dist/server/server/src/controllers/admin.mjs +8 -4
- package/dist/server/server/src/controllers/admin.mjs.map +1 -1
- package/dist/server/server/src/controllers/api-token.js +8 -8
- package/dist/server/server/src/controllers/api-token.js.map +1 -1
- package/dist/server/server/src/controllers/api-token.mjs +4 -4
- package/dist/server/server/src/controllers/api-token.mjs.map +1 -1
- package/dist/server/server/src/controllers/authentication.js +34 -8
- package/dist/server/server/src/controllers/authentication.js.map +1 -1
- package/dist/server/server/src/controllers/authentication.mjs +34 -8
- package/dist/server/server/src/controllers/authentication.mjs.map +1 -1
- package/dist/server/server/src/controllers/formatters/conditions.js +2 -2
- package/dist/server/server/src/controllers/formatters/conditions.js.map +1 -1
- package/dist/server/server/src/controllers/formatters/conditions.mjs +2 -2
- package/dist/server/server/src/controllers/formatters/conditions.mjs.map +1 -1
- package/dist/server/server/src/controllers/transfer/index.js +2 -2
- package/dist/server/server/src/controllers/transfer/index.js.map +1 -1
- package/dist/server/server/src/controllers/transfer/index.mjs +2 -2
- package/dist/server/server/src/controllers/transfer/index.mjs.map +1 -1
- package/dist/server/server/src/controllers/transfer/token.js +8 -8
- package/dist/server/server/src/controllers/transfer/token.js.map +1 -1
- package/dist/server/server/src/controllers/transfer/token.mjs +4 -4
- package/dist/server/server/src/controllers/transfer/token.mjs.map +1 -1
- package/dist/server/server/src/domain/action/index.js +18 -16
- package/dist/server/server/src/domain/action/index.js.map +1 -1
- package/dist/server/server/src/domain/action/index.mjs +16 -14
- package/dist/server/server/src/domain/action/index.mjs.map +1 -1
- package/dist/server/server/src/domain/action/provider.mjs +4 -4
- package/dist/server/server/src/domain/action/provider.mjs.map +1 -1
- package/dist/server/server/src/domain/condition/index.js +7 -4
- package/dist/server/server/src/domain/condition/index.js.map +1 -1
- package/dist/server/server/src/domain/condition/index.mjs +7 -4
- package/dist/server/server/src/domain/condition/index.mjs.map +1 -1
- package/dist/server/server/src/domain/permission/index.js +24 -15
- package/dist/server/server/src/domain/permission/index.js.map +1 -1
- package/dist/server/server/src/domain/permission/index.mjs +21 -12
- package/dist/server/server/src/domain/permission/index.mjs.map +1 -1
- package/dist/server/server/src/middlewares/rateLimit.js +5 -5
- package/dist/server/server/src/middlewares/rateLimit.js.map +1 -1
- package/dist/server/server/src/middlewares/rateLimit.mjs +4 -4
- package/dist/server/server/src/middlewares/rateLimit.mjs.map +1 -1
- package/dist/server/server/src/register.js +10 -0
- package/dist/server/server/src/register.js.map +1 -1
- package/dist/server/server/src/register.mjs +10 -0
- package/dist/server/server/src/register.mjs.map +1 -1
- package/dist/server/server/src/routes/admin.js +18 -0
- package/dist/server/server/src/routes/admin.js.map +1 -1
- package/dist/server/server/src/routes/admin.mjs +18 -0
- package/dist/server/server/src/routes/admin.mjs.map +1 -1
- package/dist/server/server/src/services/action.js +1 -2
- package/dist/server/server/src/services/action.js.map +1 -1
- package/dist/server/server/src/services/action.mjs +1 -2
- package/dist/server/server/src/services/action.mjs.map +1 -1
- package/dist/server/server/src/services/api-token.js +61 -49
- package/dist/server/server/src/services/api-token.js.map +1 -1
- package/dist/server/server/src/services/api-token.mjs +53 -41
- package/dist/server/server/src/services/api-token.mjs.map +1 -1
- package/dist/server/server/src/services/auth.js +4 -2
- package/dist/server/server/src/services/auth.js.map +1 -1
- package/dist/server/server/src/services/auth.mjs +4 -3
- package/dist/server/server/src/services/auth.mjs.map +1 -1
- package/dist/server/server/src/services/condition.js +2 -2
- package/dist/server/server/src/services/condition.js.map +1 -1
- package/dist/server/server/src/services/condition.mjs +1 -1
- package/dist/server/server/src/services/condition.mjs.map +1 -1
- package/dist/server/server/src/services/content-type.js +5 -4
- package/dist/server/server/src/services/content-type.js.map +1 -1
- package/dist/server/server/src/services/content-type.mjs +8 -7
- package/dist/server/server/src/services/content-type.mjs.map +1 -1
- package/dist/server/server/src/services/debug-dump.js +173 -0
- package/dist/server/server/src/services/debug-dump.js.map +1 -0
- package/dist/server/server/src/services/debug-dump.mjs +166 -0
- package/dist/server/server/src/services/debug-dump.mjs.map +1 -0
- package/dist/server/server/src/services/homepage.js +2 -1
- package/dist/server/server/src/services/homepage.js.map +1 -1
- package/dist/server/server/src/services/homepage.mjs +2 -1
- package/dist/server/server/src/services/homepage.mjs.map +1 -1
- package/dist/server/server/src/services/index.js +3 -1
- package/dist/server/server/src/services/index.js.map +1 -1
- package/dist/server/server/src/services/index.mjs +3 -1
- package/dist/server/server/src/services/index.mjs.map +1 -1
- package/dist/server/server/src/services/passport/local-strategy.js +2 -2
- package/dist/server/server/src/services/passport/local-strategy.js.map +1 -1
- package/dist/server/server/src/services/passport/local-strategy.mjs +1 -1
- package/dist/server/server/src/services/passport/local-strategy.mjs.map +1 -1
- package/dist/server/server/src/services/passport.js +1 -2
- package/dist/server/server/src/services/passport.js.map +1 -1
- package/dist/server/server/src/services/passport.mjs +1 -2
- package/dist/server/server/src/services/passport.mjs.map +1 -1
- package/dist/server/server/src/services/permission/engine.js +4 -4
- package/dist/server/server/src/services/permission/engine.js.map +1 -1
- package/dist/server/server/src/services/permission/engine.mjs +2 -2
- package/dist/server/server/src/services/permission/engine.mjs.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/index.js +2 -3
- package/dist/server/server/src/services/permission/permissions-manager/index.js.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/index.mjs +1 -2
- package/dist/server/server/src/services/permission/permissions-manager/index.mjs.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/permission-fields.js +6 -6
- package/dist/server/server/src/services/permission/permissions-manager/permission-fields.js.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/permission-fields.mjs +4 -4
- package/dist/server/server/src/services/permission/permissions-manager/permission-fields.mjs.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/sanitize.js +47 -41
- package/dist/server/server/src/services/permission/permissions-manager/sanitize.js.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/sanitize.mjs +44 -38
- package/dist/server/server/src/services/permission/permissions-manager/sanitize.mjs.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/validate.js +30 -26
- package/dist/server/server/src/services/permission/permissions-manager/validate.js.map +1 -1
- package/dist/server/server/src/services/permission/permissions-manager/validate.mjs +28 -24
- package/dist/server/server/src/services/permission/permissions-manager/validate.mjs.map +1 -1
- package/dist/server/server/src/services/permission/queries.js +9 -9
- package/dist/server/server/src/services/permission/queries.js.map +1 -1
- package/dist/server/server/src/services/permission/queries.mjs +9 -9
- package/dist/server/server/src/services/permission/queries.mjs.map +1 -1
- package/dist/server/server/src/services/permission/rename-fields.js +118 -0
- package/dist/server/server/src/services/permission/rename-fields.js.map +1 -0
- package/dist/server/server/src/services/permission/rename-fields.mjs +116 -0
- package/dist/server/server/src/services/permission/rename-fields.mjs.map +1 -0
- package/dist/server/server/src/services/permission/sections-builder/index.js +2 -2
- package/dist/server/server/src/services/permission/sections-builder/index.js.map +1 -1
- package/dist/server/server/src/services/permission/sections-builder/index.mjs +2 -2
- package/dist/server/server/src/services/permission/sections-builder/index.mjs.map +1 -1
- package/dist/server/server/src/services/permission/sections-builder/section.js +1 -2
- package/dist/server/server/src/services/permission/sections-builder/section.js.map +1 -1
- package/dist/server/server/src/services/permission/sections-builder/section.mjs +1 -2
- package/dist/server/server/src/services/permission/sections-builder/section.mjs.map +1 -1
- package/dist/server/server/src/services/permission/sections-builder/utils.js +6 -6
- package/dist/server/server/src/services/permission/sections-builder/utils.js.map +1 -1
- package/dist/server/server/src/services/permission/sections-builder/utils.mjs +4 -4
- package/dist/server/server/src/services/permission/sections-builder/utils.mjs.map +1 -1
- package/dist/server/server/src/services/role.js +20 -19
- package/dist/server/server/src/services/role.js.map +1 -1
- package/dist/server/server/src/services/role.mjs +20 -19
- package/dist/server/server/src/services/role.mjs.map +1 -1
- package/dist/server/server/src/services/transfer/token.js +20 -16
- package/dist/server/server/src/services/transfer/token.js.map +1 -1
- package/dist/server/server/src/services/transfer/token.mjs +14 -10
- package/dist/server/server/src/services/transfer/token.mjs.map +1 -1
- package/dist/server/server/src/services/user.js +2 -3
- package/dist/server/server/src/services/user.js.map +1 -1
- package/dist/server/server/src/services/user.mjs +3 -4
- package/dist/server/server/src/services/user.mjs.map +1 -1
- package/dist/server/server/src/strategies/api-token-utils.js +2 -3
- package/dist/server/server/src/strategies/api-token-utils.js.map +1 -1
- package/dist/server/server/src/strategies/api-token-utils.mjs +2 -3
- package/dist/server/server/src/strategies/api-token-utils.mjs.map +1 -1
- package/dist/server/server/src/strategies/content-api-token.js +3 -3
- package/dist/server/server/src/strategies/content-api-token.js.map +1 -1
- package/dist/server/server/src/strategies/content-api-token.mjs +1 -1
- package/dist/server/server/src/strategies/content-api-token.mjs.map +1 -1
- package/dist/server/server/src/strategies/data-transfer.js +4 -4
- package/dist/server/server/src/strategies/data-transfer.js.map +1 -1
- package/dist/server/server/src/strategies/data-transfer.mjs +3 -3
- package/dist/server/server/src/strategies/data-transfer.mjs.map +1 -1
- package/dist/server/server/src/utils/debug-dump/redact.js +197 -0
- package/dist/server/server/src/utils/debug-dump/redact.js.map +1 -0
- package/dist/server/server/src/utils/debug-dump/redact.mjs +194 -0
- package/dist/server/server/src/utils/debug-dump/redact.mjs.map +1 -0
- package/dist/server/server/src/validation/common-validators.js +9 -10
- package/dist/server/server/src/validation/common-validators.js.map +1 -1
- package/dist/server/server/src/validation/common-validators.mjs +13 -14
- package/dist/server/server/src/validation/common-validators.mjs.map +1 -1
- package/dist/server/server/src/validation/user.js +1 -2
- package/dist/server/server/src/validation/user.js.map +1 -1
- package/dist/server/server/src/validation/user.mjs +1 -2
- package/dist/server/server/src/validation/user.mjs.map +1 -1
- package/dist/server/shared/utils/get-project-type.js +49 -0
- package/dist/server/shared/utils/get-project-type.js.map +1 -0
- package/dist/server/shared/utils/get-project-type.mjs +46 -0
- package/dist/server/shared/utils/get-project-type.mjs.map +1 -0
- package/dist/server/src/audit-logs/auth.d.ts +72 -0
- package/dist/server/src/audit-logs/auth.d.ts.map +1 -0
- package/dist/server/src/audit-logs/tokens.d.ts.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/config/admin-actions.d.ts.map +1 -1
- package/dist/server/src/controllers/admin-token.d.ts.map +1 -1
- package/dist/server/src/controllers/admin.d.ts +3 -0
- package/dist/server/src/controllers/admin.d.ts.map +1 -1
- package/dist/server/src/controllers/api-token.d.ts.map +1 -1
- package/dist/server/src/controllers/authentication.d.ts.map +1 -1
- package/dist/server/src/controllers/formatters/conditions.d.ts +1 -1
- package/dist/server/src/controllers/formatters/conditions.d.ts.map +1 -1
- package/dist/server/src/controllers/homepage.d.ts +1 -1
- package/dist/server/src/controllers/index.d.ts +4 -1
- package/dist/server/src/controllers/index.d.ts.map +1 -1
- package/dist/server/src/controllers/transfer/index.d.ts.map +1 -1
- package/dist/server/src/controllers/transfer/token.d.ts.map +1 -1
- package/dist/server/src/domain/action/index.d.ts +1 -0
- package/dist/server/src/domain/action/index.d.ts.map +1 -1
- package/dist/server/src/domain/condition/index.d.ts +2 -2
- package/dist/server/src/domain/condition/index.d.ts.map +1 -1
- package/dist/server/src/domain/permission/index.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +11 -3
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/middlewares/index.d.ts.map +1 -1
- package/dist/server/src/middlewares/rateLimit.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/server/src/routes/admin.d.ts.map +1 -1
- package/dist/server/src/services/action.d.ts.map +1 -1
- package/dist/server/src/services/api-token.d.ts.map +1 -1
- package/dist/server/src/services/auth.d.ts +6 -0
- package/dist/server/src/services/auth.d.ts.map +1 -1
- package/dist/server/src/services/condition.d.ts.map +1 -1
- package/dist/server/src/services/content-type.d.ts.map +1 -1
- package/dist/server/src/services/debug-dump.d.ts +9 -0
- package/dist/server/src/services/debug-dump.d.ts.map +1 -0
- package/dist/server/src/services/homepage.d.ts +1 -1
- package/dist/server/src/services/homepage.d.ts.map +1 -1
- package/dist/server/src/services/index.d.ts +7 -2
- package/dist/server/src/services/index.d.ts.map +1 -1
- package/dist/server/src/services/passport/local-strategy.d.ts.map +1 -1
- package/dist/server/src/services/passport.d.ts.map +1 -1
- package/dist/server/src/services/permission/engine.d.ts.map +1 -1
- package/dist/server/src/services/permission/permissions-manager/permission-fields.d.ts.map +1 -1
- package/dist/server/src/services/permission/permissions-manager/sanitize.d.ts.map +1 -1
- package/dist/server/src/services/permission/permissions-manager/validate.d.ts.map +1 -1
- package/dist/server/src/services/permission/queries.d.ts.map +1 -1
- package/dist/server/src/services/permission/rename-fields.d.ts +21 -0
- package/dist/server/src/services/permission/rename-fields.d.ts.map +1 -0
- package/dist/server/src/services/permission/sections-builder/section.d.ts.map +1 -1
- package/dist/server/src/services/permission/sections-builder/utils.d.ts +1 -1
- package/dist/server/src/services/permission/sections-builder/utils.d.ts.map +1 -1
- package/dist/server/src/services/role.d.ts +1 -1
- package/dist/server/src/services/role.d.ts.map +1 -1
- package/dist/server/src/services/transfer/token.d.ts.map +1 -1
- package/dist/server/src/strategies/content-api-token.d.ts.map +1 -1
- package/dist/server/src/utils/debug-dump/redact.d.ts +8 -0
- package/dist/server/src/utils/debug-dump/redact.d.ts.map +1 -0
- package/dist/server/src/validation/user.d.ts.map +1 -1
- package/dist/shared/contracts/admin.d.ts +106 -0
- package/dist/shared/contracts/admin.d.ts.map +1 -1
- package/dist/shared/utils/__tests__/get-project-type.test.d.ts +1 -0
- package/dist/shared/utils/__tests__/get-project-type.test.d.ts.map +1 -0
- package/dist/shared/utils/get-project-type.d.ts +37 -0
- package/dist/shared/utils/get-project-type.d.ts.map +1 -0
- package/package.json +10 -10
- package/dist/admin/admin/src/utils/getProjectType.js +0 -22
- package/dist/admin/admin/src/utils/getProjectType.js.map +0 -1
- package/dist/admin/admin/src/utils/getProjectType.mjs +0 -20
- package/dist/admin/admin/src/utils/getProjectType.mjs.map +0 -1
- package/dist/admin/src/utils/getProjectType.d.ts +0 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-transfer.js","sources":["../../../../../server/src/strategies/data-transfer.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { differenceInHours, parseISO } from 'date-fns';\nimport { errors } from '@strapi/utils';\nimport { castArray
|
|
1
|
+
{"version":3,"file":"data-transfer.js","sources":["../../../../../server/src/strategies/data-transfer.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { differenceInHours, parseISO } from 'date-fns';\nimport { errors } from '@strapi/utils';\nimport { castArray } from 'lodash';\n\nimport { getService } from '../utils';\n\nconst { UnauthorizedError, ForbiddenError } = errors;\n\nconst extractToken = (ctx: Context) => {\n if (ctx.request && ctx.request.header && ctx.request.header.authorization) {\n const parts = ctx.request.header.authorization.split(/\\s+/);\n\n if (parts[0].toLowerCase() !== 'bearer' || parts.length !== 2) {\n return null;\n }\n\n return parts[1];\n }\n\n return null;\n};\n\n/**\n * Authenticate the validity of the token\n *\n * @type {import('.').AuthenticateFunction}\n */\nexport const authenticate = async (ctx: Context) => {\n const { token: tokenService } = getService('transfer');\n const token = extractToken(ctx);\n\n if (!token) {\n return { authenticated: false };\n }\n\n const transferToken = await tokenService.getBy({ accessKey: tokenService.hash(token) });\n\n // Check if the token exists\n if (!transferToken) {\n return { authenticated: false };\n }\n\n // Check if the token has expired\n const currentDate = new Date();\n\n if (transferToken.expiresAt != null) {\n const expirationDate = new Date(transferToken.expiresAt);\n\n if (expirationDate < currentDate) {\n return { authenticated: false, error: new UnauthorizedError('Token expired') };\n }\n }\n\n // Update token metadata if the token has not been used in the last hour\n // @ts-expect-error - FIXME: verify lastUsedAt is defined\n const hoursSinceLastUsed = differenceInHours(currentDate, parseISO(transferToken.lastUsedAt));\n if (hoursSinceLastUsed >= 1) {\n await strapi.db.query('admin::api-token').update({\n where: { id: transferToken.id },\n data: { lastUsedAt: currentDate },\n });\n }\n\n // Generate an ability based on the token permissions\n const ability = await getService('transfer').permission.engine.generateAbility(\n transferToken.permissions.map((action: any) => ({ action }))\n );\n\n return { authenticated: true, ability, credentials: transferToken };\n};\n\n/**\n * Verify the token has the required abilities for the requested scope\n *\n * @type {import('.').VerifyFunction}\n */\nexport const verify = async (auth: any, config: any = {}) => {\n const { credentials: transferToken, ability } = auth;\n\n if (!transferToken) {\n throw new UnauthorizedError('Token not found');\n }\n\n const currentDate = new Date();\n\n if (transferToken.expiresAt != null) {\n const expirationDate = new Date(transferToken.expiresAt);\n // token has expired\n if (expirationDate < currentDate) {\n throw new UnauthorizedError('Token expired');\n }\n }\n\n if (!ability) {\n throw new ForbiddenError();\n }\n\n const scopes = castArray(config.scope ?? []);\n\n const isAllowed = scopes.every((scope) => ability.can(scope));\n\n if (!isAllowed) {\n throw new ForbiddenError();\n }\n};\n\nexport const name = 'data-transfer';\n\n/** @type {import('.').AuthStrategy} */\nexport default {\n name,\n authenticate,\n verify,\n};\n"],"names":["UnauthorizedError","ForbiddenError","errors","extractToken","ctx","request","header","authorization","parts","split","toLowerCase","length","authenticate","token","tokenService","getService","authenticated","transferToken","getBy","accessKey","hash","currentDate","Date","expiresAt","expirationDate","error","hoursSinceLastUsed","differenceInHours","parseISO","lastUsedAt","strapi","db","query","update","where","id","data","ability","permission","engine","generateAbility","permissions","map","action","credentials","verify","auth","config","scopes","castArray","scope","isAllowed","every","can","name"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { differenceInHours, parseISO } from 'date-fns';
|
|
2
2
|
import { errors } from '@strapi/utils';
|
|
3
|
-
import {
|
|
3
|
+
import { castArray } from 'lodash';
|
|
4
4
|
import { getService } from '../utils/index.mjs';
|
|
5
5
|
|
|
6
6
|
const { UnauthorizedError, ForbiddenError } = errors;
|
|
@@ -37,7 +37,7 @@ const extractToken = (ctx)=>{
|
|
|
37
37
|
}
|
|
38
38
|
// Check if the token has expired
|
|
39
39
|
const currentDate = new Date();
|
|
40
|
-
if (
|
|
40
|
+
if (transferToken.expiresAt != null) {
|
|
41
41
|
const expirationDate = new Date(transferToken.expiresAt);
|
|
42
42
|
if (expirationDate < currentDate) {
|
|
43
43
|
return {
|
|
@@ -79,7 +79,7 @@ const extractToken = (ctx)=>{
|
|
|
79
79
|
throw new UnauthorizedError('Token not found');
|
|
80
80
|
}
|
|
81
81
|
const currentDate = new Date();
|
|
82
|
-
if (
|
|
82
|
+
if (transferToken.expiresAt != null) {
|
|
83
83
|
const expirationDate = new Date(transferToken.expiresAt);
|
|
84
84
|
// token has expired
|
|
85
85
|
if (expirationDate < currentDate) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-transfer.mjs","sources":["../../../../../server/src/strategies/data-transfer.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { differenceInHours, parseISO } from 'date-fns';\nimport { errors } from '@strapi/utils';\nimport { castArray
|
|
1
|
+
{"version":3,"file":"data-transfer.mjs","sources":["../../../../../server/src/strategies/data-transfer.ts"],"sourcesContent":["import type { Context } from 'koa';\nimport { differenceInHours, parseISO } from 'date-fns';\nimport { errors } from '@strapi/utils';\nimport { castArray } from 'lodash';\n\nimport { getService } from '../utils';\n\nconst { UnauthorizedError, ForbiddenError } = errors;\n\nconst extractToken = (ctx: Context) => {\n if (ctx.request && ctx.request.header && ctx.request.header.authorization) {\n const parts = ctx.request.header.authorization.split(/\\s+/);\n\n if (parts[0].toLowerCase() !== 'bearer' || parts.length !== 2) {\n return null;\n }\n\n return parts[1];\n }\n\n return null;\n};\n\n/**\n * Authenticate the validity of the token\n *\n * @type {import('.').AuthenticateFunction}\n */\nexport const authenticate = async (ctx: Context) => {\n const { token: tokenService } = getService('transfer');\n const token = extractToken(ctx);\n\n if (!token) {\n return { authenticated: false };\n }\n\n const transferToken = await tokenService.getBy({ accessKey: tokenService.hash(token) });\n\n // Check if the token exists\n if (!transferToken) {\n return { authenticated: false };\n }\n\n // Check if the token has expired\n const currentDate = new Date();\n\n if (transferToken.expiresAt != null) {\n const expirationDate = new Date(transferToken.expiresAt);\n\n if (expirationDate < currentDate) {\n return { authenticated: false, error: new UnauthorizedError('Token expired') };\n }\n }\n\n // Update token metadata if the token has not been used in the last hour\n // @ts-expect-error - FIXME: verify lastUsedAt is defined\n const hoursSinceLastUsed = differenceInHours(currentDate, parseISO(transferToken.lastUsedAt));\n if (hoursSinceLastUsed >= 1) {\n await strapi.db.query('admin::api-token').update({\n where: { id: transferToken.id },\n data: { lastUsedAt: currentDate },\n });\n }\n\n // Generate an ability based on the token permissions\n const ability = await getService('transfer').permission.engine.generateAbility(\n transferToken.permissions.map((action: any) => ({ action }))\n );\n\n return { authenticated: true, ability, credentials: transferToken };\n};\n\n/**\n * Verify the token has the required abilities for the requested scope\n *\n * @type {import('.').VerifyFunction}\n */\nexport const verify = async (auth: any, config: any = {}) => {\n const { credentials: transferToken, ability } = auth;\n\n if (!transferToken) {\n throw new UnauthorizedError('Token not found');\n }\n\n const currentDate = new Date();\n\n if (transferToken.expiresAt != null) {\n const expirationDate = new Date(transferToken.expiresAt);\n // token has expired\n if (expirationDate < currentDate) {\n throw new UnauthorizedError('Token expired');\n }\n }\n\n if (!ability) {\n throw new ForbiddenError();\n }\n\n const scopes = castArray(config.scope ?? []);\n\n const isAllowed = scopes.every((scope) => ability.can(scope));\n\n if (!isAllowed) {\n throw new ForbiddenError();\n }\n};\n\nexport const name = 'data-transfer';\n\n/** @type {import('.').AuthStrategy} */\nexport default {\n name,\n authenticate,\n verify,\n};\n"],"names":["UnauthorizedError","ForbiddenError","errors","extractToken","ctx","request","header","authorization","parts","split","toLowerCase","length","authenticate","token","tokenService","getService","authenticated","transferToken","getBy","accessKey","hash","currentDate","Date","expiresAt","expirationDate","error","hoursSinceLastUsed","differenceInHours","parseISO","lastUsedAt","strapi","db","query","update","where","id","data","ability","permission","engine","generateAbility","permissions","map","action","credentials","verify","auth","config","scopes","castArray","scope","isAllowed","every","can","name"],"mappings":";;;;;AAOA,MAAM,EAAEA,iBAAiB,EAAEC,cAAc,EAAE,GAAGC,MAAAA;AAE9C,MAAMC,eAAe,CAACC,GAAAA,GAAAA;AACpB,IAAA,IAAIA,GAAAA,CAAIC,OAAO,IAAID,GAAAA,CAAIC,OAAO,CAACC,MAAM,IAAIF,GAAAA,CAAIC,OAAO,CAACC,MAAM,CAACC,aAAa,EAAE;QACzE,MAAMC,KAAAA,GAAQJ,IAAIC,OAAO,CAACC,MAAM,CAACC,aAAa,CAACE,KAAK,CAAC,KAAA,CAAA;QAErD,IAAID,KAAK,CAAC,CAAA,CAAE,CAACE,WAAW,OAAO,QAAA,IAAYF,KAAAA,CAAMG,MAAM,KAAK,CAAA,EAAG;YAC7D,OAAO,IAAA;AACT,QAAA;QAEA,OAAOH,KAAK,CAAC,CAAA,CAAE;AACjB,IAAA;IAEA,OAAO,IAAA;AACT,CAAA;AAEA;;;;IAKO,MAAMI,YAAAA,GAAe,OAAOR,GAAAA,GAAAA;AACjC,IAAA,MAAM,EAAES,KAAAA,EAAOC,YAAY,EAAE,GAAGC,UAAAA,CAAW,UAAA,CAAA;AAC3C,IAAA,MAAMF,QAAQV,YAAAA,CAAaC,GAAAA,CAAAA;AAE3B,IAAA,IAAI,CAACS,KAAAA,EAAO;QACV,OAAO;YAAEG,aAAAA,EAAe;AAAM,SAAA;AAChC,IAAA;AAEA,IAAA,MAAMC,aAAAA,GAAgB,MAAMH,YAAAA,CAAaI,KAAK,CAAC;QAAEC,SAAAA,EAAWL,YAAAA,CAAaM,IAAI,CAACP,KAAAA;AAAO,KAAA,CAAA;;AAGrF,IAAA,IAAI,CAACI,aAAAA,EAAe;QAClB,OAAO;YAAED,aAAAA,EAAe;AAAM,SAAA;AAChC,IAAA;;AAGA,IAAA,MAAMK,cAAc,IAAIC,IAAAA,EAAAA;IAExB,IAAIL,aAAAA,CAAcM,SAAS,IAAI,IAAA,EAAM;AACnC,QAAA,MAAMC,cAAAA,GAAiB,IAAIF,IAAAA,CAAKL,aAAAA,CAAcM,SAAS,CAAA;AAEvD,QAAA,IAAIC,iBAAiBH,WAAAA,EAAa;YAChC,OAAO;gBAAEL,aAAAA,EAAe,KAAA;AAAOS,gBAAAA,KAAAA,EAAO,IAAIzB,iBAAAA,CAAkB,eAAA;AAAiB,aAAA;AAC/E,QAAA;AACF,IAAA;;;AAIA,IAAA,MAAM0B,kBAAAA,GAAqBC,iBAAAA,CAAkBN,WAAAA,EAAaO,QAAAA,CAASX,cAAcY,UAAU,CAAA,CAAA;AAC3F,IAAA,IAAIH,sBAAsB,CAAA,EAAG;AAC3B,QAAA,MAAMI,OAAOC,EAAE,CAACC,KAAK,CAAC,kBAAA,CAAA,CAAoBC,MAAM,CAAC;YAC/CC,KAAAA,EAAO;AAAEC,gBAAAA,EAAAA,EAAIlB,cAAckB;AAAG,aAAA;YAC9BC,IAAAA,EAAM;gBAAEP,UAAAA,EAAYR;AAAY;AAClC,SAAA,CAAA;AACF,IAAA;;AAGA,IAAA,MAAMgB,UAAU,MAAMtB,UAAAA,CAAW,UAAA,CAAA,CAAYuB,UAAU,CAACC,MAAM,CAACC,eAAe,CAC5EvB,cAAcwB,WAAW,CAACC,GAAG,CAAC,CAACC,UAAiB;AAAEA,YAAAA;SAAO,CAAA,CAAA,CAAA;IAG3D,OAAO;QAAE3B,aAAAA,EAAe,IAAA;AAAMqB,QAAAA,OAAAA;QAASO,WAAAA,EAAa3B;AAAc,KAAA;AACpE;AAEA;;;;AAIC,IACM,MAAM4B,MAAAA,GAAS,OAAOC,IAAAA,EAAWC,MAAAA,GAAc,EAAE,GAAA;AACtD,IAAA,MAAM,EAAEH,WAAAA,EAAa3B,aAAa,EAAEoB,OAAO,EAAE,GAAGS,IAAAA;AAEhD,IAAA,IAAI,CAAC7B,aAAAA,EAAe;AAClB,QAAA,MAAM,IAAIjB,iBAAAA,CAAkB,iBAAA,CAAA;AAC9B,IAAA;AAEA,IAAA,MAAMqB,cAAc,IAAIC,IAAAA,EAAAA;IAExB,IAAIL,aAAAA,CAAcM,SAAS,IAAI,IAAA,EAAM;AACnC,QAAA,MAAMC,cAAAA,GAAiB,IAAIF,IAAAA,CAAKL,aAAAA,CAAcM,SAAS,CAAA;;AAEvD,QAAA,IAAIC,iBAAiBH,WAAAA,EAAa;AAChC,YAAA,MAAM,IAAIrB,iBAAAA,CAAkB,eAAA,CAAA;AAC9B,QAAA;AACF,IAAA;AAEA,IAAA,IAAI,CAACqC,OAAAA,EAAS;AACZ,QAAA,MAAM,IAAIpC,cAAAA,EAAAA;AACZ,IAAA;AAEA,IAAA,MAAM+C,MAAAA,GAASC,SAAAA,CAAUF,MAAAA,CAAOG,KAAK,IAAI,EAAE,CAAA;IAE3C,MAAMC,SAAAA,GAAYH,OAAOI,KAAK,CAAC,CAACF,KAAAA,GAAUb,OAAAA,CAAQgB,GAAG,CAACH,KAAAA,CAAAA,CAAAA;AAEtD,IAAA,IAAI,CAACC,SAAAA,EAAW;AACd,QAAA,MAAM,IAAIlD,cAAAA,EAAAA;AACZ,IAAA;AACF;AAEO,MAAMqD,OAAO;AAEpB,wCACA,+BAAe;AACbA,IAAAA,IAAAA;AACA1C,IAAAA,YAAAA;AACAiC,IAAAA;AACF,CAAA;;;;"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const REDACTED = '[REDACTED]';
|
|
4
|
+
// Layer 1a: key names (substring match) whose value must be masked wherever they appear.
|
|
5
|
+
const SECRET_KEY_PATTERN = /(secret|password|passphrase|salt|token|api[_-]?key|access[_-]?key|license[_-]?key|private[_-]?key|encryption[_-]?key|credential|provider[_-]?options|connection[_-]?string|mnemonic|seed[_-]?phrase|authorization|bearer)/i;
|
|
6
|
+
// Layer 1b: short, ambiguous key names matched EXACTLY (case-insensitive), so they
|
|
7
|
+
// do not over-match as substrings (e.g. `pass` must not redact `compass`/`bypass`,
|
|
8
|
+
// and this still catches a nested SMTP `auth.pass`).
|
|
9
|
+
const SECRET_KEY_EXACT = new Set([
|
|
10
|
+
'pass',
|
|
11
|
+
'pwd',
|
|
12
|
+
'passwd',
|
|
13
|
+
'dsn'
|
|
14
|
+
]);
|
|
15
|
+
// camelCase password suffixes (capitalized), e.g. `smtpAuthPass`, `dbPwd` — the
|
|
16
|
+
// capital letter distinguishes them from lowercase look-alikes (`compass`, `bypass`).
|
|
17
|
+
const SECRET_KEY_SUFFIX = /[a-z](Pass|Pwd|Passwd)$/;
|
|
18
|
+
// separator-delimited short secret names, e.g. `auth.pass`, `db_pwd`, `x-pass`.
|
|
19
|
+
const SECRET_KEY_DELIMITED = /(^|[._-])(pass|pwd|passwd|dsn)([._-]|$)/i;
|
|
20
|
+
const isSecretKey = (key)=>SECRET_KEY_PATTERN.test(key) || SECRET_KEY_EXACT.has(key.toLowerCase()) || SECRET_KEY_SUFFIX.test(key) || SECRET_KEY_DELIMITED.test(key);
|
|
21
|
+
// Layer 3: string values that look like secrets regardless of their key.
|
|
22
|
+
// Real JWTs are base64url-encoded and the header segment always begins with
|
|
23
|
+
// `eyJ` (the base64url encoding of `{"`), so requiring that prefix avoids
|
|
24
|
+
// matching arbitrary three-part dotted strings like semver versions
|
|
25
|
+
// (e.g. "5.50.1", "18.3.1").
|
|
26
|
+
const JWT_PATTERN = /^eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
|
|
27
|
+
const LONG_TOKEN_PATTERN = /^[A-Fa-f0-9]{32,}$|^[A-Za-z0-9+/]{40,}={0,2}$/;
|
|
28
|
+
// Credentials embedded in a URL authority: `user:pass@` or `:pass@` (empty user,
|
|
29
|
+
// as in `redis://:password@host`). The user part stops at the first colon, as in
|
|
30
|
+
// RFC 3986, so the split between user and password is fixed; letting it take colons
|
|
31
|
+
// made a long colon run with no `@` retry every split point, which is quadratic.
|
|
32
|
+
const URL_WITH_CREDENTIALS = /^[a-z][a-z0-9+.-]*:\/\/[^/@\s:]*:[^/@\s]+@/i;
|
|
33
|
+
// PEM private key blocks (certificates are public, so only PRIVATE KEY is masked).
|
|
34
|
+
const PEM_PRIVATE_KEY_PATTERN = /-----BEGIN(?: [A-Z0-9]+)* PRIVATE KEY-----/;
|
|
35
|
+
// URLs whose secret is carried in the host/path rather than a `user:pass@` authority:
|
|
36
|
+
// chat webhooks and error-tracking DSNs.
|
|
37
|
+
const SECRET_URL_PATTERN = /^https:\/\/hooks\.slack\.com\/services\/|^https:\/\/(?:discord|discordapp)\.com\/api\/webhooks\/|:\/\/[^/@\s]+@[^/\s]*\bsentry\.io\b/i;
|
|
38
|
+
// Well-known provider secret token formats, matched against the whole value. The
|
|
39
|
+
// prefixes are specific enough to have negligible false-positive risk, so they
|
|
40
|
+
// mask a value even under an innocuous key (e.g. `key: 'sk_live_...'`).
|
|
41
|
+
// `pk_` (publishable) keys are intentionally excluded — they are public by design.
|
|
42
|
+
const PROVIDER_SECRET_PATTERN = new RegExp([
|
|
43
|
+
'^(sk|rk)_(live|test)_[A-Za-z0-9]{8,}$',
|
|
44
|
+
'^whsec_[A-Za-z0-9]{16,}$',
|
|
45
|
+
'^(gh[posru]_|github_pat_)[A-Za-z0-9_]{20,}$',
|
|
46
|
+
'^xox[baprs]-[A-Za-z0-9-]{10,}$',
|
|
47
|
+
'^(AKIA|ASIA)[A-Z0-9]{16}$',
|
|
48
|
+
'^SG\\.[A-Za-z0-9_-]{16,}\\.[A-Za-z0-9_-]{16,}$',
|
|
49
|
+
'^AIza[A-Za-z0-9_-]{20,}$',
|
|
50
|
+
'^ya29\\.[A-Za-z0-9_-]{20,}$',
|
|
51
|
+
'^glpat-[A-Za-z0-9_-]{16,}$',
|
|
52
|
+
'^(shpat|shpss|shpca|shppa)_[A-Za-z0-9]{20,}$',
|
|
53
|
+
'^dop_v1_[a-f0-9]{40,}$',
|
|
54
|
+
'^re_[A-Za-z0-9_]{16,}$',
|
|
55
|
+
'^nfp_[A-Za-z0-9]{20,}$',
|
|
56
|
+
'^EAAA[A-Za-z0-9_-]{20,}$'
|
|
57
|
+
].join('|'));
|
|
58
|
+
const looksSecret = (value)=>JWT_PATTERN.test(value) || LONG_TOKEN_PATTERN.test(value) || URL_WITH_CREDENTIALS.test(value) || PROVIDER_SECRET_PATTERN.test(value) || PEM_PRIVATE_KEY_PATTERN.test(value) || SECRET_URL_PATTERN.test(value);
|
|
59
|
+
const isPlainObject = (value)=>{
|
|
60
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const proto = Object.getPrototypeOf(value);
|
|
64
|
+
return proto === Object.prototype || proto === null;
|
|
65
|
+
};
|
|
66
|
+
// Accept either separator regardless of the host platform: `os.homedir()` and the app root come
|
|
67
|
+
// back with backslashes on Windows, and a dump may also carry POSIX-style paths (e.g. from
|
|
68
|
+
// config values), so a POSIX-only prefix check would ship absolute Windows paths verbatim.
|
|
69
|
+
const isPathPrefix = (value, prefix)=>{
|
|
70
|
+
if (value === prefix) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
if (!value.startsWith(prefix)) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
const next = value.charAt(prefix.length);
|
|
77
|
+
return next === '/' || next === '\\';
|
|
78
|
+
};
|
|
79
|
+
const relativize = (value, appRoot, homeDir)=>{
|
|
80
|
+
if (appRoot && isPathPrefix(value, appRoot)) {
|
|
81
|
+
return `<app>${value.slice(appRoot.length)}`;
|
|
82
|
+
}
|
|
83
|
+
if (homeDir && isPathPrefix(value, homeDir)) {
|
|
84
|
+
return `<home>${value.slice(homeDir.length)}`;
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
};
|
|
88
|
+
// Characters that end a URL authority
|
|
89
|
+
const AUTHORITY_END = new Set([
|
|
90
|
+
'/',
|
|
91
|
+
'?',
|
|
92
|
+
'#',
|
|
93
|
+
' ',
|
|
94
|
+
'\t',
|
|
95
|
+
'\n',
|
|
96
|
+
'\r',
|
|
97
|
+
'"',
|
|
98
|
+
"'",
|
|
99
|
+
'`'
|
|
100
|
+
]);
|
|
101
|
+
/**
|
|
102
|
+
* Masks the password of every `scheme://user:password@host` inside a longer string, such as a
|
|
103
|
+
* package.json script that inlines a database URL. Whole-value credential URLs are already
|
|
104
|
+
* caught by URL_WITH_CREDENTIALS; this covers the ones in the middle of a value. It is a single
|
|
105
|
+
* forward scan rather than a regex, because an unanchored pattern backtracks quadratically on
|
|
106
|
+
* long runs (the reason URL_WITH_CREDENTIALS is anchored and colon-free in the user part).
|
|
107
|
+
*/ const maskEmbeddedCredentials = (value)=>{
|
|
108
|
+
let result = '';
|
|
109
|
+
let copiedUpTo = 0;
|
|
110
|
+
let separator = value.indexOf('://');
|
|
111
|
+
while(separator !== -1){
|
|
112
|
+
const authorityStart = separator + 3;
|
|
113
|
+
let firstColon = -1;
|
|
114
|
+
let lastAt = -1;
|
|
115
|
+
let end = authorityStart;
|
|
116
|
+
while(end < value.length && !AUTHORITY_END.has(value[end])){
|
|
117
|
+
if (value[end] === ':' && firstColon === -1) {
|
|
118
|
+
firstColon = end;
|
|
119
|
+
} else if (value[end] === '@') {
|
|
120
|
+
lastAt = end;
|
|
121
|
+
}
|
|
122
|
+
end += 1;
|
|
123
|
+
}
|
|
124
|
+
// A colon before the last `@` separates user and password; one after it is a port.
|
|
125
|
+
if (firstColon !== -1 && lastAt > firstColon) {
|
|
126
|
+
result += `${value.slice(copiedUpTo, firstColon + 1)}${REDACTED}`;
|
|
127
|
+
copiedUpTo = lastAt;
|
|
128
|
+
}
|
|
129
|
+
separator = value.indexOf('://', end);
|
|
130
|
+
}
|
|
131
|
+
return copiedUpTo === 0 ? value : result + value.slice(copiedUpTo);
|
|
132
|
+
};
|
|
133
|
+
const deleteAtPath = (target, path)=>{
|
|
134
|
+
const segments = path.split('.');
|
|
135
|
+
let node = target;
|
|
136
|
+
for(let i = 0; i < segments.length - 1; i += 1){
|
|
137
|
+
if (!isPlainObject(node)) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
node = node[segments[i]];
|
|
141
|
+
}
|
|
142
|
+
const lastKey = segments[segments.length - 1];
|
|
143
|
+
if (isPlainObject(node) && lastKey in node) {
|
|
144
|
+
node[lastKey] = REDACTED;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const walk = (value, appRoot, homeDir)=>{
|
|
148
|
+
if (typeof value === 'string') {
|
|
149
|
+
// Relativization is tried FIRST, and a value it rewrote is returned as-is. A string
|
|
150
|
+
// that starts with the app root or the home directory is a path, never a credential,
|
|
151
|
+
// whereas the reverse order let the secret heuristics claim one: a POSIX path made
|
|
152
|
+
// only of letters, digits and `/` is valid standard base64, so anything past 40
|
|
153
|
+
// characters matched LONG_TOKEN_PATTERN and shipped as `[REDACTED]` instead of
|
|
154
|
+
// `<app>/...`. Values that do not relativize still go through the full checks.
|
|
155
|
+
const relativized = relativize(value, appRoot, homeDir);
|
|
156
|
+
if (relativized !== value) {
|
|
157
|
+
return relativized;
|
|
158
|
+
}
|
|
159
|
+
return looksSecret(value) ? REDACTED : maskEmbeddedCredentials(value);
|
|
160
|
+
}
|
|
161
|
+
if (Array.isArray(value)) {
|
|
162
|
+
return value.map((item)=>walk(item, appRoot, homeDir));
|
|
163
|
+
}
|
|
164
|
+
if (isPlainObject(value)) {
|
|
165
|
+
const out = {};
|
|
166
|
+
for (const [key, val] of Object.entries(value)){
|
|
167
|
+
if (key === '__proto__') {
|
|
168
|
+
continue; // never write through the Object.prototype setter
|
|
169
|
+
}
|
|
170
|
+
// A secret-named key always collapses wholesale, regardless of the value's
|
|
171
|
+
// type. Recursing into it (e.g. for `apiToken: { salt, ... }`) would leak
|
|
172
|
+
// any inner value whose own key/value doesn't independently match a
|
|
173
|
+
// masking pattern (e.g. `providerOptions.auth.pass`), so there is nothing
|
|
174
|
+
// safe to preserve underneath a secret-named container.
|
|
175
|
+
out[key] = isSecretKey(key) ? REDACTED : walk(val, appRoot, homeDir);
|
|
176
|
+
}
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
// Any other object type — Buffer, Date, Map, Set, class instances, etc. —
|
|
180
|
+
// is not a plain data container we can safely walk (Object.entries on a
|
|
181
|
+
// Buffer leaks its bytes, a Date serializes to `{}`), so redact defensively.
|
|
182
|
+
if (value !== null && typeof value === 'object') {
|
|
183
|
+
return REDACTED;
|
|
184
|
+
}
|
|
185
|
+
return value;
|
|
186
|
+
};
|
|
187
|
+
const scrub = (value, options = {})=>{
|
|
188
|
+
const cloned = walk(value, options.appRoot, options.homeDir);
|
|
189
|
+
for (const path of options.extraPaths ?? []){
|
|
190
|
+
deleteAtPath(cloned, path);
|
|
191
|
+
}
|
|
192
|
+
return cloned;
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
exports.REDACTED = REDACTED;
|
|
196
|
+
exports.scrub = scrub;
|
|
197
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sources":["../../../../../../server/src/utils/debug-dump/redact.ts"],"sourcesContent":["export const REDACTED = '[REDACTED]';\n\n// Layer 1a: key names (substring match) whose value must be masked wherever they appear.\nconst SECRET_KEY_PATTERN =\n /(secret|password|passphrase|salt|token|api[_-]?key|access[_-]?key|license[_-]?key|private[_-]?key|encryption[_-]?key|credential|provider[_-]?options|connection[_-]?string|mnemonic|seed[_-]?phrase|authorization|bearer)/i;\n\n// Layer 1b: short, ambiguous key names matched EXACTLY (case-insensitive), so they\n// do not over-match as substrings (e.g. `pass` must not redact `compass`/`bypass`,\n// and this still catches a nested SMTP `auth.pass`).\nconst SECRET_KEY_EXACT = new Set(['pass', 'pwd', 'passwd', 'dsn']);\n// camelCase password suffixes (capitalized), e.g. `smtpAuthPass`, `dbPwd` — the\n// capital letter distinguishes them from lowercase look-alikes (`compass`, `bypass`).\nconst SECRET_KEY_SUFFIX = /[a-z](Pass|Pwd|Passwd)$/;\n// separator-delimited short secret names, e.g. `auth.pass`, `db_pwd`, `x-pass`.\nconst SECRET_KEY_DELIMITED = /(^|[._-])(pass|pwd|passwd|dsn)([._-]|$)/i;\n\nconst isSecretKey = (key: string): boolean =>\n SECRET_KEY_PATTERN.test(key) ||\n SECRET_KEY_EXACT.has(key.toLowerCase()) ||\n SECRET_KEY_SUFFIX.test(key) ||\n SECRET_KEY_DELIMITED.test(key);\n\n// Layer 3: string values that look like secrets regardless of their key.\n// Real JWTs are base64url-encoded and the header segment always begins with\n// `eyJ` (the base64url encoding of `{\"`), so requiring that prefix avoids\n// matching arbitrary three-part dotted strings like semver versions\n// (e.g. \"5.50.1\", \"18.3.1\").\nconst JWT_PATTERN = /^eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/;\nconst LONG_TOKEN_PATTERN = /^[A-Fa-f0-9]{32,}$|^[A-Za-z0-9+/]{40,}={0,2}$/;\n// Credentials embedded in a URL authority: `user:pass@` or `:pass@` (empty user,\n// as in `redis://:password@host`). The user part stops at the first colon, as in\n// RFC 3986, so the split between user and password is fixed; letting it take colons\n// made a long colon run with no `@` retry every split point, which is quadratic.\nconst URL_WITH_CREDENTIALS = /^[a-z][a-z0-9+.-]*:\\/\\/[^/@\\s:]*:[^/@\\s]+@/i;\n// PEM private key blocks (certificates are public, so only PRIVATE KEY is masked).\nconst PEM_PRIVATE_KEY_PATTERN = /-----BEGIN(?: [A-Z0-9]+)* PRIVATE KEY-----/;\n// URLs whose secret is carried in the host/path rather than a `user:pass@` authority:\n// chat webhooks and error-tracking DSNs.\nconst SECRET_URL_PATTERN =\n /^https:\\/\\/hooks\\.slack\\.com\\/services\\/|^https:\\/\\/(?:discord|discordapp)\\.com\\/api\\/webhooks\\/|:\\/\\/[^/@\\s]+@[^/\\s]*\\bsentry\\.io\\b/i;\n\n// Well-known provider secret token formats, matched against the whole value. The\n// prefixes are specific enough to have negligible false-positive risk, so they\n// mask a value even under an innocuous key (e.g. `key: 'sk_live_...'`).\n// `pk_` (publishable) keys are intentionally excluded — they are public by design.\nconst PROVIDER_SECRET_PATTERN = new RegExp(\n [\n '^(sk|rk)_(live|test)_[A-Za-z0-9]{8,}$', // Stripe secret / restricted\n '^whsec_[A-Za-z0-9]{16,}$', // Stripe webhook signing secret\n '^(gh[posru]_|github_pat_)[A-Za-z0-9_]{20,}$', // GitHub tokens / fine-grained PAT\n '^xox[baprs]-[A-Za-z0-9-]{10,}$', // Slack tokens\n '^(AKIA|ASIA)[A-Z0-9]{16}$', // AWS access key id\n '^SG\\\\.[A-Za-z0-9_-]{16,}\\\\.[A-Za-z0-9_-]{16,}$', // SendGrid\n '^AIza[A-Za-z0-9_-]{20,}$', // Google API key\n '^ya29\\\\.[A-Za-z0-9_-]{20,}$', // Google OAuth access token\n '^glpat-[A-Za-z0-9_-]{16,}$', // GitLab personal access token\n '^(shpat|shpss|shpca|shppa)_[A-Za-z0-9]{20,}$', // Shopify\n '^dop_v1_[a-f0-9]{40,}$', // DigitalOcean\n '^re_[A-Za-z0-9_]{16,}$', // Resend\n '^nfp_[A-Za-z0-9]{20,}$', // Netlify\n '^EAAA[A-Za-z0-9_-]{20,}$', // Square\n ].join('|')\n);\n\nconst looksSecret = (value: string): boolean =>\n JWT_PATTERN.test(value) ||\n LONG_TOKEN_PATTERN.test(value) ||\n URL_WITH_CREDENTIALS.test(value) ||\n PROVIDER_SECRET_PATTERN.test(value) ||\n PEM_PRIVATE_KEY_PATTERN.test(value) ||\n SECRET_URL_PATTERN.test(value);\n\nexport interface ScrubOptions {\n appRoot?: string;\n homeDir?: string;\n extraPaths?: string[];\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n};\n\n// Accept either separator regardless of the host platform: `os.homedir()` and the app root come\n// back with backslashes on Windows, and a dump may also carry POSIX-style paths (e.g. from\n// config values), so a POSIX-only prefix check would ship absolute Windows paths verbatim.\nconst isPathPrefix = (value: string, prefix: string): boolean => {\n if (value === prefix) {\n return true;\n }\n if (!value.startsWith(prefix)) {\n return false;\n }\n const next = value.charAt(prefix.length);\n return next === '/' || next === '\\\\';\n};\n\nconst relativize = (value: string, appRoot?: string, homeDir?: string): string => {\n if (appRoot && isPathPrefix(value, appRoot)) {\n return `<app>${value.slice(appRoot.length)}`;\n }\n if (homeDir && isPathPrefix(value, homeDir)) {\n return `<home>${value.slice(homeDir.length)}`;\n }\n return value;\n};\n\n// Characters that end a URL authority\nconst AUTHORITY_END = new Set(['/', '?', '#', ' ', '\\t', '\\n', '\\r', '\"', \"'\", '`']);\n\n/**\n * Masks the password of every `scheme://user:password@host` inside a longer string, such as a\n * package.json script that inlines a database URL. Whole-value credential URLs are already\n * caught by URL_WITH_CREDENTIALS; this covers the ones in the middle of a value. It is a single\n * forward scan rather than a regex, because an unanchored pattern backtracks quadratically on\n * long runs (the reason URL_WITH_CREDENTIALS is anchored and colon-free in the user part).\n */\nconst maskEmbeddedCredentials = (value: string): string => {\n let result = '';\n let copiedUpTo = 0;\n let separator = value.indexOf('://');\n\n while (separator !== -1) {\n const authorityStart = separator + 3;\n let firstColon = -1;\n let lastAt = -1;\n let end = authorityStart;\n\n while (end < value.length && !AUTHORITY_END.has(value[end])) {\n if (value[end] === ':' && firstColon === -1) {\n firstColon = end;\n } else if (value[end] === '@') {\n lastAt = end;\n }\n end += 1;\n }\n\n // A colon before the last `@` separates user and password; one after it is a port.\n if (firstColon !== -1 && lastAt > firstColon) {\n result += `${value.slice(copiedUpTo, firstColon + 1)}${REDACTED}`;\n copiedUpTo = lastAt;\n }\n\n separator = value.indexOf('://', end);\n }\n\n return copiedUpTo === 0 ? value : result + value.slice(copiedUpTo);\n};\n\nconst deleteAtPath = (target: unknown, path: string): void => {\n const segments = path.split('.');\n let node: unknown = target;\n for (let i = 0; i < segments.length - 1; i += 1) {\n if (!isPlainObject(node)) {\n return;\n }\n node = node[segments[i]];\n }\n const lastKey = segments[segments.length - 1];\n if (isPlainObject(node) && lastKey in node) {\n node[lastKey] = REDACTED;\n }\n};\n\nconst walk = (value: unknown, appRoot?: string, homeDir?: string): unknown => {\n if (typeof value === 'string') {\n // Relativization is tried FIRST, and a value it rewrote is returned as-is. A string\n // that starts with the app root or the home directory is a path, never a credential,\n // whereas the reverse order let the secret heuristics claim one: a POSIX path made\n // only of letters, digits and `/` is valid standard base64, so anything past 40\n // characters matched LONG_TOKEN_PATTERN and shipped as `[REDACTED]` instead of\n // `<app>/...`. Values that do not relativize still go through the full checks.\n const relativized = relativize(value, appRoot, homeDir);\n if (relativized !== value) {\n return relativized;\n }\n return looksSecret(value) ? REDACTED : maskEmbeddedCredentials(value);\n }\n if (Array.isArray(value)) {\n return value.map((item) => walk(item, appRoot, homeDir));\n }\n if (isPlainObject(value)) {\n const out: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (key === '__proto__') {\n continue; // never write through the Object.prototype setter\n }\n // A secret-named key always collapses wholesale, regardless of the value's\n // type. Recursing into it (e.g. for `apiToken: { salt, ... }`) would leak\n // any inner value whose own key/value doesn't independently match a\n // masking pattern (e.g. `providerOptions.auth.pass`), so there is nothing\n // safe to preserve underneath a secret-named container.\n out[key] = isSecretKey(key) ? REDACTED : walk(val, appRoot, homeDir);\n }\n return out;\n }\n // Any other object type — Buffer, Date, Map, Set, class instances, etc. —\n // is not a plain data container we can safely walk (Object.entries on a\n // Buffer leaks its bytes, a Date serializes to `{}`), so redact defensively.\n if (value !== null && typeof value === 'object') {\n return REDACTED;\n }\n return value;\n};\n\nexport const scrub = (value: unknown, options: ScrubOptions = {}): unknown => {\n const cloned = walk(value, options.appRoot, options.homeDir);\n for (const path of options.extraPaths ?? []) {\n deleteAtPath(cloned, path);\n }\n return cloned;\n};\n"],"names":["REDACTED","SECRET_KEY_PATTERN","SECRET_KEY_EXACT","Set","SECRET_KEY_SUFFIX","SECRET_KEY_DELIMITED","isSecretKey","key","test","has","toLowerCase","JWT_PATTERN","LONG_TOKEN_PATTERN","URL_WITH_CREDENTIALS","PEM_PRIVATE_KEY_PATTERN","SECRET_URL_PATTERN","PROVIDER_SECRET_PATTERN","RegExp","join","looksSecret","value","isPlainObject","Array","isArray","proto","Object","getPrototypeOf","prototype","isPathPrefix","prefix","startsWith","next","charAt","length","relativize","appRoot","homeDir","slice","AUTHORITY_END","maskEmbeddedCredentials","result","copiedUpTo","separator","indexOf","authorityStart","firstColon","lastAt","end","deleteAtPath","target","path","segments","split","node","i","lastKey","walk","relativized","map","item","out","val","entries","scrub","options","cloned","extraPaths"],"mappings":"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"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
const REDACTED = '[REDACTED]';
|
|
2
|
+
// Layer 1a: key names (substring match) whose value must be masked wherever they appear.
|
|
3
|
+
const SECRET_KEY_PATTERN = /(secret|password|passphrase|salt|token|api[_-]?key|access[_-]?key|license[_-]?key|private[_-]?key|encryption[_-]?key|credential|provider[_-]?options|connection[_-]?string|mnemonic|seed[_-]?phrase|authorization|bearer)/i;
|
|
4
|
+
// Layer 1b: short, ambiguous key names matched EXACTLY (case-insensitive), so they
|
|
5
|
+
// do not over-match as substrings (e.g. `pass` must not redact `compass`/`bypass`,
|
|
6
|
+
// and this still catches a nested SMTP `auth.pass`).
|
|
7
|
+
const SECRET_KEY_EXACT = new Set([
|
|
8
|
+
'pass',
|
|
9
|
+
'pwd',
|
|
10
|
+
'passwd',
|
|
11
|
+
'dsn'
|
|
12
|
+
]);
|
|
13
|
+
// camelCase password suffixes (capitalized), e.g. `smtpAuthPass`, `dbPwd` — the
|
|
14
|
+
// capital letter distinguishes them from lowercase look-alikes (`compass`, `bypass`).
|
|
15
|
+
const SECRET_KEY_SUFFIX = /[a-z](Pass|Pwd|Passwd)$/;
|
|
16
|
+
// separator-delimited short secret names, e.g. `auth.pass`, `db_pwd`, `x-pass`.
|
|
17
|
+
const SECRET_KEY_DELIMITED = /(^|[._-])(pass|pwd|passwd|dsn)([._-]|$)/i;
|
|
18
|
+
const isSecretKey = (key)=>SECRET_KEY_PATTERN.test(key) || SECRET_KEY_EXACT.has(key.toLowerCase()) || SECRET_KEY_SUFFIX.test(key) || SECRET_KEY_DELIMITED.test(key);
|
|
19
|
+
// Layer 3: string values that look like secrets regardless of their key.
|
|
20
|
+
// Real JWTs are base64url-encoded and the header segment always begins with
|
|
21
|
+
// `eyJ` (the base64url encoding of `{"`), so requiring that prefix avoids
|
|
22
|
+
// matching arbitrary three-part dotted strings like semver versions
|
|
23
|
+
// (e.g. "5.50.1", "18.3.1").
|
|
24
|
+
const JWT_PATTERN = /^eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
|
|
25
|
+
const LONG_TOKEN_PATTERN = /^[A-Fa-f0-9]{32,}$|^[A-Za-z0-9+/]{40,}={0,2}$/;
|
|
26
|
+
// Credentials embedded in a URL authority: `user:pass@` or `:pass@` (empty user,
|
|
27
|
+
// as in `redis://:password@host`). The user part stops at the first colon, as in
|
|
28
|
+
// RFC 3986, so the split between user and password is fixed; letting it take colons
|
|
29
|
+
// made a long colon run with no `@` retry every split point, which is quadratic.
|
|
30
|
+
const URL_WITH_CREDENTIALS = /^[a-z][a-z0-9+.-]*:\/\/[^/@\s:]*:[^/@\s]+@/i;
|
|
31
|
+
// PEM private key blocks (certificates are public, so only PRIVATE KEY is masked).
|
|
32
|
+
const PEM_PRIVATE_KEY_PATTERN = /-----BEGIN(?: [A-Z0-9]+)* PRIVATE KEY-----/;
|
|
33
|
+
// URLs whose secret is carried in the host/path rather than a `user:pass@` authority:
|
|
34
|
+
// chat webhooks and error-tracking DSNs.
|
|
35
|
+
const SECRET_URL_PATTERN = /^https:\/\/hooks\.slack\.com\/services\/|^https:\/\/(?:discord|discordapp)\.com\/api\/webhooks\/|:\/\/[^/@\s]+@[^/\s]*\bsentry\.io\b/i;
|
|
36
|
+
// Well-known provider secret token formats, matched against the whole value. The
|
|
37
|
+
// prefixes are specific enough to have negligible false-positive risk, so they
|
|
38
|
+
// mask a value even under an innocuous key (e.g. `key: 'sk_live_...'`).
|
|
39
|
+
// `pk_` (publishable) keys are intentionally excluded — they are public by design.
|
|
40
|
+
const PROVIDER_SECRET_PATTERN = new RegExp([
|
|
41
|
+
'^(sk|rk)_(live|test)_[A-Za-z0-9]{8,}$',
|
|
42
|
+
'^whsec_[A-Za-z0-9]{16,}$',
|
|
43
|
+
'^(gh[posru]_|github_pat_)[A-Za-z0-9_]{20,}$',
|
|
44
|
+
'^xox[baprs]-[A-Za-z0-9-]{10,}$',
|
|
45
|
+
'^(AKIA|ASIA)[A-Z0-9]{16}$',
|
|
46
|
+
'^SG\\.[A-Za-z0-9_-]{16,}\\.[A-Za-z0-9_-]{16,}$',
|
|
47
|
+
'^AIza[A-Za-z0-9_-]{20,}$',
|
|
48
|
+
'^ya29\\.[A-Za-z0-9_-]{20,}$',
|
|
49
|
+
'^glpat-[A-Za-z0-9_-]{16,}$',
|
|
50
|
+
'^(shpat|shpss|shpca|shppa)_[A-Za-z0-9]{20,}$',
|
|
51
|
+
'^dop_v1_[a-f0-9]{40,}$',
|
|
52
|
+
'^re_[A-Za-z0-9_]{16,}$',
|
|
53
|
+
'^nfp_[A-Za-z0-9]{20,}$',
|
|
54
|
+
'^EAAA[A-Za-z0-9_-]{20,}$'
|
|
55
|
+
].join('|'));
|
|
56
|
+
const looksSecret = (value)=>JWT_PATTERN.test(value) || LONG_TOKEN_PATTERN.test(value) || URL_WITH_CREDENTIALS.test(value) || PROVIDER_SECRET_PATTERN.test(value) || PEM_PRIVATE_KEY_PATTERN.test(value) || SECRET_URL_PATTERN.test(value);
|
|
57
|
+
const isPlainObject = (value)=>{
|
|
58
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const proto = Object.getPrototypeOf(value);
|
|
62
|
+
return proto === Object.prototype || proto === null;
|
|
63
|
+
};
|
|
64
|
+
// Accept either separator regardless of the host platform: `os.homedir()` and the app root come
|
|
65
|
+
// back with backslashes on Windows, and a dump may also carry POSIX-style paths (e.g. from
|
|
66
|
+
// config values), so a POSIX-only prefix check would ship absolute Windows paths verbatim.
|
|
67
|
+
const isPathPrefix = (value, prefix)=>{
|
|
68
|
+
if (value === prefix) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (!value.startsWith(prefix)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
const next = value.charAt(prefix.length);
|
|
75
|
+
return next === '/' || next === '\\';
|
|
76
|
+
};
|
|
77
|
+
const relativize = (value, appRoot, homeDir)=>{
|
|
78
|
+
if (appRoot && isPathPrefix(value, appRoot)) {
|
|
79
|
+
return `<app>${value.slice(appRoot.length)}`;
|
|
80
|
+
}
|
|
81
|
+
if (homeDir && isPathPrefix(value, homeDir)) {
|
|
82
|
+
return `<home>${value.slice(homeDir.length)}`;
|
|
83
|
+
}
|
|
84
|
+
return value;
|
|
85
|
+
};
|
|
86
|
+
// Characters that end a URL authority
|
|
87
|
+
const AUTHORITY_END = new Set([
|
|
88
|
+
'/',
|
|
89
|
+
'?',
|
|
90
|
+
'#',
|
|
91
|
+
' ',
|
|
92
|
+
'\t',
|
|
93
|
+
'\n',
|
|
94
|
+
'\r',
|
|
95
|
+
'"',
|
|
96
|
+
"'",
|
|
97
|
+
'`'
|
|
98
|
+
]);
|
|
99
|
+
/**
|
|
100
|
+
* Masks the password of every `scheme://user:password@host` inside a longer string, such as a
|
|
101
|
+
* package.json script that inlines a database URL. Whole-value credential URLs are already
|
|
102
|
+
* caught by URL_WITH_CREDENTIALS; this covers the ones in the middle of a value. It is a single
|
|
103
|
+
* forward scan rather than a regex, because an unanchored pattern backtracks quadratically on
|
|
104
|
+
* long runs (the reason URL_WITH_CREDENTIALS is anchored and colon-free in the user part).
|
|
105
|
+
*/ const maskEmbeddedCredentials = (value)=>{
|
|
106
|
+
let result = '';
|
|
107
|
+
let copiedUpTo = 0;
|
|
108
|
+
let separator = value.indexOf('://');
|
|
109
|
+
while(separator !== -1){
|
|
110
|
+
const authorityStart = separator + 3;
|
|
111
|
+
let firstColon = -1;
|
|
112
|
+
let lastAt = -1;
|
|
113
|
+
let end = authorityStart;
|
|
114
|
+
while(end < value.length && !AUTHORITY_END.has(value[end])){
|
|
115
|
+
if (value[end] === ':' && firstColon === -1) {
|
|
116
|
+
firstColon = end;
|
|
117
|
+
} else if (value[end] === '@') {
|
|
118
|
+
lastAt = end;
|
|
119
|
+
}
|
|
120
|
+
end += 1;
|
|
121
|
+
}
|
|
122
|
+
// A colon before the last `@` separates user and password; one after it is a port.
|
|
123
|
+
if (firstColon !== -1 && lastAt > firstColon) {
|
|
124
|
+
result += `${value.slice(copiedUpTo, firstColon + 1)}${REDACTED}`;
|
|
125
|
+
copiedUpTo = lastAt;
|
|
126
|
+
}
|
|
127
|
+
separator = value.indexOf('://', end);
|
|
128
|
+
}
|
|
129
|
+
return copiedUpTo === 0 ? value : result + value.slice(copiedUpTo);
|
|
130
|
+
};
|
|
131
|
+
const deleteAtPath = (target, path)=>{
|
|
132
|
+
const segments = path.split('.');
|
|
133
|
+
let node = target;
|
|
134
|
+
for(let i = 0; i < segments.length - 1; i += 1){
|
|
135
|
+
if (!isPlainObject(node)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
node = node[segments[i]];
|
|
139
|
+
}
|
|
140
|
+
const lastKey = segments[segments.length - 1];
|
|
141
|
+
if (isPlainObject(node) && lastKey in node) {
|
|
142
|
+
node[lastKey] = REDACTED;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const walk = (value, appRoot, homeDir)=>{
|
|
146
|
+
if (typeof value === 'string') {
|
|
147
|
+
// Relativization is tried FIRST, and a value it rewrote is returned as-is. A string
|
|
148
|
+
// that starts with the app root or the home directory is a path, never a credential,
|
|
149
|
+
// whereas the reverse order let the secret heuristics claim one: a POSIX path made
|
|
150
|
+
// only of letters, digits and `/` is valid standard base64, so anything past 40
|
|
151
|
+
// characters matched LONG_TOKEN_PATTERN and shipped as `[REDACTED]` instead of
|
|
152
|
+
// `<app>/...`. Values that do not relativize still go through the full checks.
|
|
153
|
+
const relativized = relativize(value, appRoot, homeDir);
|
|
154
|
+
if (relativized !== value) {
|
|
155
|
+
return relativized;
|
|
156
|
+
}
|
|
157
|
+
return looksSecret(value) ? REDACTED : maskEmbeddedCredentials(value);
|
|
158
|
+
}
|
|
159
|
+
if (Array.isArray(value)) {
|
|
160
|
+
return value.map((item)=>walk(item, appRoot, homeDir));
|
|
161
|
+
}
|
|
162
|
+
if (isPlainObject(value)) {
|
|
163
|
+
const out = {};
|
|
164
|
+
for (const [key, val] of Object.entries(value)){
|
|
165
|
+
if (key === '__proto__') {
|
|
166
|
+
continue; // never write through the Object.prototype setter
|
|
167
|
+
}
|
|
168
|
+
// A secret-named key always collapses wholesale, regardless of the value's
|
|
169
|
+
// type. Recursing into it (e.g. for `apiToken: { salt, ... }`) would leak
|
|
170
|
+
// any inner value whose own key/value doesn't independently match a
|
|
171
|
+
// masking pattern (e.g. `providerOptions.auth.pass`), so there is nothing
|
|
172
|
+
// safe to preserve underneath a secret-named container.
|
|
173
|
+
out[key] = isSecretKey(key) ? REDACTED : walk(val, appRoot, homeDir);
|
|
174
|
+
}
|
|
175
|
+
return out;
|
|
176
|
+
}
|
|
177
|
+
// Any other object type — Buffer, Date, Map, Set, class instances, etc. —
|
|
178
|
+
// is not a plain data container we can safely walk (Object.entries on a
|
|
179
|
+
// Buffer leaks its bytes, a Date serializes to `{}`), so redact defensively.
|
|
180
|
+
if (value !== null && typeof value === 'object') {
|
|
181
|
+
return REDACTED;
|
|
182
|
+
}
|
|
183
|
+
return value;
|
|
184
|
+
};
|
|
185
|
+
const scrub = (value, options = {})=>{
|
|
186
|
+
const cloned = walk(value, options.appRoot, options.homeDir);
|
|
187
|
+
for (const path of options.extraPaths ?? []){
|
|
188
|
+
deleteAtPath(cloned, path);
|
|
189
|
+
}
|
|
190
|
+
return cloned;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export { REDACTED, scrub };
|
|
194
|
+
//# sourceMappingURL=redact.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.mjs","sources":["../../../../../../server/src/utils/debug-dump/redact.ts"],"sourcesContent":["export const REDACTED = '[REDACTED]';\n\n// Layer 1a: key names (substring match) whose value must be masked wherever they appear.\nconst SECRET_KEY_PATTERN =\n /(secret|password|passphrase|salt|token|api[_-]?key|access[_-]?key|license[_-]?key|private[_-]?key|encryption[_-]?key|credential|provider[_-]?options|connection[_-]?string|mnemonic|seed[_-]?phrase|authorization|bearer)/i;\n\n// Layer 1b: short, ambiguous key names matched EXACTLY (case-insensitive), so they\n// do not over-match as substrings (e.g. `pass` must not redact `compass`/`bypass`,\n// and this still catches a nested SMTP `auth.pass`).\nconst SECRET_KEY_EXACT = new Set(['pass', 'pwd', 'passwd', 'dsn']);\n// camelCase password suffixes (capitalized), e.g. `smtpAuthPass`, `dbPwd` — the\n// capital letter distinguishes them from lowercase look-alikes (`compass`, `bypass`).\nconst SECRET_KEY_SUFFIX = /[a-z](Pass|Pwd|Passwd)$/;\n// separator-delimited short secret names, e.g. `auth.pass`, `db_pwd`, `x-pass`.\nconst SECRET_KEY_DELIMITED = /(^|[._-])(pass|pwd|passwd|dsn)([._-]|$)/i;\n\nconst isSecretKey = (key: string): boolean =>\n SECRET_KEY_PATTERN.test(key) ||\n SECRET_KEY_EXACT.has(key.toLowerCase()) ||\n SECRET_KEY_SUFFIX.test(key) ||\n SECRET_KEY_DELIMITED.test(key);\n\n// Layer 3: string values that look like secrets regardless of their key.\n// Real JWTs are base64url-encoded and the header segment always begins with\n// `eyJ` (the base64url encoding of `{\"`), so requiring that prefix avoids\n// matching arbitrary three-part dotted strings like semver versions\n// (e.g. \"5.50.1\", \"18.3.1\").\nconst JWT_PATTERN = /^eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/;\nconst LONG_TOKEN_PATTERN = /^[A-Fa-f0-9]{32,}$|^[A-Za-z0-9+/]{40,}={0,2}$/;\n// Credentials embedded in a URL authority: `user:pass@` or `:pass@` (empty user,\n// as in `redis://:password@host`). The user part stops at the first colon, as in\n// RFC 3986, so the split between user and password is fixed; letting it take colons\n// made a long colon run with no `@` retry every split point, which is quadratic.\nconst URL_WITH_CREDENTIALS = /^[a-z][a-z0-9+.-]*:\\/\\/[^/@\\s:]*:[^/@\\s]+@/i;\n// PEM private key blocks (certificates are public, so only PRIVATE KEY is masked).\nconst PEM_PRIVATE_KEY_PATTERN = /-----BEGIN(?: [A-Z0-9]+)* PRIVATE KEY-----/;\n// URLs whose secret is carried in the host/path rather than a `user:pass@` authority:\n// chat webhooks and error-tracking DSNs.\nconst SECRET_URL_PATTERN =\n /^https:\\/\\/hooks\\.slack\\.com\\/services\\/|^https:\\/\\/(?:discord|discordapp)\\.com\\/api\\/webhooks\\/|:\\/\\/[^/@\\s]+@[^/\\s]*\\bsentry\\.io\\b/i;\n\n// Well-known provider secret token formats, matched against the whole value. The\n// prefixes are specific enough to have negligible false-positive risk, so they\n// mask a value even under an innocuous key (e.g. `key: 'sk_live_...'`).\n// `pk_` (publishable) keys are intentionally excluded — they are public by design.\nconst PROVIDER_SECRET_PATTERN = new RegExp(\n [\n '^(sk|rk)_(live|test)_[A-Za-z0-9]{8,}$', // Stripe secret / restricted\n '^whsec_[A-Za-z0-9]{16,}$', // Stripe webhook signing secret\n '^(gh[posru]_|github_pat_)[A-Za-z0-9_]{20,}$', // GitHub tokens / fine-grained PAT\n '^xox[baprs]-[A-Za-z0-9-]{10,}$', // Slack tokens\n '^(AKIA|ASIA)[A-Z0-9]{16}$', // AWS access key id\n '^SG\\\\.[A-Za-z0-9_-]{16,}\\\\.[A-Za-z0-9_-]{16,}$', // SendGrid\n '^AIza[A-Za-z0-9_-]{20,}$', // Google API key\n '^ya29\\\\.[A-Za-z0-9_-]{20,}$', // Google OAuth access token\n '^glpat-[A-Za-z0-9_-]{16,}$', // GitLab personal access token\n '^(shpat|shpss|shpca|shppa)_[A-Za-z0-9]{20,}$', // Shopify\n '^dop_v1_[a-f0-9]{40,}$', // DigitalOcean\n '^re_[A-Za-z0-9_]{16,}$', // Resend\n '^nfp_[A-Za-z0-9]{20,}$', // Netlify\n '^EAAA[A-Za-z0-9_-]{20,}$', // Square\n ].join('|')\n);\n\nconst looksSecret = (value: string): boolean =>\n JWT_PATTERN.test(value) ||\n LONG_TOKEN_PATTERN.test(value) ||\n URL_WITH_CREDENTIALS.test(value) ||\n PROVIDER_SECRET_PATTERN.test(value) ||\n PEM_PRIVATE_KEY_PATTERN.test(value) ||\n SECRET_URL_PATTERN.test(value);\n\nexport interface ScrubOptions {\n appRoot?: string;\n homeDir?: string;\n extraPaths?: string[];\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n};\n\n// Accept either separator regardless of the host platform: `os.homedir()` and the app root come\n// back with backslashes on Windows, and a dump may also carry POSIX-style paths (e.g. from\n// config values), so a POSIX-only prefix check would ship absolute Windows paths verbatim.\nconst isPathPrefix = (value: string, prefix: string): boolean => {\n if (value === prefix) {\n return true;\n }\n if (!value.startsWith(prefix)) {\n return false;\n }\n const next = value.charAt(prefix.length);\n return next === '/' || next === '\\\\';\n};\n\nconst relativize = (value: string, appRoot?: string, homeDir?: string): string => {\n if (appRoot && isPathPrefix(value, appRoot)) {\n return `<app>${value.slice(appRoot.length)}`;\n }\n if (homeDir && isPathPrefix(value, homeDir)) {\n return `<home>${value.slice(homeDir.length)}`;\n }\n return value;\n};\n\n// Characters that end a URL authority\nconst AUTHORITY_END = new Set(['/', '?', '#', ' ', '\\t', '\\n', '\\r', '\"', \"'\", '`']);\n\n/**\n * Masks the password of every `scheme://user:password@host` inside a longer string, such as a\n * package.json script that inlines a database URL. Whole-value credential URLs are already\n * caught by URL_WITH_CREDENTIALS; this covers the ones in the middle of a value. It is a single\n * forward scan rather than a regex, because an unanchored pattern backtracks quadratically on\n * long runs (the reason URL_WITH_CREDENTIALS is anchored and colon-free in the user part).\n */\nconst maskEmbeddedCredentials = (value: string): string => {\n let result = '';\n let copiedUpTo = 0;\n let separator = value.indexOf('://');\n\n while (separator !== -1) {\n const authorityStart = separator + 3;\n let firstColon = -1;\n let lastAt = -1;\n let end = authorityStart;\n\n while (end < value.length && !AUTHORITY_END.has(value[end])) {\n if (value[end] === ':' && firstColon === -1) {\n firstColon = end;\n } else if (value[end] === '@') {\n lastAt = end;\n }\n end += 1;\n }\n\n // A colon before the last `@` separates user and password; one after it is a port.\n if (firstColon !== -1 && lastAt > firstColon) {\n result += `${value.slice(copiedUpTo, firstColon + 1)}${REDACTED}`;\n copiedUpTo = lastAt;\n }\n\n separator = value.indexOf('://', end);\n }\n\n return copiedUpTo === 0 ? value : result + value.slice(copiedUpTo);\n};\n\nconst deleteAtPath = (target: unknown, path: string): void => {\n const segments = path.split('.');\n let node: unknown = target;\n for (let i = 0; i < segments.length - 1; i += 1) {\n if (!isPlainObject(node)) {\n return;\n }\n node = node[segments[i]];\n }\n const lastKey = segments[segments.length - 1];\n if (isPlainObject(node) && lastKey in node) {\n node[lastKey] = REDACTED;\n }\n};\n\nconst walk = (value: unknown, appRoot?: string, homeDir?: string): unknown => {\n if (typeof value === 'string') {\n // Relativization is tried FIRST, and a value it rewrote is returned as-is. A string\n // that starts with the app root or the home directory is a path, never a credential,\n // whereas the reverse order let the secret heuristics claim one: a POSIX path made\n // only of letters, digits and `/` is valid standard base64, so anything past 40\n // characters matched LONG_TOKEN_PATTERN and shipped as `[REDACTED]` instead of\n // `<app>/...`. Values that do not relativize still go through the full checks.\n const relativized = relativize(value, appRoot, homeDir);\n if (relativized !== value) {\n return relativized;\n }\n return looksSecret(value) ? REDACTED : maskEmbeddedCredentials(value);\n }\n if (Array.isArray(value)) {\n return value.map((item) => walk(item, appRoot, homeDir));\n }\n if (isPlainObject(value)) {\n const out: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (key === '__proto__') {\n continue; // never write through the Object.prototype setter\n }\n // A secret-named key always collapses wholesale, regardless of the value's\n // type. Recursing into it (e.g. for `apiToken: { salt, ... }`) would leak\n // any inner value whose own key/value doesn't independently match a\n // masking pattern (e.g. `providerOptions.auth.pass`), so there is nothing\n // safe to preserve underneath a secret-named container.\n out[key] = isSecretKey(key) ? REDACTED : walk(val, appRoot, homeDir);\n }\n return out;\n }\n // Any other object type — Buffer, Date, Map, Set, class instances, etc. —\n // is not a plain data container we can safely walk (Object.entries on a\n // Buffer leaks its bytes, a Date serializes to `{}`), so redact defensively.\n if (value !== null && typeof value === 'object') {\n return REDACTED;\n }\n return value;\n};\n\nexport const scrub = (value: unknown, options: ScrubOptions = {}): unknown => {\n const cloned = walk(value, options.appRoot, options.homeDir);\n for (const path of options.extraPaths ?? []) {\n deleteAtPath(cloned, path);\n }\n return cloned;\n};\n"],"names":["REDACTED","SECRET_KEY_PATTERN","SECRET_KEY_EXACT","Set","SECRET_KEY_SUFFIX","SECRET_KEY_DELIMITED","isSecretKey","key","test","has","toLowerCase","JWT_PATTERN","LONG_TOKEN_PATTERN","URL_WITH_CREDENTIALS","PEM_PRIVATE_KEY_PATTERN","SECRET_URL_PATTERN","PROVIDER_SECRET_PATTERN","RegExp","join","looksSecret","value","isPlainObject","Array","isArray","proto","Object","getPrototypeOf","prototype","isPathPrefix","prefix","startsWith","next","charAt","length","relativize","appRoot","homeDir","slice","AUTHORITY_END","maskEmbeddedCredentials","result","copiedUpTo","separator","indexOf","authorityStart","firstColon","lastAt","end","deleteAtPath","target","path","segments","split","node","i","lastKey","walk","relativized","map","item","out","val","entries","scrub","options","cloned","extraPaths"],"mappings":"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"}
|