@automattic/jetpack-scan 0.3.0 → 0.4.1

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/CHANGELOG.md CHANGED
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.1] - 2024-11-28
9
+ ### Fixed
10
+ - Fix package build. [#40299]
11
+
12
+ ## [0.4.0] - 2024-11-26
13
+ ### Added
14
+ - Adds utility for retrieving a detailed action description [#40214]
15
+
8
16
  ## [0.3.0] - 2024-11-25
9
17
  ### Added
10
18
  - Adds utilities for retrieving fixer messaging [#40197]
@@ -64,5 +72,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
64
72
  ### Removed
65
73
  - Updated dependencies. [#39754]
66
74
 
75
+ [0.4.1]: https://github.com/Automattic/jetpack-scan/compare/v0.4.0...v0.4.1
76
+ [0.4.0]: https://github.com/Automattic/jetpack-scan/compare/v0.3.0...v0.4.0
67
77
  [0.3.0]: https://github.com/Automattic/jetpack-scan/compare/v0.2.0...v0.3.0
68
78
  [0.2.0]: https://github.com/Automattic/jetpack-scan/compare/v0.1.0...v0.2.0
@@ -0,0 +1,3 @@
1
+ export declare const CONTACT_SUPPORT_URL = "https://jetpack.com/contact-support/?rel=support";
2
+ /** Once a fixer has been running for this specified amount of time (in ms), it should be considered "stale". */
3
+ export declare const FIXER_IS_STALE_THRESHOLD: number;
@@ -0,0 +1,3 @@
1
+ export const CONTACT_SUPPORT_URL = 'https://jetpack.com/contact-support/?rel=support';
2
+ /** Once a fixer has been running for this specified amount of time (in ms), it should be considered "stale". */
3
+ export const FIXER_IS_STALE_THRESHOLD = 1000 * 60 * 60 * 24; // 24 hours
@@ -0,0 +1,3 @@
1
+ export * from './types/index.js';
2
+ export * from './constants/index.js';
3
+ export * from './utils/index.js';
package/build/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './types/index.js';
2
+ export * from './constants/index.js';
3
+ export * from './utils/index.js';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ test('Scan Package', () => {
2
+ expect(true).toBe(true);
3
+ });
4
+ export {};
@@ -0,0 +1,14 @@
1
+ export type FixerStatus = 'not_started' | 'in_progress' | 'fixed' | 'not_fixed';
2
+ /**
3
+ * Threat Fix Status
4
+ *
5
+ * Individual fixer status for a threat.
6
+ */
7
+ export type ThreatFixStatusError = {
8
+ error: string;
9
+ };
10
+ export type ThreatFixStatusSuccess = {
11
+ status: FixerStatus;
12
+ lastUpdated: string;
13
+ };
14
+ export type ThreatFixStatus = ThreatFixStatusError | ThreatFixStatusSuccess;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from './fixers.js';
2
+ export * from './threats.js';
@@ -0,0 +1,2 @@
1
+ export * from './fixers.js';
2
+ export * from './threats.js';
@@ -0,0 +1,46 @@
1
+ import { ThreatFixStatus } from './fixers.js';
2
+ export type ThreatStatus = 'fixed' | 'ignored' | 'current';
3
+ export type ThreatFixType = 'replace' | 'delete' | 'update' | string;
4
+ export type Threat = {
5
+ /** The threat's unique ID. */
6
+ id: string | number;
7
+ /** The threat's title. */
8
+ title?: string;
9
+ /** The threat's description. */
10
+ description?: string;
11
+ /** The threat's current status. */
12
+ status?: ThreatStatus;
13
+ /** The threat's severity level (0-10). */
14
+ severity?: number;
15
+ /** The threat's signature. */
16
+ signature?: string;
17
+ /** The date the threat was first detected on the site, in YYYY-MM-DDTHH:MM:SS.000Z format. */
18
+ firstDetected?: string;
19
+ /** The version the threat is fixed in. */
20
+ fixedIn?: string | null;
21
+ /** The date the threat was fixed, in YYYY-MM-DDTHH:MM:SS.000Z format. */
22
+ fixedOn?: string;
23
+ /** The fixable details. */
24
+ fixable?: {
25
+ fixer: ThreatFixType;
26
+ target?: string | null;
27
+ extensionStatus?: string | null;
28
+ } | false;
29
+ /** The fixer status. */
30
+ fixer?: ThreatFixStatus;
31
+ /** The threat's source. */
32
+ source?: string;
33
+ /** The threat's context. */
34
+ context?: Record<string, unknown>;
35
+ /** The name of the affected file. */
36
+ filename?: string;
37
+ /** The diff showing the threat's modified file contents. */
38
+ diff?: string;
39
+ /** The affected extension. */
40
+ extension?: {
41
+ slug: string;
42
+ name: string;
43
+ version: string;
44
+ type: 'plugin' | 'theme' | 'core';
45
+ };
46
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ import { type ThreatFixStatus } from '../types/fixers.js';
2
+ import { type Threat } from '../types/threats.js';
3
+ export declare const getThreatType: (threat: Threat) => "plugin" | "theme" | "core" | "file";
4
+ export declare const fixerTimestampIsStale: (lastUpdatedTimestamp: string) => boolean;
5
+ export declare const fixerIsInError: (fixerStatus: ThreatFixStatus) => boolean;
6
+ export declare const fixerIsInProgress: (fixerStatus: ThreatFixStatus) => boolean;
7
+ export declare const fixerStatusIsStale: (fixerStatus: ThreatFixStatus) => boolean;
8
+ export declare const getFixerState: (fixerStatus: ThreatFixStatus) => {
9
+ inProgress: boolean;
10
+ error: boolean;
11
+ stale: boolean;
12
+ };
13
+ export declare const getFixerAction: (threat: Threat) => string;
14
+ export declare const getDetailedFixerAction: (threat: Threat) => string;
15
+ export declare const getFixerDescription: (threat: Threat) => string;
@@ -0,0 +1,128 @@
1
+ import { __, sprintf } from '@wordpress/i18n';
2
+ import { FIXER_IS_STALE_THRESHOLD } from '../constants/index.js';
3
+ export const getThreatType = (threat) => {
4
+ if (threat.signature === 'Vulnerable.WP.Core') {
5
+ return 'core';
6
+ }
7
+ if (threat.extension) {
8
+ return threat.extension.type;
9
+ }
10
+ if (threat.filename) {
11
+ return 'file';
12
+ }
13
+ return null;
14
+ };
15
+ export const fixerTimestampIsStale = (lastUpdatedTimestamp) => {
16
+ const now = new Date();
17
+ const lastUpdated = new Date(lastUpdatedTimestamp);
18
+ return now.getTime() - lastUpdated.getTime() >= FIXER_IS_STALE_THRESHOLD;
19
+ };
20
+ export const fixerIsInError = (fixerStatus) => {
21
+ return !!('error' in fixerStatus && fixerStatus.error);
22
+ };
23
+ export const fixerIsInProgress = (fixerStatus) => {
24
+ return !!('status' in fixerStatus && fixerStatus.status === 'in_progress');
25
+ };
26
+ export const fixerStatusIsStale = (fixerStatus) => {
27
+ return (fixerIsInProgress(fixerStatus) &&
28
+ 'lastUpdated' in fixerStatus &&
29
+ !!fixerTimestampIsStale(fixerStatus.lastUpdated));
30
+ };
31
+ export const getFixerState = (fixerStatus) => {
32
+ return {
33
+ inProgress: fixerStatus && fixerIsInProgress(fixerStatus),
34
+ error: fixerStatus && fixerIsInError(fixerStatus),
35
+ stale: fixerStatus && fixerStatusIsStale(fixerStatus),
36
+ };
37
+ };
38
+ export const getFixerAction = (threat) => {
39
+ switch (threat.fixable && threat.fixable.fixer) {
40
+ case 'delete':
41
+ return __('Delete', 'jetpack-scan');
42
+ case 'update':
43
+ return __('Update', 'jetpack-scan');
44
+ case 'replace':
45
+ case 'rollback':
46
+ return __('Replace', 'jetpack-scan');
47
+ default:
48
+ return __('Auto-fix', 'jetpack-scan');
49
+ }
50
+ };
51
+ export const getDetailedFixerAction = (threat) => {
52
+ var _a, _b, _c, _d;
53
+ switch (threat.fixable && threat.fixable.fixer) {
54
+ case 'delete':
55
+ if (threat.filename) {
56
+ return __('Delete file', 'jetpack-scan');
57
+ }
58
+ if (((_a = threat.extension) === null || _a === void 0 ? void 0 : _a.type) === 'plugin') {
59
+ return __('Delete plugin from site', 'jetpack-scan');
60
+ }
61
+ if (((_b = threat.extension) === null || _b === void 0 ? void 0 : _b.type) === 'theme') {
62
+ return __('Delete theme from site', 'jetpack-scan');
63
+ }
64
+ break;
65
+ case 'update':
66
+ if (((_c = threat.extension) === null || _c === void 0 ? void 0 : _c.type) === 'plugin') {
67
+ return __('Update plugin to newer version', 'jetpack-scan');
68
+ }
69
+ if (((_d = threat.extension) === null || _d === void 0 ? void 0 : _d.type) === 'theme') {
70
+ return __('Update theme to newer version', 'jetpack-scan');
71
+ }
72
+ return __('Update', 'jetpack-scan');
73
+ break;
74
+ case 'replace':
75
+ case 'rollback':
76
+ if (threat.filename) {
77
+ return __('Replace from backup', 'jetpack-scan');
78
+ }
79
+ if (threat.signature === 'php_hardening_WP_Config_NoSalts_001') {
80
+ return __('Replace default salts', 'jetpack-scan');
81
+ }
82
+ break;
83
+ default:
84
+ return __('Auto-fix', 'jetpack-scan');
85
+ }
86
+ };
87
+ export const getFixerDescription = (threat) => {
88
+ var _a, _b;
89
+ switch (threat.fixable && threat.fixable.fixer) {
90
+ case 'delete':
91
+ if (threat.filename) {
92
+ if (threat.filename.endsWith('/')) {
93
+ return __('Delete the directory that the infected file is in.', 'jetpack-scan');
94
+ }
95
+ if (threat.signature === 'Core.File.Modification') {
96
+ return __('Delete the unexpected file in a core WordPress directory.', 'jetpack-scan');
97
+ }
98
+ return __('Delete the infected file.', 'jetpack-scan');
99
+ }
100
+ if (((_a = threat.extension) === null || _a === void 0 ? void 0 : _a.type) === 'plugin') {
101
+ return __('Delete the plugin directory to fix the threat.', 'jetpack-scan');
102
+ }
103
+ if (((_b = threat.extension) === null || _b === void 0 ? void 0 : _b.type) === 'theme') {
104
+ return __('Delete the theme directory to fix the threat.', 'jetpack-scan');
105
+ }
106
+ break;
107
+ case 'update':
108
+ if (threat.fixedIn && threat.extension.name) {
109
+ return sprintf(
110
+ /* translators: Translates to Updates to version. %1$s: Name. %2$s: Fixed version */
111
+ __('Update %1$s to version %2$s', 'jetpack-scan'), threat.extension.name, threat.fixedIn);
112
+ }
113
+ return __('Upgrade the plugin or theme to a newer version.', 'jetpack-scan');
114
+ case 'replace':
115
+ case 'rollback':
116
+ if (threat.filename) {
117
+ return threat.signature === 'Core.File.Modification'
118
+ ? __('Replace the modified core WordPress file with the original clean version from the WordPress source code.', 'jetpack-scan')
119
+ : __('Replace the infected file with a previously backed up version that is clean.', 'jetpack-scan');
120
+ }
121
+ if (threat.signature === 'php_hardening_WP_Config_NoSalts_001') {
122
+ return __('Replace the default salt keys in wp-config.php with unique ones.', 'jetpack-scan');
123
+ }
124
+ break;
125
+ default:
126
+ return __('Jetpack will auto-fix the threat.', 'jetpack-scan');
127
+ }
128
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@automattic/jetpack-scan",
4
- "version": "0.3.0",
4
+ "version": "0.4.1",
5
5
  "description": "A JS client for consuming Jetpack Scan services",
6
6
  "homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/scan/#readme",
7
7
  "bugs": {
@@ -23,9 +23,6 @@
23
23
  },
24
24
  "type": "module",
25
25
  "devDependencies": {
26
- "@automattic/jetpack-webpack-config": "workspace:*",
27
- "@babel/core": "7.26.0",
28
- "@babel/plugin-transform-react-jsx": "7.25.9",
29
26
  "@jest/globals": "29.7.0",
30
27
  "@storybook/addon-actions": "8.3.5",
31
28
  "@storybook/blocks": "8.3.5",
@@ -34,8 +31,6 @@
34
31
  "@testing-library/react": "16.0.1",
35
32
  "@types/jest": "29.5.12",
36
33
  "@types/react": "18.3.12",
37
- "@wordpress/babel-plugin-import-jsx-pragma": "5.12.0",
38
- "babel-jest": "29.7.0",
39
34
  "jest": "^29.7.0",
40
35
  "jest-environment-jsdom": "29.7.0",
41
36
  "storybook": "8.3.5",
package/src/index.ts CHANGED
@@ -1,3 +1,3 @@
1
- export * from './types';
2
- export * from './constants';
3
- export * from './utils';
1
+ export * from './types/index.js';
2
+ export * from './constants/index.js';
3
+ export * from './utils/index.js';
@@ -1,2 +1,2 @@
1
- export * from './fixers';
2
- export * from './threats';
1
+ export * from './fixers.js';
2
+ export * from './threats.js';
@@ -1,4 +1,4 @@
1
- import { ThreatFixStatus } from '..';
1
+ import { ThreatFixStatus } from './fixers.js';
2
2
 
3
3
  export type ThreatStatus = 'fixed' | 'ignored' | 'current';
4
4
 
@@ -1,5 +1,7 @@
1
1
  import { __, sprintf } from '@wordpress/i18n';
2
- import { Threat, ThreatFixStatus, FIXER_IS_STALE_THRESHOLD } from '..';
2
+ import { FIXER_IS_STALE_THRESHOLD } from '../constants/index.js';
3
+ import { type ThreatFixStatus } from '../types/fixers.js';
4
+ import { type Threat } from '../types/threats.js';
3
5
 
4
6
  export const getThreatType = ( threat: Threat ) => {
5
7
  if ( threat.signature === 'Vulnerable.WP.Core' ) {
@@ -55,60 +57,99 @@ export const getFixerAction = ( threat: Threat ) => {
55
57
  case 'rollback':
56
58
  return __( 'Replace', 'jetpack-scan' );
57
59
  default:
58
- return __( 'Fix', 'jetpack-scan' );
60
+ return __( 'Auto-fix', 'jetpack-scan' );
59
61
  }
60
62
  };
61
63
 
62
- export const getFixerMessage = ( threat: Threat ) => {
64
+ export const getDetailedFixerAction = ( threat: Threat ) => {
65
+ switch ( threat.fixable && threat.fixable.fixer ) {
66
+ case 'delete':
67
+ if ( threat.filename ) {
68
+ return __( 'Delete file', 'jetpack-scan' );
69
+ }
70
+
71
+ if ( threat.extension?.type === 'plugin' ) {
72
+ return __( 'Delete plugin from site', 'jetpack-scan' );
73
+ }
74
+
75
+ if ( threat.extension?.type === 'theme' ) {
76
+ return __( 'Delete theme from site', 'jetpack-scan' );
77
+ }
78
+ break;
79
+ case 'update':
80
+ if ( threat.extension?.type === 'plugin' ) {
81
+ return __( 'Update plugin to newer version', 'jetpack-scan' );
82
+ }
83
+ if ( threat.extension?.type === 'theme' ) {
84
+ return __( 'Update theme to newer version', 'jetpack-scan' );
85
+ }
86
+ return __( 'Update', 'jetpack-scan' );
87
+ break;
88
+ case 'replace':
89
+ case 'rollback':
90
+ if ( threat.filename ) {
91
+ return __( 'Replace from backup', 'jetpack-scan' );
92
+ }
93
+
94
+ if ( threat.signature === 'php_hardening_WP_Config_NoSalts_001' ) {
95
+ return __( 'Replace default salts', 'jetpack-scan' );
96
+ }
97
+ break;
98
+ default:
99
+ return __( 'Auto-fix', 'jetpack-scan' );
100
+ }
101
+ };
102
+
103
+ export const getFixerDescription = ( threat: Threat ) => {
63
104
  switch ( threat.fixable && threat.fixable.fixer ) {
64
105
  case 'delete':
65
106
  if ( threat.filename ) {
66
107
  if ( threat.filename.endsWith( '/' ) ) {
67
- return __( 'Deletes the directory that the infected file is in.', 'jetpack-scan' );
108
+ return __( 'Delete the directory that the infected file is in.', 'jetpack-scan' );
68
109
  }
69
110
 
70
111
  if ( threat.signature === 'Core.File.Modification' ) {
71
- return __( 'Deletes the unexpected file in a core WordPress directory.', 'jetpack-scan' );
112
+ return __( 'Delete the unexpected file in a core WordPress directory.', 'jetpack-scan' );
72
113
  }
73
114
 
74
- return __( 'Deletes the infected file.', 'jetpack-scan' );
115
+ return __( 'Delete the infected file.', 'jetpack-scan' );
75
116
  }
76
117
 
77
118
  if ( threat.extension?.type === 'plugin' ) {
78
- return __( 'Deletes the plugin directory to fix the threat.', 'jetpack-scan' );
119
+ return __( 'Delete the plugin directory to fix the threat.', 'jetpack-scan' );
79
120
  }
80
121
 
81
122
  if ( threat.extension?.type === 'theme' ) {
82
- return __( 'Deletes the theme directory to fix the threat.', 'jetpack-scan' );
123
+ return __( 'Delete the theme directory to fix the threat.', 'jetpack-scan' );
83
124
  }
84
125
  break;
85
126
  case 'update':
86
127
  if ( threat.fixedIn && threat.extension.name ) {
87
128
  return sprintf(
88
129
  /* translators: Translates to Updates to version. %1$s: Name. %2$s: Fixed version */
89
- __( 'Updates %1$s to version %2$s', 'jetpack-scan' ),
130
+ __( 'Update %1$s to version %2$s', 'jetpack-scan' ),
90
131
  threat.extension.name,
91
132
  threat.fixedIn
92
133
  );
93
134
  }
94
- return __( 'Upgrades the plugin or theme to a newer version.', 'jetpack-scan' );
135
+ return __( 'Upgrade the plugin or theme to a newer version.', 'jetpack-scan' );
95
136
  case 'replace':
96
137
  case 'rollback':
97
138
  if ( threat.filename ) {
98
139
  return threat.signature === 'Core.File.Modification'
99
140
  ? __(
100
- 'Replaces the modified core WordPress file with the original clean version from the WordPress source code.',
141
+ 'Replace the modified core WordPress file with the original clean version from the WordPress source code.',
101
142
  'jetpack-scan'
102
143
  )
103
144
  : __(
104
- 'Replaces the infected file with a previously backed up version that is clean.',
145
+ 'Replace the infected file with a previously backed up version that is clean.',
105
146
  'jetpack-scan'
106
147
  );
107
148
  }
108
149
 
109
150
  if ( threat.signature === 'php_hardening_WP_Config_NoSalts_001' ) {
110
151
  return __(
111
- 'Replaces the default salt keys in wp-config.php with unique ones.',
152
+ 'Replace the default salt keys in wp-config.php with unique ones.',
112
153
  'jetpack-scan'
113
154
  );
114
155
  }