>,
diff --git a/opencti-platform/opencti-front/src/private/components/settings/activity/configuration/Configuration.tsx b/opencti-platform/opencti-front/src/private/components/settings/activity/configuration/Configuration.tsx
index 86d83447344e..f71db95c786a 100644
--- a/opencti-platform/opencti-front/src/private/components/settings/activity/configuration/Configuration.tsx
+++ b/opencti-platform/opencti-front/src/private/components/settings/activity/configuration/Configuration.tsx
@@ -116,9 +116,10 @@ const ConfigurationComponent: FunctionComponent<
);
const currentListeners = (settings.activity_listeners ?? []).map((a) => a.id);
const onChangeData = (resetForm: () => void) => {
- return (name: string, data: FieldOption) => {
- if (!currentListeners.includes(data.value)) {
- const value = R.uniq([...currentListeners, data.value]);
+ return (name: string, data: FieldOption | null) => {
+ const val = data?.value ?? '';
+ if (!currentListeners.includes(val)) {
+ const value = R.uniq([...currentListeners, val]);
commit({
variables: {
id: settings?.id,
diff --git a/opencti-platform/opencti-front/src/utils/field.ts b/opencti-platform/opencti-front/src/utils/field.ts
deleted file mode 100644
index d457facd0acb..000000000000
--- a/opencti-platform/opencti-front/src/utils/field.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-export const fieldSpacingContainerStyle = { marginTop: 20, width: '100%' };
-
-export interface FieldOption {
- id?: string;
- value: string;
- label: string;
- color?: string;
- type?: string;
- standard_id?: string;
-}
-
-// TODO move this interface inside file KillChainPhasesField
-// when it has been transformed it TypeScript.
-export interface KillChainPhaseFieldOption extends FieldOption {
- kill_chain_name: string;
- phase_name: string;
-}
diff --git a/opencti-platform/opencti-front/src/utils/field.tsx b/opencti-platform/opencti-front/src/utils/field.tsx
new file mode 100644
index 000000000000..2b487062f081
--- /dev/null
+++ b/opencti-platform/opencti-front/src/utils/field.tsx
@@ -0,0 +1,32 @@
+import { ComponentType } from 'react';
+import { FieldConfig, Field as FormikField } from 'formik';
+
+export const fieldSpacingContainerStyle = { marginTop: 20, width: '100%' };
+
+export interface FieldOption {
+ id?: string;
+ value: string;
+ label: string;
+ color?: string;
+ type?: string;
+ standard_id?: string;
+}
+
+// TODO move this interface inside file KillChainPhasesField
+// when it has been transformed it TypeScript.
+export interface KillChainPhaseFieldOption extends FieldOption {
+ kill_chain_name: string;
+ phase_name: string;
+}
+
+type FormikFieldConfig = Omit, 'component' | 'as' | 'render' | 'children'>;
+type NoMetaProps = Omit
;
+type FieldProps = FormikFieldConfig & NoMetaProps & {
+ component: ComponentType;
+};
+
+const Field = (props: FieldProps) => {
+ return ;
+};
+
+export default Field;
From d91c19e1e7a50c2642d28de7f1ccf54666b1eb48 Mon Sep 17 00:00:00 2001
From: Xavier Fournet <461943+xfournet@users.noreply.github.com>
Date: Tue, 30 Dec 2025 16:11:59 +0100
Subject: [PATCH 009/126] [backend] Improve template engine (#13831)
---
.../opencti-graphql/src/utils/safeEjs.ts | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/opencti-platform/opencti-graphql/src/utils/safeEjs.ts b/opencti-platform/opencti-graphql/src/utils/safeEjs.ts
index 14c5d1d761f8..2be4dd1643d2 100644
--- a/opencti-platform/opencti-graphql/src/utils/safeEjs.ts
+++ b/opencti-platform/opencti-graphql/src/utils/safeEjs.ts
@@ -111,10 +111,11 @@ const createSafeContext = (async: boolean, { maxExecutedStatementCount = 0, maxE
},
[safeName('property')]: (propertyName: unknown) => {
- if (typeof propertyName === 'string' && (propertyName.startsWith(safeReservedPrefix) || forbiddenProperties.has(propertyName))) {
- throw new VerifierIllegalAccessError(`Forbidden property access ${JSON.stringify({ propertyName })}`);
+ const name = String(propertyName);
+ if (name.startsWith(safeReservedPrefix) || forbiddenProperties.has(name)) {
+ throw new VerifierIllegalAccessError(`Forbidden property access ${JSON.stringify({ propertyName: name })}`);
}
- return propertyName;
+ return name;
},
[safeName('Object')]: Object.freeze({
@@ -127,11 +128,12 @@ const createSafeContext = (async: boolean, { maxExecutedStatementCount = 0, maxE
.filter((src) => src && typeof src === 'object')
.forEach((src) => {
Object.entries(src).forEach(([key, value]) => {
- if (key.startsWith(safeReservedPrefix) || forbiddenProperties.has(key)) {
- throw new VerifierIllegalAccessError(`Forbidden property access ${JSON.stringify({ propertyName: key })}`);
+ const name = String(key); // key should already be a string, but enforce it anyway
+ if (name.startsWith(safeReservedPrefix) || forbiddenProperties.has(name)) {
+ throw new VerifierIllegalAccessError(`Forbidden property access ${JSON.stringify({ propertyName: name })}`);
}
- target[key] = value;
+ target[name] = value;
});
});
return target;
From 2518d2e397e74edf612a9c67d72c69bbb8e23872 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9line=20S=C3=A8be?=
<87119259+CelineSebe@users.noreply.github.com>
Date: Tue, 30 Dec 2025 17:19:00 +0100
Subject: [PATCH 010/126] [frontend] TypesField & SelectField to ts (#13845)
---
.../{SelectField.jsx => SelectField.tsx} | 62 +++++++----
.../components/observations/TypesField.jsx | 63 -----------
.../components/observations/TypesField.tsx | 104 ++++++++++++++++++
3 files changed, 143 insertions(+), 86 deletions(-)
rename opencti-platform/opencti-front/src/components/fields/{SelectField.jsx => SelectField.tsx} (58%)
delete mode 100644 opencti-platform/opencti-front/src/private/components/observations/TypesField.jsx
create mode 100644 opencti-platform/opencti-front/src/private/components/observations/TypesField.tsx
diff --git a/opencti-platform/opencti-front/src/components/fields/SelectField.jsx b/opencti-platform/opencti-front/src/components/fields/SelectField.tsx
similarity index 58%
rename from opencti-platform/opencti-front/src/components/fields/SelectField.jsx
rename to opencti-platform/opencti-front/src/components/fields/SelectField.tsx
index 6e802fc46765..e8340bb464d4 100644
--- a/opencti-platform/opencti-front/src/components/fields/SelectField.jsx
+++ b/opencti-platform/opencti-front/src/components/fields/SelectField.tsx
@@ -1,39 +1,52 @@
import React from 'react';
import { isNil } from 'ramda';
-import { getIn, useField } from 'formik';
+import { FieldProps, getIn, useField } from 'formik';
import { v4 as uuid } from 'uuid';
import MuiSelect from '@mui/material/Select';
import InputLabel from '@mui/material/InputLabel';
import FormControl from '@mui/material/FormControl';
import FormHelperText from '@mui/material/FormHelperText';
+import { SelectProps } from '@mui/material';
-const fieldToSelect = ({
- disabled,
- field: { onChange: fieldOnChange, ...field },
- form: { isSubmitting, touched, errors, setFieldTouched, setFieldValue },
- onClose,
- ...props
-}) => {
+export type SelectFieldProps = FieldProps & Omit, 'onChange' | 'onFocus'> & {
+ required: boolean;
+ onChange?: (name: string, value: string) => void;
+ onFocus?: (name: string) => void;
+ onSubmit?: (name: string, value: string) => void;
+ containerstyle?: Record;
+ helpertext?: string;
+};
+
+const fieldToSelect = (muiProps: SelectFieldProps) => {
+ const {
+ disabled,
+ field: { onChange: fieldOnChange, ...field },
+ form: { isSubmitting, touched, errors, setFieldTouched, setFieldValue },
+ onClose,
+ } = muiProps;
const fieldError = getIn(errors, field.name);
const showError = getIn(touched, field.name) && !!fieldError;
+
return {
+ ...field,
+ ...muiProps,
disabled: disabled ?? isSubmitting,
error: showError,
onBlur: () => {},
onChange: fieldOnChange ?? (() => {}),
onClose: onClose ?? (async (e) => {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
const { dataset } = e.target;
if (dataset && dataset.value) {
await setFieldValue(field.name, dataset.value);
}
setFieldTouched(field.name, true);
}),
- ...field,
- ...props,
};
};
-const SelectField = (props) => {
+const SelectField = (muiProps: SelectFieldProps) => {
const {
form: { setFieldValue, setFieldTouched },
field: { name },
@@ -41,8 +54,11 @@ const SelectField = (props) => {
onChange,
onFocus,
onSubmit,
- } = props;
- const internalOnChange = React.useCallback(
+ containerstyle,
+ helpertext,
+ } = muiProps;
+
+ const internalOnChange = React.useCallback['onChange']>>(
(event) => {
const { value } = event.target;
setFieldValue(name, value);
@@ -52,12 +68,12 @@ const SelectField = (props) => {
},
[setFieldValue, onChange, name],
);
- const internalOnFocus = React.useCallback(() => {
+ const internalOnFocus = React.useCallback['onFocus']>>(() => {
if (typeof onFocus === 'function') {
onFocus(name);
}
}, [onFocus, name]);
- const internalOnBlur = React.useCallback(
+ const internalOnBlur = React.useCallback['onBlur']>>(
(event) => {
const { value } = event.target;
setFieldTouched(name, true);
@@ -68,22 +84,22 @@ const SelectField = (props) => {
[setFieldTouched, onSubmit, name],
);
const [, meta] = useField(name);
- const { value, ...otherProps } = fieldToSelect(props);
+ const { value, ...otherProps } = fieldToSelect(muiProps);
const labelId = uuid();
return (
- {props.label}
+ {muiProps.label}
{
labelId={labelId}
/>
- {meta.touched && !isNil(meta.error) ? meta.error : props.helpertext}
+ {meta.touched && !isNil(meta.error) ? meta.error : helpertext}
);
diff --git a/opencti-platform/opencti-front/src/private/components/observations/TypesField.jsx b/opencti-platform/opencti-front/src/private/components/observations/TypesField.jsx
deleted file mode 100644
index 207af8dbfc6a..000000000000
--- a/opencti-platform/opencti-front/src/private/components/observations/TypesField.jsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import React, { Component } from 'react';
-import * as PropTypes from 'prop-types';
-import { Field } from 'formik';
-import { assoc, compose, map, pipe, prop, sortBy, toLower } from 'ramda';
-import withStyles from '@mui/styles/withStyles';
-import MenuItem from '@mui/material/MenuItem';
-import inject18n from '../../../components/i18n';
-import SelectField from '../../../components/fields/SelectField';
-import { QueryRenderer } from '../../../relay/environment';
-import { stixCyberObservablesLinesSubTypesQuery } from './stix_cyber_observables/StixCyberObservablesLines';
-
-const styles = () => ({
- container: {
- margin: 0,
- },
-});
-
-class TypesField extends Component {
- render() {
- const { t, name, label, containerstyle } = this.props;
- return (
- {
- if (props && props.subTypes) {
- const subTypesEdges = props.subTypes.edges;
- const sortByLabel = sortBy(compose(toLower, prop('tlabel')));
- const translatedOrderedList = pipe(
- map((n) => n.node),
- map((n) => assoc('tlabel', t(`entity_${n.label}`), n)),
- sortByLabel,
- )(subTypesEdges);
- return (
-
- {translatedOrderedList.map((subType) => (
-
- ))}
-
- );
- }
- return ;
- }}
- />
- );
- }
-}
-
-TypesField.propTypes = {
- classes: PropTypes.object,
- t: PropTypes.func,
-};
-
-export default compose(inject18n, withStyles(styles))(TypesField);
diff --git a/opencti-platform/opencti-front/src/private/components/observations/TypesField.tsx b/opencti-platform/opencti-front/src/private/components/observations/TypesField.tsx
new file mode 100644
index 000000000000..282fc37f4fef
--- /dev/null
+++ b/opencti-platform/opencti-front/src/private/components/observations/TypesField.tsx
@@ -0,0 +1,104 @@
+import React, { Suspense } from 'react';
+import { Field } from 'formik';
+import MenuItem from '@mui/material/MenuItem';
+import { useFormatter } from '../../../components/i18n';
+import SelectField from '../../../components/fields/SelectField';
+import { stixCyberObservablesLinesSubTypesQuery } from './stix_cyber_observables/StixCyberObservablesLines';
+import useQueryLoading from 'src/utils/hooks/useQueryLoading';
+import { PreloadedQuery, usePreloadedQuery } from 'react-relay';
+import { StixCyberObservablesLinesSubTypesQuery } from '@components/observations/stix_cyber_observables/__generated__/StixCyberObservablesLinesSubTypesQuery.graphql';
+
+interface TypesFieldComponentProps {
+ queryRef: PreloadedQuery;
+ name: string;
+ label?: string;
+ required?: boolean;
+ containerstyle?: Record;
+ multiple?: boolean;
+ onChange?: (name: string, value: string | string[]) => void;
+}
+interface TLabel {
+ tlabel: string;
+}
+
+const TypesFieldComponent = ({
+ name,
+ label,
+ required = false,
+ containerstyle,
+ queryRef,
+}: TypesFieldComponentProps) => {
+ const { t_i18n } = useFormatter();
+ const { subTypes } = usePreloadedQuery(stixCyberObservablesLinesSubTypesQuery, queryRef);
+
+ if (subTypes) {
+ const subTypesEdges = subTypes.edges;
+ const sortByLabel = (arr: T[]): T[] =>
+ [...arr].sort((a, b) => {
+ const labelA = String(a.tlabel).toLowerCase();
+ const labelB = String(b.tlabel).toLowerCase();
+ return labelA.localeCompare(labelB);
+ });
+
+ const translatedOrderedList = sortByLabel(
+ subTypesEdges
+ .map((n) => n.node)
+ .map((n) => ({
+ ...n,
+ tlabel: t_i18n(`entity_${n.label}`),
+ })),
+ );
+ return (
+
+ {translatedOrderedList.map((subType) => (
+
+ ))}
+
+ );
+ }
+};
+
+type TypesFieldProps = Omit;
+
+const TypesField = (props: TypesFieldProps) => {
+ const { name, label, containerstyle, required } = props;
+
+ const queryRef = useQueryLoading(
+ stixCyberObservablesLinesSubTypesQuery,
+ { type: 'Stix-Cyber-Observable' },
+ );
+ const FallbackSelect = (
+
+ );
+
+ return (
+
+ {queryRef && (
+
+ )}
+
+ );
+};
+
+export default TypesField;
From fbf8846263d8a90ebf43851ba85205090a563e31 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 30 Dec 2025 19:03:06 +0100
Subject: [PATCH 011/126] [deps] Update dependency nodemailer to v7.0.12
(#13834)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
opencti-platform/opencti-graphql/package.json | 2 +-
opencti-platform/opencti-graphql/yarn.lock | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/opencti-platform/opencti-graphql/package.json b/opencti-platform/opencti-graphql/package.json
index da26b005724c..1a4115d2a5fd 100644
--- a/opencti-platform/opencti-graphql/package.json
+++ b/opencti-platform/opencti-graphql/package.json
@@ -142,7 +142,7 @@
"node-calls-python": "1.11.1",
"node-fetch": "3.3.2",
"node-forge": "1.3.3",
- "nodemailer": "7.0.11",
+ "nodemailer": "7.0.12",
"openai": "4.104.0",
"openid-client": "5.7.1",
"opentelemetry-node-metrics": "3.0.0",
diff --git a/opencti-platform/opencti-graphql/yarn.lock b/opencti-platform/opencti-graphql/yarn.lock
index 167636e3179d..ad33a7e0fe4e 100644
--- a/opencti-platform/opencti-graphql/yarn.lock
+++ b/opencti-platform/opencti-graphql/yarn.lock
@@ -10657,10 +10657,10 @@ __metadata:
languageName: node
linkType: hard
-"nodemailer@npm:7.0.11":
- version: 7.0.11
- resolution: "nodemailer@npm:7.0.11"
- checksum: 10c0/208f108fdb4c5dd0e3a2f013578d53dad505cf1b9c7a084f6d22fc9d6f3912daafb4a23793ca568ff848afc35f15f4eb24382d3f6f9fb8ede4a8410d4ca63618
+"nodemailer@npm:7.0.12":
+ version: 7.0.12
+ resolution: "nodemailer@npm:7.0.12"
+ checksum: 10c0/b03948744423386b5fd7cb5bdf60797f2f71c4d3db202eedf7e0037429b5887cb90b641e7ca244af3b96e0b76949e3135cba96336fb0d3ade00ae33727ca8cf8
languageName: node
linkType: hard
@@ -11036,7 +11036,7 @@ __metadata:
node-calls-python: "npm:1.11.1"
node-fetch: "npm:3.3.2"
node-forge: "npm:1.3.3"
- nodemailer: "npm:7.0.11"
+ nodemailer: "npm:7.0.12"
openai: "npm:4.104.0"
openid-client: "npm:5.7.1"
opentelemetry-node-metrics: "npm:3.0.0"
From bad8a0e12c1b503a2382dcbf78d25517a3a92a52 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 30 Dec 2025 19:06:22 +0100
Subject: [PATCH 012/126] [deps] Update dependency slack to v6.1.2 (#13836)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
.circleci/config.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 9f3ce984f5e8..a9c6638be27b 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,6 +1,6 @@
version: 2.1
orbs:
- slack: circleci/slack@6.1.1
+ slack: circleci/slack@6.1.2
kubernetes: circleci/kubernetes@1.3.1
jobs:
# Client-python steps
From 3ec07d3add0ad91021ded2e238e3e33ad5e07e1d Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 30 Dec 2025 19:06:51 +0100
Subject: [PATCH 013/126] [deps] Update dependency file-type to v21.2.0
(#13843)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
opencti-platform/opencti-graphql/package.json | 2 +-
opencti-platform/opencti-graphql/yarn.lock | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/opencti-platform/opencti-graphql/package.json b/opencti-platform/opencti-graphql/package.json
index 1a4115d2a5fd..90eeab2fa220 100644
--- a/opencti-platform/opencti-graphql/package.json
+++ b/opencti-platform/opencti-graphql/package.json
@@ -110,7 +110,7 @@
"express-rate-limit": "8.2.1",
"express-session": "1.18.2",
"fast-json-patch": "3.1.1",
- "file-type": "21.1.1",
+ "file-type": "21.2.0",
"github-api": "3.4.0",
"graphql": "16.12.0",
"graphql-constraint-directive": "6.0.0",
diff --git a/opencti-platform/opencti-graphql/yarn.lock b/opencti-platform/opencti-graphql/yarn.lock
index ad33a7e0fe4e..af9624bf5016 100644
--- a/opencti-platform/opencti-graphql/yarn.lock
+++ b/opencti-platform/opencti-graphql/yarn.lock
@@ -8191,15 +8191,15 @@ __metadata:
languageName: node
linkType: hard
-"file-type@npm:21.1.1":
- version: 21.1.1
- resolution: "file-type@npm:21.1.1"
+"file-type@npm:21.2.0":
+ version: 21.2.0
+ resolution: "file-type@npm:21.2.0"
dependencies:
"@tokenizer/inflate": "npm:^0.4.1"
strtok3: "npm:^10.3.4"
token-types: "npm:^6.1.1"
uint8array-extras: "npm:^1.4.0"
- checksum: 10c0/2df4375a934ddb74ad071c70012d863c993a90792a01c6c9128c02dc47e0adf724e9eff8b0489d880ee345d34df713a34536564a39a9c6db780475710fb9f366
+ checksum: 10c0/af72f992fb8a6d9ff3a43dfe9293cab4f6b4faec7dc7f950e10c30fda9d5e5799e5fc45ad749fe5b2c1076699716f47ebcf0d573a6ad8640da82e35f36a481cf
languageName: node
linkType: hard
@@ -11002,7 +11002,7 @@ __metadata:
express-rate-limit: "npm:8.2.1"
express-session: "npm:1.18.2"
fast-json-patch: "npm:3.1.1"
- file-type: "npm:21.1.1"
+ file-type: "npm:21.2.0"
github-api: "npm:3.4.0"
globals: "npm:16.5.0"
graphql: "npm:16.12.0"
From 56e820a403de8fc5b23a52dce2d2afc7d34ca0b9 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 30 Dec 2025 19:07:17 +0100
Subject: [PATCH 014/126] [deps] Update dependency typescript-eslint to v8.50.1
(#13842)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
opencti-platform/opencti-front/package.json | 2 +-
opencti-platform/opencti-front/yarn.lock | 146 +++++++++---------
opencti-platform/opencti-graphql/package.json | 2 +-
opencti-platform/opencti-graphql/yarn.lock | 146 +++++++++---------
4 files changed, 148 insertions(+), 148 deletions(-)
diff --git a/opencti-platform/opencti-front/package.json b/opencti-platform/opencti-front/package.json
index bc6a68b6607b..b9eca95014bf 100644
--- a/opencti-platform/opencti-front/package.json
+++ b/opencti-platform/opencti-front/package.json
@@ -172,7 +172,7 @@
"relay-compiler": "20.1.1",
"relay-test-utils": "20.1.1",
"typescript": "5.9.3",
- "typescript-eslint": "8.50.0",
+ "typescript-eslint": "8.50.1",
"vite": "7.3.0",
"vite-plugin-relay": "2.1.0",
"vite-plugin-static-copy": "3.1.4",
diff --git a/opencti-platform/opencti-front/yarn.lock b/opencti-platform/opencti-front/yarn.lock
index 8df86446e1bc..8600214fef86 100644
--- a/opencti-platform/opencti-front/yarn.lock
+++ b/opencti-platform/opencti-front/yarn.lock
@@ -5102,94 +5102,94 @@ __metadata:
languageName: node
linkType: hard
-"@typescript-eslint/eslint-plugin@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/eslint-plugin@npm:8.50.0"
+"@typescript-eslint/eslint-plugin@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/eslint-plugin@npm:8.50.1"
dependencies:
"@eslint-community/regexpp": "npm:^4.10.0"
- "@typescript-eslint/scope-manager": "npm:8.50.0"
- "@typescript-eslint/type-utils": "npm:8.50.0"
- "@typescript-eslint/utils": "npm:8.50.0"
- "@typescript-eslint/visitor-keys": "npm:8.50.0"
+ "@typescript-eslint/scope-manager": "npm:8.50.1"
+ "@typescript-eslint/type-utils": "npm:8.50.1"
+ "@typescript-eslint/utils": "npm:8.50.1"
+ "@typescript-eslint/visitor-keys": "npm:8.50.1"
ignore: "npm:^7.0.0"
natural-compare: "npm:^1.4.0"
ts-api-utils: "npm:^2.1.0"
peerDependencies:
- "@typescript-eslint/parser": ^8.50.0
+ "@typescript-eslint/parser": ^8.50.1
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/032038ee029d1e0984e7c189c3e8173dc4fb909c3ab4d272227e62e6d1872eb9853699c72d46e269c0a084f113ea01fa00d4b61620190276b224fa1b5a5cbd80
+ checksum: 10c0/cae56cec414dc5d8347f1ff9fc01ec7b82c7988bcca9597569564b69e1715594e044487805a72ce7a9b4e6e81c3632db92c3d4b6b991874dafa402e1fcb508d5
languageName: node
linkType: hard
-"@typescript-eslint/parser@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/parser@npm:8.50.0"
+"@typescript-eslint/parser@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/parser@npm:8.50.1"
dependencies:
- "@typescript-eslint/scope-manager": "npm:8.50.0"
- "@typescript-eslint/types": "npm:8.50.0"
- "@typescript-eslint/typescript-estree": "npm:8.50.0"
- "@typescript-eslint/visitor-keys": "npm:8.50.0"
+ "@typescript-eslint/scope-manager": "npm:8.50.1"
+ "@typescript-eslint/types": "npm:8.50.1"
+ "@typescript-eslint/typescript-estree": "npm:8.50.1"
+ "@typescript-eslint/visitor-keys": "npm:8.50.1"
debug: "npm:^4.3.4"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/3bdc9e7b2190285abf7350039056b104725fa70cbd769695717f9948669de4987db7103a7011d33d25d44e9474fe02404746816b8eba72642e17815cb6b0b2e6
+ checksum: 10c0/60a2591745650b35cd8d425bb1959ef40d598245481bdfdc2654ed1f7878364c2c442ba70ca7105b650d0df2b6109727dd43214be76045667de0d32a221f3955
languageName: node
linkType: hard
-"@typescript-eslint/project-service@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/project-service@npm:8.50.0"
+"@typescript-eslint/project-service@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/project-service@npm:8.50.1"
dependencies:
- "@typescript-eslint/tsconfig-utils": "npm:^8.50.0"
- "@typescript-eslint/types": "npm:^8.50.0"
+ "@typescript-eslint/tsconfig-utils": "npm:^8.50.1"
+ "@typescript-eslint/types": "npm:^8.50.1"
debug: "npm:^4.3.4"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/54fdf4c8540eb8e592ab4818345935300bf5776621274cdc8bb942e72e84a4d2566b047b77218f6c851de26eab759c45153a39557ed2c2d1054d180d587d9780
+ checksum: 10c0/50fee0882188c2d704deddfb39f5283618adf7e5f72418143e9f69a8f3771233d55a3e0fc2673fa09c62e230ec53e500f95c0f1ed331ffac5f6a7f8e7b7a2e8c
languageName: node
linkType: hard
-"@typescript-eslint/scope-manager@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/scope-manager@npm:8.50.0"
+"@typescript-eslint/scope-manager@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/scope-manager@npm:8.50.1"
dependencies:
- "@typescript-eslint/types": "npm:8.50.0"
- "@typescript-eslint/visitor-keys": "npm:8.50.0"
- checksum: 10c0/62a374aaa0bf7d185be43a4d7dd420d7135ab8f13f5cb4e602e16fdf712f0e00e6ab3fc8a31321e19922d27b867579b0b08c4040b23d528853f4b73e9ebcff3b
+ "@typescript-eslint/types": "npm:8.50.1"
+ "@typescript-eslint/visitor-keys": "npm:8.50.1"
+ checksum: 10c0/ef0df092745f5d4e3684a3d770dc47735ab3195456de4ac5825931aeed1857a7e8d7cec14cc9c78c5ed049b3d83b0f8ac43b9463c5032ba548558a06bebb5539
languageName: node
linkType: hard
-"@typescript-eslint/tsconfig-utils@npm:8.50.0, @typescript-eslint/tsconfig-utils@npm:^8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/tsconfig-utils@npm:8.50.0"
+"@typescript-eslint/tsconfig-utils@npm:8.50.1, @typescript-eslint/tsconfig-utils@npm:^8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/tsconfig-utils@npm:8.50.1"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/5398d26e4a7bec866cc783f5f329a4fed1bc07cd4d21c5c32929a7524b1ebf8ae8e15ca7a035d1177630d86b614ecd3243d63289228bbe292526dbcbf9fae430
+ checksum: 10c0/6a1ffb0cd2d9e820ed0c7555a43ebb21438ca80f26c9632e0753bd09e764d9b8e9a352215e4ae60f6d570ab1e77751c9460a00515648b9a2f13f56c56a068a94
languageName: node
linkType: hard
-"@typescript-eslint/type-utils@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/type-utils@npm:8.50.0"
+"@typescript-eslint/type-utils@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/type-utils@npm:8.50.1"
dependencies:
- "@typescript-eslint/types": "npm:8.50.0"
- "@typescript-eslint/typescript-estree": "npm:8.50.0"
- "@typescript-eslint/utils": "npm:8.50.0"
+ "@typescript-eslint/types": "npm:8.50.1"
+ "@typescript-eslint/typescript-estree": "npm:8.50.1"
+ "@typescript-eslint/utils": "npm:8.50.1"
debug: "npm:^4.3.4"
ts-api-utils: "npm:^2.1.0"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/7ebd9a1ebd0cbb6eca9864439f80c2432545bd3ac38dee706be0004c78a26a9908003aa4f0825c0745f4fa1356ffacc0848dd230eae22a6516a02710ab645157
+ checksum: 10c0/e4bfd3dd2459e936f7b6d9ee4b60fdedbf4b8f6b3d832e11d3cb1b58c1ce6da098880daafe3b65b2d33e2f79aba0e75c4b6eafdfa2a66c6e00a9ad3132b8e90d
languageName: node
linkType: hard
-"@typescript-eslint/types@npm:8.50.0, @typescript-eslint/types@npm:^8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/types@npm:8.50.0"
- checksum: 10c0/15ec0d75deb331c5ccda726ad95d7f2801fde0f5edfe70425bbdede9e3c9e93b18e7890c9bc42f86ebd65221ebce75e6cc536a65cb1fbbdb0763df22ac392c7a
+"@typescript-eslint/types@npm:8.50.1, @typescript-eslint/types@npm:^8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/types@npm:8.50.1"
+ checksum: 10c0/04e3c296d81293e370578762be6736fccd1581476f9d534938d42fe93968571fcaf26d7d8c3de52ed63a5af2c0b2da922b8ee2011fa5fb9fb401fc7f0916367a
languageName: node
linkType: hard
@@ -5200,14 +5200,14 @@ __metadata:
languageName: node
linkType: hard
-"@typescript-eslint/typescript-estree@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/typescript-estree@npm:8.50.0"
+"@typescript-eslint/typescript-estree@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/typescript-estree@npm:8.50.1"
dependencies:
- "@typescript-eslint/project-service": "npm:8.50.0"
- "@typescript-eslint/tsconfig-utils": "npm:8.50.0"
- "@typescript-eslint/types": "npm:8.50.0"
- "@typescript-eslint/visitor-keys": "npm:8.50.0"
+ "@typescript-eslint/project-service": "npm:8.50.1"
+ "@typescript-eslint/tsconfig-utils": "npm:8.50.1"
+ "@typescript-eslint/types": "npm:8.50.1"
+ "@typescript-eslint/visitor-keys": "npm:8.50.1"
debug: "npm:^4.3.4"
minimatch: "npm:^9.0.4"
semver: "npm:^7.6.0"
@@ -5215,32 +5215,32 @@ __metadata:
ts-api-utils: "npm:^2.1.0"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/30344ba5aab687dc50d805c33d4b481cc68c96acdcc679e8a1f46c5b4d8ba1ee562e3f377a4dc1c6418adf5b3fd342b31e5d30e54d0e7b18628ef6b1fb484341
+ checksum: 10c0/697b53fd3355619271a7bf543c5880731670b96567da63f554a3c3cd4d746feb8153628ec912c8a2df95e3123472e9a77df43c32fad72946b69ace89c2cf8b7e
languageName: node
linkType: hard
-"@typescript-eslint/utils@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/utils@npm:8.50.0"
+"@typescript-eslint/utils@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/utils@npm:8.50.1"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.7.0"
- "@typescript-eslint/scope-manager": "npm:8.50.0"
- "@typescript-eslint/types": "npm:8.50.0"
- "@typescript-eslint/typescript-estree": "npm:8.50.0"
+ "@typescript-eslint/scope-manager": "npm:8.50.1"
+ "@typescript-eslint/types": "npm:8.50.1"
+ "@typescript-eslint/typescript-estree": "npm:8.50.1"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/4069fbf56717401629c86ea1e36df3a7dc1bbbf5c11ec7b26add2b61cdb9070b48786dc45c8e35a872a0cddced1edef654557e27420b9a666616cead539b3ec0
+ checksum: 10c0/66b19a9c8981b0b601af3a477fdcabdd110b0805591f28eefa11b32bbb88518d80b928e49eaa4c40d42ea8d71605bf5cd2ee5e39802022d1daec2800f1b198df
languageName: node
linkType: hard
-"@typescript-eslint/visitor-keys@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/visitor-keys@npm:8.50.0"
+"@typescript-eslint/visitor-keys@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/visitor-keys@npm:8.50.1"
dependencies:
- "@typescript-eslint/types": "npm:8.50.0"
+ "@typescript-eslint/types": "npm:8.50.1"
eslint-visitor-keys: "npm:^4.2.1"
- checksum: 10c0/a13337ecc2042229b922b03882d6691df63053445aa8860f6fcc1da59d04d05f75d4e0ee132551b76d5c5f665e881eb89f327a6f0e83240860f913dff5d745ee
+ checksum: 10c0/b23839d04b2e5e7964a4006317d75cdc3cf76e56f4c5fde1e0bcd23f3bb78dca910e3dcadca80606f76a09ff9e44b3363ee1e1d6394e3f7479da74a641a8870f
languageName: node
linkType: hard
@@ -12574,7 +12574,7 @@ __metadata:
rxjs: "npm:7.8.2"
three-spritetext: "npm:1.10.0"
typescript: "npm:5.9.3"
- typescript-eslint: "npm:8.50.0"
+ typescript-eslint: "npm:8.50.1"
use-analytics: "npm:1.1.0"
uuid: "npm:11.1.0"
vite: "npm:7.3.0"
@@ -15450,18 +15450,18 @@ __metadata:
languageName: node
linkType: hard
-"typescript-eslint@npm:8.50.0":
- version: 8.50.0
- resolution: "typescript-eslint@npm:8.50.0"
+"typescript-eslint@npm:8.50.1":
+ version: 8.50.1
+ resolution: "typescript-eslint@npm:8.50.1"
dependencies:
- "@typescript-eslint/eslint-plugin": "npm:8.50.0"
- "@typescript-eslint/parser": "npm:8.50.0"
- "@typescript-eslint/typescript-estree": "npm:8.50.0"
- "@typescript-eslint/utils": "npm:8.50.0"
+ "@typescript-eslint/eslint-plugin": "npm:8.50.1"
+ "@typescript-eslint/parser": "npm:8.50.1"
+ "@typescript-eslint/typescript-estree": "npm:8.50.1"
+ "@typescript-eslint/utils": "npm:8.50.1"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/63f96505fdfc7d0ff0b5d0338c5877a76ef0933ea3a0c90b2a5d73a7f0ee18d778dc673d9345de3bcb6f37ae02fd930301ef13b2e162c4850f08ad89f1c19613
+ checksum: 10c0/481095a249c48fa1d3551c50ceb8dcfba22413d6175f586ee802200342478a24b566b49d59e618c835631e4071ba1902d8549dc6467f47adb3079d00394d614f
languageName: node
linkType: hard
diff --git a/opencti-platform/opencti-graphql/package.json b/opencti-platform/opencti-graphql/package.json
index 90eeab2fa220..ecba8b2b95d0 100644
--- a/opencti-platform/opencti-graphql/package.json
+++ b/opencti-platform/opencti-graphql/package.json
@@ -204,7 +204,7 @@
"globals": "16.5.0",
"graphql-tag": "2.12.6",
"typescript": "5.9.3",
- "typescript-eslint": "8.50.0",
+ "typescript-eslint": "8.50.1",
"vitest": "3.2.4"
},
"resolutions": {
diff --git a/opencti-platform/opencti-graphql/yarn.lock b/opencti-platform/opencti-graphql/yarn.lock
index af9624bf5016..9ab82efedd0d 100644
--- a/opencti-platform/opencti-graphql/yarn.lock
+++ b/opencti-platform/opencti-graphql/yarn.lock
@@ -5159,94 +5159,94 @@ __metadata:
languageName: node
linkType: hard
-"@typescript-eslint/eslint-plugin@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/eslint-plugin@npm:8.50.0"
+"@typescript-eslint/eslint-plugin@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/eslint-plugin@npm:8.50.1"
dependencies:
"@eslint-community/regexpp": "npm:^4.10.0"
- "@typescript-eslint/scope-manager": "npm:8.50.0"
- "@typescript-eslint/type-utils": "npm:8.50.0"
- "@typescript-eslint/utils": "npm:8.50.0"
- "@typescript-eslint/visitor-keys": "npm:8.50.0"
+ "@typescript-eslint/scope-manager": "npm:8.50.1"
+ "@typescript-eslint/type-utils": "npm:8.50.1"
+ "@typescript-eslint/utils": "npm:8.50.1"
+ "@typescript-eslint/visitor-keys": "npm:8.50.1"
ignore: "npm:^7.0.0"
natural-compare: "npm:^1.4.0"
ts-api-utils: "npm:^2.1.0"
peerDependencies:
- "@typescript-eslint/parser": ^8.50.0
+ "@typescript-eslint/parser": ^8.50.1
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/032038ee029d1e0984e7c189c3e8173dc4fb909c3ab4d272227e62e6d1872eb9853699c72d46e269c0a084f113ea01fa00d4b61620190276b224fa1b5a5cbd80
+ checksum: 10c0/cae56cec414dc5d8347f1ff9fc01ec7b82c7988bcca9597569564b69e1715594e044487805a72ce7a9b4e6e81c3632db92c3d4b6b991874dafa402e1fcb508d5
languageName: node
linkType: hard
-"@typescript-eslint/parser@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/parser@npm:8.50.0"
+"@typescript-eslint/parser@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/parser@npm:8.50.1"
dependencies:
- "@typescript-eslint/scope-manager": "npm:8.50.0"
- "@typescript-eslint/types": "npm:8.50.0"
- "@typescript-eslint/typescript-estree": "npm:8.50.0"
- "@typescript-eslint/visitor-keys": "npm:8.50.0"
+ "@typescript-eslint/scope-manager": "npm:8.50.1"
+ "@typescript-eslint/types": "npm:8.50.1"
+ "@typescript-eslint/typescript-estree": "npm:8.50.1"
+ "@typescript-eslint/visitor-keys": "npm:8.50.1"
debug: "npm:^4.3.4"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/3bdc9e7b2190285abf7350039056b104725fa70cbd769695717f9948669de4987db7103a7011d33d25d44e9474fe02404746816b8eba72642e17815cb6b0b2e6
+ checksum: 10c0/60a2591745650b35cd8d425bb1959ef40d598245481bdfdc2654ed1f7878364c2c442ba70ca7105b650d0df2b6109727dd43214be76045667de0d32a221f3955
languageName: node
linkType: hard
-"@typescript-eslint/project-service@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/project-service@npm:8.50.0"
+"@typescript-eslint/project-service@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/project-service@npm:8.50.1"
dependencies:
- "@typescript-eslint/tsconfig-utils": "npm:^8.50.0"
- "@typescript-eslint/types": "npm:^8.50.0"
+ "@typescript-eslint/tsconfig-utils": "npm:^8.50.1"
+ "@typescript-eslint/types": "npm:^8.50.1"
debug: "npm:^4.3.4"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/54fdf4c8540eb8e592ab4818345935300bf5776621274cdc8bb942e72e84a4d2566b047b77218f6c851de26eab759c45153a39557ed2c2d1054d180d587d9780
+ checksum: 10c0/50fee0882188c2d704deddfb39f5283618adf7e5f72418143e9f69a8f3771233d55a3e0fc2673fa09c62e230ec53e500f95c0f1ed331ffac5f6a7f8e7b7a2e8c
languageName: node
linkType: hard
-"@typescript-eslint/scope-manager@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/scope-manager@npm:8.50.0"
+"@typescript-eslint/scope-manager@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/scope-manager@npm:8.50.1"
dependencies:
- "@typescript-eslint/types": "npm:8.50.0"
- "@typescript-eslint/visitor-keys": "npm:8.50.0"
- checksum: 10c0/62a374aaa0bf7d185be43a4d7dd420d7135ab8f13f5cb4e602e16fdf712f0e00e6ab3fc8a31321e19922d27b867579b0b08c4040b23d528853f4b73e9ebcff3b
+ "@typescript-eslint/types": "npm:8.50.1"
+ "@typescript-eslint/visitor-keys": "npm:8.50.1"
+ checksum: 10c0/ef0df092745f5d4e3684a3d770dc47735ab3195456de4ac5825931aeed1857a7e8d7cec14cc9c78c5ed049b3d83b0f8ac43b9463c5032ba548558a06bebb5539
languageName: node
linkType: hard
-"@typescript-eslint/tsconfig-utils@npm:8.50.0, @typescript-eslint/tsconfig-utils@npm:^8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/tsconfig-utils@npm:8.50.0"
+"@typescript-eslint/tsconfig-utils@npm:8.50.1, @typescript-eslint/tsconfig-utils@npm:^8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/tsconfig-utils@npm:8.50.1"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/5398d26e4a7bec866cc783f5f329a4fed1bc07cd4d21c5c32929a7524b1ebf8ae8e15ca7a035d1177630d86b614ecd3243d63289228bbe292526dbcbf9fae430
+ checksum: 10c0/6a1ffb0cd2d9e820ed0c7555a43ebb21438ca80f26c9632e0753bd09e764d9b8e9a352215e4ae60f6d570ab1e77751c9460a00515648b9a2f13f56c56a068a94
languageName: node
linkType: hard
-"@typescript-eslint/type-utils@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/type-utils@npm:8.50.0"
+"@typescript-eslint/type-utils@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/type-utils@npm:8.50.1"
dependencies:
- "@typescript-eslint/types": "npm:8.50.0"
- "@typescript-eslint/typescript-estree": "npm:8.50.0"
- "@typescript-eslint/utils": "npm:8.50.0"
+ "@typescript-eslint/types": "npm:8.50.1"
+ "@typescript-eslint/typescript-estree": "npm:8.50.1"
+ "@typescript-eslint/utils": "npm:8.50.1"
debug: "npm:^4.3.4"
ts-api-utils: "npm:^2.1.0"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/7ebd9a1ebd0cbb6eca9864439f80c2432545bd3ac38dee706be0004c78a26a9908003aa4f0825c0745f4fa1356ffacc0848dd230eae22a6516a02710ab645157
+ checksum: 10c0/e4bfd3dd2459e936f7b6d9ee4b60fdedbf4b8f6b3d832e11d3cb1b58c1ce6da098880daafe3b65b2d33e2f79aba0e75c4b6eafdfa2a66c6e00a9ad3132b8e90d
languageName: node
linkType: hard
-"@typescript-eslint/types@npm:8.50.0, @typescript-eslint/types@npm:^8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/types@npm:8.50.0"
- checksum: 10c0/15ec0d75deb331c5ccda726ad95d7f2801fde0f5edfe70425bbdede9e3c9e93b18e7890c9bc42f86ebd65221ebce75e6cc536a65cb1fbbdb0763df22ac392c7a
+"@typescript-eslint/types@npm:8.50.1, @typescript-eslint/types@npm:^8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/types@npm:8.50.1"
+ checksum: 10c0/04e3c296d81293e370578762be6736fccd1581476f9d534938d42fe93968571fcaf26d7d8c3de52ed63a5af2c0b2da922b8ee2011fa5fb9fb401fc7f0916367a
languageName: node
linkType: hard
@@ -5257,14 +5257,14 @@ __metadata:
languageName: node
linkType: hard
-"@typescript-eslint/typescript-estree@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/typescript-estree@npm:8.50.0"
+"@typescript-eslint/typescript-estree@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/typescript-estree@npm:8.50.1"
dependencies:
- "@typescript-eslint/project-service": "npm:8.50.0"
- "@typescript-eslint/tsconfig-utils": "npm:8.50.0"
- "@typescript-eslint/types": "npm:8.50.0"
- "@typescript-eslint/visitor-keys": "npm:8.50.0"
+ "@typescript-eslint/project-service": "npm:8.50.1"
+ "@typescript-eslint/tsconfig-utils": "npm:8.50.1"
+ "@typescript-eslint/types": "npm:8.50.1"
+ "@typescript-eslint/visitor-keys": "npm:8.50.1"
debug: "npm:^4.3.4"
minimatch: "npm:^9.0.4"
semver: "npm:^7.6.0"
@@ -5272,32 +5272,32 @@ __metadata:
ts-api-utils: "npm:^2.1.0"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/30344ba5aab687dc50d805c33d4b481cc68c96acdcc679e8a1f46c5b4d8ba1ee562e3f377a4dc1c6418adf5b3fd342b31e5d30e54d0e7b18628ef6b1fb484341
+ checksum: 10c0/697b53fd3355619271a7bf543c5880731670b96567da63f554a3c3cd4d746feb8153628ec912c8a2df95e3123472e9a77df43c32fad72946b69ace89c2cf8b7e
languageName: node
linkType: hard
-"@typescript-eslint/utils@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/utils@npm:8.50.0"
+"@typescript-eslint/utils@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/utils@npm:8.50.1"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.7.0"
- "@typescript-eslint/scope-manager": "npm:8.50.0"
- "@typescript-eslint/types": "npm:8.50.0"
- "@typescript-eslint/typescript-estree": "npm:8.50.0"
+ "@typescript-eslint/scope-manager": "npm:8.50.1"
+ "@typescript-eslint/types": "npm:8.50.1"
+ "@typescript-eslint/typescript-estree": "npm:8.50.1"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/4069fbf56717401629c86ea1e36df3a7dc1bbbf5c11ec7b26add2b61cdb9070b48786dc45c8e35a872a0cddced1edef654557e27420b9a666616cead539b3ec0
+ checksum: 10c0/66b19a9c8981b0b601af3a477fdcabdd110b0805591f28eefa11b32bbb88518d80b928e49eaa4c40d42ea8d71605bf5cd2ee5e39802022d1daec2800f1b198df
languageName: node
linkType: hard
-"@typescript-eslint/visitor-keys@npm:8.50.0":
- version: 8.50.0
- resolution: "@typescript-eslint/visitor-keys@npm:8.50.0"
+"@typescript-eslint/visitor-keys@npm:8.50.1":
+ version: 8.50.1
+ resolution: "@typescript-eslint/visitor-keys@npm:8.50.1"
dependencies:
- "@typescript-eslint/types": "npm:8.50.0"
+ "@typescript-eslint/types": "npm:8.50.1"
eslint-visitor-keys: "npm:^4.2.1"
- checksum: 10c0/a13337ecc2042229b922b03882d6691df63053445aa8860f6fcc1da59d04d05f75d4e0ee132551b76d5c5f665e881eb89f327a6f0e83240860f913dff5d745ee
+ checksum: 10c0/b23839d04b2e5e7964a4006317d75cdc3cf76e56f4c5fde1e0bcd23f3bb78dca910e3dcadca80606f76a09ff9e44b3363ee1e1d6394e3f7479da74a641a8870f
languageName: node
linkType: hard
@@ -11056,7 +11056,7 @@ __metadata:
tough-cookie: "npm:6.0.0"
turndown: "npm:7.2.2"
typescript: "npm:5.9.3"
- typescript-eslint: "npm:8.50.0"
+ typescript-eslint: "npm:8.50.1"
unzipper: "npm:0.12.3"
uuid: "npm:11.1.0"
uuid-time: "npm:1.0.0"
@@ -13210,18 +13210,18 @@ __metadata:
languageName: node
linkType: hard
-"typescript-eslint@npm:8.50.0":
- version: 8.50.0
- resolution: "typescript-eslint@npm:8.50.0"
+"typescript-eslint@npm:8.50.1":
+ version: 8.50.1
+ resolution: "typescript-eslint@npm:8.50.1"
dependencies:
- "@typescript-eslint/eslint-plugin": "npm:8.50.0"
- "@typescript-eslint/parser": "npm:8.50.0"
- "@typescript-eslint/typescript-estree": "npm:8.50.0"
- "@typescript-eslint/utils": "npm:8.50.0"
+ "@typescript-eslint/eslint-plugin": "npm:8.50.1"
+ "@typescript-eslint/parser": "npm:8.50.1"
+ "@typescript-eslint/typescript-estree": "npm:8.50.1"
+ "@typescript-eslint/utils": "npm:8.50.1"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: ">=4.8.4 <6.0.0"
- checksum: 10c0/63f96505fdfc7d0ff0b5d0338c5877a76ef0933ea3a0c90b2a5d73a7f0ee18d778dc673d9345de3bcb6f37ae02fd930301ef13b2e162c4850f08ad89f1c19613
+ checksum: 10c0/481095a249c48fa1d3551c50ceb8dcfba22413d6175f586ee802200342478a24b566b49d59e618c835631e4071ba1902d8549dc6467f47adb3079d00394d614f
languageName: node
linkType: hard
From f21fcb9eaa6818cf671b68e65f1731af83c4435a Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 30 Dec 2025 19:07:51 +0100
Subject: [PATCH 015/126] [deps] Update GitHub Artifact Actions (major)
(#13704)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
.github/workflows/ci-docker-build.yml | 4 ++--
.github/workflows/ci-test-api.yml | 12 ++++++------
.github/workflows/ci-test-client-python.yml | 2 +-
.github/workflows/ci-test-frontend.yml | 2 +-
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/ci-docker-build.yml b/.github/workflows/ci-docker-build.yml
index bc9a2ac4a4ca..36c62ec50869 100644
--- a/.github/workflows/ci-docker-build.yml
+++ b/.github/workflows/ci-docker-build.yml
@@ -83,7 +83,7 @@ jobs:
- name: Upload opencti docker image artifact
if: ${{ inputs.publish_to_registry == 'false' }}
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v6
with:
name: docker-image-opencti-platform
path: /tmp/opencti-platform.tar
@@ -135,7 +135,7 @@ jobs:
labels: ${{ steps.meta.outputs.labels }}
- name: Upload artifact
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v6
with:
name: docker-image-opencti-worker
path: /tmp/opencti-worker.tar
diff --git a/.github/workflows/ci-test-api.yml b/.github/workflows/ci-test-api.yml
index d1544a0f9bd8..ba10bae5b791 100644
--- a/.github/workflows/ci-test-api.yml
+++ b/.github/workflows/ci-test-api.yml
@@ -28,13 +28,13 @@ jobs:
- name: Download image platform
continue-on-error: true
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v7
with:
name: docker-image-opencti-platform
path: /tmp
- name: Download image worker
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v7
with:
name: docker-image-opencti-worker
path: /tmp
@@ -87,7 +87,7 @@ jobs:
'
- name: Upload backend test result
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
if: always()
continue-on-error: true
with:
@@ -150,13 +150,13 @@ jobs:
- name: Download image platform
continue-on-error: true
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v7
with:
name: docker-image-opencti-platform
path: /tmp
- name: Download image worker
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v7
with:
name: docker-image-opencti-worker
path: /tmp
@@ -225,7 +225,7 @@ jobs:
- name: Download image platform
continue-on-error: true
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v7
with:
name: docker-image-opencti-platform
path: /tmp
diff --git a/.github/workflows/ci-test-client-python.yml b/.github/workflows/ci-test-client-python.yml
index f591da03df4b..bfc7dc882c44 100644
--- a/.github/workflows/ci-test-client-python.yml
+++ b/.github/workflows/ci-test-client-python.yml
@@ -39,7 +39,7 @@ jobs:
- name: Download image platform
continue-on-error: true
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v7
with:
name: docker-image-opencti-platform
path: /tmp
diff --git a/.github/workflows/ci-test-frontend.yml b/.github/workflows/ci-test-frontend.yml
index 6534f613b4b7..747811443417 100644
--- a/.github/workflows/ci-test-frontend.yml
+++ b/.github/workflows/ci-test-frontend.yml
@@ -163,7 +163,7 @@ jobs:
'
- name: Upload front e2e test results
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v6
if: always()
continue-on-error: true
with:
From d5f983e67b95e7ca17777cff63fe9e458667ccff Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 30 Dec 2025 21:42:29 +0100
Subject: [PATCH 016/126] [deps] Update dependency html-react-parser to v5.2.11
(#13813)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
opencti-platform/opencti-front/package.json | 2 +-
opencti-platform/opencti-front/yarn.lock | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/opencti-platform/opencti-front/package.json b/opencti-platform/opencti-front/package.json
index b9eca95014bf..7efcf3b4b437 100644
--- a/opencti-platform/opencti-front/package.json
+++ b/opencti-platform/opencti-front/package.json
@@ -71,7 +71,7 @@
"graphiql": "4.1.2",
"graphql": "16.12.0",
"graphql-ws": "5.16.2",
- "html-react-parser": "5.2.10",
+ "html-react-parser": "5.2.11",
"html-to-image": "1.11.13",
"html-to-pdfmake": "2.5.32",
"invert-color": "2.0.0",
diff --git a/opencti-platform/opencti-front/yarn.lock b/opencti-platform/opencti-front/yarn.lock
index 8600214fef86..7767529e7f6d 100644
--- a/opencti-platform/opencti-front/yarn.lock
+++ b/opencti-platform/opencti-front/yarn.lock
@@ -9620,9 +9620,9 @@ __metadata:
languageName: node
linkType: hard
-"html-react-parser@npm:5.2.10":
- version: 5.2.10
- resolution: "html-react-parser@npm:5.2.10"
+"html-react-parser@npm:5.2.11":
+ version: 5.2.11
+ resolution: "html-react-parser@npm:5.2.11"
dependencies:
domhandler: "npm:5.0.3"
html-dom-parser: "npm:5.1.2"
@@ -9634,7 +9634,7 @@ __metadata:
peerDependenciesMeta:
"@types/react":
optional: true
- checksum: 10c0/af93dc554eb47633a2a8d1a5c9276768730606fd30f7355de30e02ad6ef16bb269b0e4b4ae7190ba1a056da43acf2c17cd4fae0f3981486d117f6b3646245974
+ checksum: 10c0/9173df6db4523aab142e1e4c4b55bf9ae6a18a6581d98a2ce9d92af0d3a5dccebb39f26719cf3b5d35d7cc21d49fc774508dda54146771ac7e67e9a1fa252d8a
languageName: node
linkType: hard
@@ -12514,7 +12514,7 @@ __metadata:
graphiql: "npm:4.1.2"
graphql: "npm:16.12.0"
graphql-ws: "npm:5.16.2"
- html-react-parser: "npm:5.2.10"
+ html-react-parser: "npm:5.2.11"
html-to-image: "npm:1.11.13"
html-to-pdfmake: "npm:2.5.32"
http-proxy-middleware: "npm:3.0.5"
From c6105c3a45d034cf9d646d9439e8f32b437f20b1 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 30 Dec 2025 21:43:36 +0100
Subject: [PATCH 017/126] [deps] Update dependency pdfmake to v0.2.21 (#13835)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
opencti-platform/opencti-front/package.json | 2 +-
opencti-platform/opencti-front/yarn.lock | 37 +++++++++++++--------
2 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/opencti-platform/opencti-front/package.json b/opencti-platform/opencti-front/package.json
index 7efcf3b4b437..7b175f71c8bf 100644
--- a/opencti-platform/opencti-front/package.json
+++ b/opencti-platform/opencti-front/package.json
@@ -85,7 +85,7 @@
"mdi-material-ui": "7.9.4",
"moment": "2.30.1",
"moment-timezone": "0.6.0",
- "pdfmake": "0.2.20",
+ "pdfmake": "0.2.21",
"prop-types": "15.8.1",
"qrcode": "1.5.4",
"ramda": "0.32.0",
diff --git a/opencti-platform/opencti-front/yarn.lock b/opencti-platform/opencti-front/yarn.lock
index 7767529e7f6d..23f32dea1fd4 100644
--- a/opencti-platform/opencti-front/yarn.lock
+++ b/opencti-platform/opencti-front/yarn.lock
@@ -9812,7 +9812,7 @@ __metadata:
languageName: node
linkType: hard
-"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3":
+"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2":
version: 0.6.3
resolution: "iconv-lite@npm:0.6.3"
dependencies:
@@ -9830,6 +9830,15 @@ __metadata:
languageName: node
linkType: hard
+"iconv-lite@npm:^0.7.1":
+ version: 0.7.1
+ resolution: "iconv-lite@npm:0.7.1"
+ dependencies:
+ safer-buffer: "npm:>= 2.1.2 < 3.0.0"
+ checksum: 10c0/f5c9e2bddd7101a71b07a381ace44ebdc65ca76a10be0e9e64d372b511132acc4ee41b830962f438840d492cd6f9e08c237289f760d6a7fed754e61cffcb6757
+ languageName: node
+ linkType: hard
+
"ieee754@npm:^1.2.1":
version: 1.2.1
resolution: "ieee754@npm:1.2.1"
@@ -12533,7 +12542,7 @@ __metadata:
moment: "npm:2.30.1"
moment-timezone: "npm:0.6.0"
monocart-reporter: "npm:2.9.23"
- pdfmake: "npm:0.2.20"
+ pdfmake: "npm:0.2.21"
prop-types: "npm:15.8.1"
qrcode: "npm:1.5.4"
ramda: "npm:0.32.0"
@@ -12828,15 +12837,15 @@ __metadata:
languageName: node
linkType: hard
-"pdfmake@npm:0.2.20":
- version: 0.2.20
- resolution: "pdfmake@npm:0.2.20"
+"pdfmake@npm:0.2.21":
+ version: 0.2.21
+ resolution: "pdfmake@npm:0.2.21"
dependencies:
"@foliojs-fork/linebreak": "npm:^1.1.2"
"@foliojs-fork/pdfkit": "npm:^0.15.3"
- iconv-lite: "npm:^0.6.3"
- xmldoc: "npm:^2.0.1"
- checksum: 10c0/6464d408aa7c214561753f01701ffa387e8ba2784e6000977fc1b7e360958d2a256989451f72a73bf9d4d313a0b77d0d11378bf8451a65edfa95c56c82eac043
+ iconv-lite: "npm:^0.7.1"
+ xmldoc: "npm:^2.0.3"
+ checksum: 10c0/72385405832823f72adc82f7956c34d8ad6a8821ae0c48145346508c924a64979008fb88ef3d2686fc67ca18da93e0ac2823873f3e4d7f8f0364d9d487a5d5e2
languageName: node
linkType: hard
@@ -14266,7 +14275,7 @@ __metadata:
languageName: node
linkType: hard
-"sax@npm:^1.2.4, sax@npm:^1.4.1":
+"sax@npm:^1.4.1, sax@npm:^1.4.3":
version: 1.4.3
resolution: "sax@npm:1.4.3"
checksum: 10c0/45bba07561d93f184a8686e1a543418ced8c844b994fbe45cc49d5cd2fc8ac7ec949dae38565e35e388ad0cca2b75997a29b6857c927bf6553da3f80ed0e4e62
@@ -16494,12 +16503,12 @@ __metadata:
languageName: node
linkType: hard
-"xmldoc@npm:^2.0.1":
- version: 2.0.2
- resolution: "xmldoc@npm:2.0.2"
+"xmldoc@npm:^2.0.3":
+ version: 2.0.3
+ resolution: "xmldoc@npm:2.0.3"
dependencies:
- sax: "npm:^1.2.4"
- checksum: 10c0/dbf42e50a136e99be811238dd6b5bf7a0ff2af539b8aa0253f4932c9cc26cf8a20122e287fc0f12553d8cd2dc726a4ecac90cd1922654b788ac7bb1dc3e8cfa8
+ sax: "npm:^1.4.3"
+ checksum: 10c0/8b01fc2b49f7dfa3fc0506d7ae4bab41476e15836114a1ab3794a5dc925498e2f4c248391479f57426e166a718082e6628c7112a89e6bf015ed780c9772f4406
languageName: node
linkType: hard
From 3537eced7b4ab6fe9dd70b087e25a89f56add5b3 Mon Sep 17 00:00:00 2001
From: hervyt
Date: Wed, 31 Dec 2025 14:39:09 +0100
Subject: [PATCH 018/126] [frontend/backend] - (TaxiiFeeds) Add service account
#13848
---
...g.tsx => IngestionEditionUserHandling.tsx} | 72 ++++------
.../data/ingestionCsv/IngestionCsvEdition.tsx | 21 ++-
.../ingestionTaxii/IngestionTaxiiCreation.jsx | 13 +-
.../ingestionTaxii/IngestionTaxiiEdition.tsx | 35 ++++-
.../src/schema/relay.schema.graphql | 10 +-
.../opencti-graphql/src/generated/graphql.ts | 19 ++-
.../ingestion/ingestion-taxii-domain.ts | 22 ++-
.../ingestion/ingestion-taxii-resolver.ts | 13 +-
.../modules/ingestion/ingestion-taxii.graphql | 10 +-
.../02-resolvers/ingestion-taxii-test.ts | 126 ++++++++++++++++--
.../04-manager/ingestionManager-test.ts | 52 ++++----
11 files changed, 293 insertions(+), 100 deletions(-)
rename opencti-platform/opencti-front/src/private/components/data/{ingestionCsv/IngestionCsvEditionUserHandling.tsx => IngestionEditionUserHandling.tsx} (65%)
diff --git a/opencti-platform/opencti-front/src/private/components/data/ingestionCsv/IngestionCsvEditionUserHandling.tsx b/opencti-platform/opencti-front/src/private/components/data/IngestionEditionUserHandling.tsx
similarity index 65%
rename from opencti-platform/opencti-front/src/private/components/data/ingestionCsv/IngestionCsvEditionUserHandling.tsx
rename to opencti-platform/opencti-front/src/private/components/data/IngestionEditionUserHandling.tsx
index a5b3324da9c6..d8c81737dd66 100644
--- a/opencti-platform/opencti-front/src/private/components/data/ingestionCsv/IngestionCsvEditionUserHandling.tsx
+++ b/opencti-platform/opencti-front/src/private/components/data/IngestionEditionUserHandling.tsx
@@ -11,16 +11,17 @@ import { graphql } from 'react-relay';
import { FormikConfig } from 'formik/dist/types';
import { Formik } from 'formik';
import * as Yup from 'yup';
-import { IngestionCsvEditionUserHandlingQuery$data } from '@components/data/ingestionCsv/__generated__/IngestionCsvEditionUserHandlingQuery.graphql';
import Alert from '@mui/material/Alert';
-import { fetchQuery } from '../../../../relay/environment';
-import { useFormatter } from '../../../../components/i18n';
-import { fieldSpacingContainerStyle } from '../../../../utils/field';
-import Transition from '../../../../components/Transition';
-import useApiMutation from '../../../../utils/hooks/useApiMutation';
-
-export const ingestionCsvEditionUserHandlingQuery = graphql`
- query IngestionCsvEditionUserHandlingQuery(
+import { fetchQuery } from '../../../relay/environment';
+import { useFormatter } from '../../../components/i18n';
+import { fieldSpacingContainerStyle } from '../../../utils/field';
+import Transition from '../../../components/Transition';
+import useApiMutation from '../../../utils/hooks/useApiMutation';
+import { IngestionEditionUserHandlingQuery$data } from '@components/data/__generated__/IngestionEditionUserHandlingQuery.graphql';
+import { GraphQLTaggedNode } from 'relay-runtime/lib/query/RelayModernGraphQLTag';
+
+export const ingestionEditionUserHandlingQuery = graphql`
+ query IngestionEditionUserHandlingQuery(
$name: String!
) {
userAlreadyExists(
@@ -29,72 +30,53 @@ export const ingestionCsvEditionUserHandlingQuery = graphql`
}
`;
-export const ingestionCsvEditionUserHandlingFragment = graphql`
- fragment IngestionCsvEditionUserHandlingFragment_ingestionCsv on IngestionCsv {
- id
- name
- user {
- id
- entity_type
- name
- }
- }
-`;
-export const ingestionCsvEditionUserHandlingPatch = graphql`
- mutation IngestionCsvEditionUserHandlingMutation($id: ID!, $input: IngestionCsvAddAutoUserInput!) {
- ingestionCsvAddAutoUser(id: $id, input: $input) {
- ...IngestionCsvEditionUserHandlingFragment_ingestionCsv
- }
- }
-`;
-
-export interface EditionCsvAddAutoUserInput {
+export interface IngestionEditionAddAutoUserInput {
user_name: string;
confidence_level: number;
}
-interface IngestionCsvEditionUserHandlingProps {
+interface IngestionEditionUserHandlingProps {
feedName: string;
- ingestionCsvDataId: string;
+ dataId: string;
onAutoUserCreated: () => void;
+ mutation: GraphQLTaggedNode;
}
-const IngestionCsvEditionUserHandling: FunctionComponent = ({ feedName, ingestionCsvDataId, onAutoUserCreated }) => {
+const IngestionEditionUserHandling: FunctionComponent = ({ feedName, dataId, onAutoUserCreated, mutation }) => {
const { t_i18n } = useFormatter();
const [openDialog, setOpenDialog] = useState(false);
- const [commitUpdate] = useApiMutation(ingestionCsvEditionUserHandlingPatch);
- const ingestionCsvCreationValidation = () => Yup.object().shape({
+ const [commitUpdate] = useApiMutation(mutation);
+ const validationSchema = () => Yup.object().shape({
user_name: Yup.string(),
- confidence_level: Yup.string(),
+ confidence_level: Yup.number(),
});
- const initialValues: EditionCsvAddAutoUserInput = {
+ const initialValues: IngestionEditionAddAutoUserInput = {
user_name: `[F] ${feedName}`,
confidence_level: 50,
};
- const onSubmit: FormikConfig['onSubmit'] = async (
+ const onSubmit: FormikConfig['onSubmit'] = async (
values,
{ setSubmitting, setFieldError },
) => {
- const existingUsers = await fetchQuery(ingestionCsvEditionUserHandlingQuery, {
+ const existingUsers = await fetchQuery(ingestionEditionUserHandlingQuery, {
name: values.user_name,
})
.toPromise();
- if ((existingUsers as IngestionCsvEditionUserHandlingQuery$data)?.userAlreadyExists) {
+ if ((existingUsers as IngestionEditionUserHandlingQuery$data)?.userAlreadyExists) {
setSubmitting(false);
setFieldError('user_name', t_i18n('This service account already exists. Change the feed\'s name to change the automatically created service account name'));
return;
}
- // send data to backend
commitUpdate({
variables: {
- id: ingestionCsvDataId,
+ id: dataId,
input: {
user_name: values.user_name,
- confidence_level: values.confidence_level,
+ confidence_level: Number(values.confidence_level),
},
},
onCompleted: () => {
@@ -120,9 +102,9 @@ const IngestionCsvEditionUserHandling: FunctionComponent
-
+
initialValues={initialValues}
- validationSchema={ingestionCsvCreationValidation}
+ validationSchema={validationSchema}
onSubmit={onSubmit}
>
{({ submitForm, resetForm }) => (
@@ -187,4 +169,4 @@ const IngestionCsvEditionUserHandling: FunctionComponent {
return {
@@ -512,11 +526,12 @@ const IngestionCsvEdition: FunctionComponent = ({
/>
{ingestionCsvData.user?.name === 'SYSTEM'
&& (
- setFieldValue('user_id', `[F] ${values.name}`)}
- ingestionCsvDataId={ingestionCsvData.id}
+ dataId={ingestionCsvData.id}
+ mutation={ingestionCsvEditionUserHandlingPatch}
/>
)
}
diff --git a/opencti-platform/opencti-front/src/private/components/data/ingestionTaxii/IngestionTaxiiCreation.jsx b/opencti-platform/opencti-front/src/private/components/data/ingestionTaxii/IngestionTaxiiCreation.jsx
index bd5a11b5bb38..0e4eb8466eaf 100644
--- a/opencti-platform/opencti-front/src/private/components/data/ingestionTaxii/IngestionTaxiiCreation.jsx
+++ b/opencti-platform/opencti-front/src/private/components/data/ingestionTaxii/IngestionTaxiiCreation.jsx
@@ -12,7 +12,6 @@ import Drawer from '../../common/drawer/Drawer';
import inject18n from '../../../../components/i18n';
import { commitMutation } from '../../../../relay/environment';
import TextField from '../../../../components/TextField';
-import CreatorField from '../../common/form/CreatorField';
import { fieldSpacingContainerStyle } from '../../../../utils/field';
import { insertNode } from '../../../../utils/store';
import SelectField from '../../../../components/fields/SelectField';
@@ -20,6 +19,7 @@ import DateTimePickerField from '../../../../components/DateTimePickerField';
import SwitchField from '../../../../components/fields/SwitchField';
import PasswordTextField from '../../../../components/PasswordTextField';
import CreateEntityControlledDial from '../../../../components/CreateEntityControlledDial';
+import IngestionCreationUserHandling from '@components/data/IngestionCreationUserHandling';
const styles = (theme) => ({
buttons: {
@@ -82,6 +82,8 @@ const IngestionTaxiiCreation = (props) => {
authentication_value: authentifcationValueResolved,
added_after_start: values.added_after_start,
user_id: values.user_id?.value,
+ automatic_user: values.automatic_user ?? true,
+ ...((values.automatic_user !== false) && { confidence_level: Number(values.confidence_level) }),
confidence_to_score: values.confidence_to_score,
};
commitMutation({
@@ -122,6 +124,7 @@ const IngestionTaxiiCreation = (props) => {
authentication_type: 'none',
authentication_value: '',
user_id: '',
+ automatic_user: true,
username: '',
password: '',
cert: '',
@@ -245,11 +248,9 @@ const IngestionTaxiiCreation = (props) => {
/>
>
)}
-
{
return {
...{
@@ -46,6 +61,7 @@ export const initIngestionValue = (ingestionTaxiiData: IngestionTaxiiEditionFrag
user_id: convertUser(ingestionTaxiiData, 'user'),
added_after_start: ingestionTaxiiData.added_after_start,
confidence_to_score: ingestionTaxiiData.confidence_to_score,
+ automatic_user: true,
},
...(ingestionTaxiiData.authentication_type === BEARER_AUTH
? {
@@ -401,11 +417,22 @@ const IngestionTaxiiEdition: FunctionComponent = ({
)}
+ {ingestionTaxiiData.user?.name === 'SYSTEM'
+ && (
+ setFieldValue('user_id', `[F] ${values.name}`)}
+ dataId={ingestionTaxiiData.id}
+ mutation={ingestionTaxiiEditionUserHandlingPatch}
+ />
+ )
+ }
;
authentication_type: IngestionAuthType;
authentication_value?: InputMaybe;
+ automatic_user?: InputMaybe;
collection: Scalars['String']['input'];
+ confidence_level?: InputMaybe;
confidence_to_score?: InputMaybe;
description?: InputMaybe;
ingestion_running?: InputMaybe;
name: Scalars['String']['input'];
uri: Scalars['String']['input'];
- user_id?: InputMaybe;
+ user_id: Scalars['String']['input'];
version: TaxiiVersion;
};
@@ -15162,6 +15169,7 @@ export type Mutation = {
ingestionRssDelete?: Maybe;
ingestionRssFieldPatch?: Maybe;
ingestionTaxiiAdd?: Maybe;
+ ingestionTaxiiAddAutoUser?: Maybe;
ingestionTaxiiCollectionAdd?: Maybe;
ingestionTaxiiCollectionDelete?: Maybe;
ingestionTaxiiCollectionFieldPatch?: Maybe;
@@ -16452,6 +16460,12 @@ export type MutationIngestionTaxiiAddArgs = {
};
+export type MutationIngestionTaxiiAddAutoUserArgs = {
+ id: Scalars['ID']['input'];
+ input: IngestionTaxiiAddAutoUserInput;
+};
+
+
export type MutationIngestionTaxiiCollectionAddArgs = {
input: IngestionTaxiiCollectionAddInput;
};
@@ -36351,6 +36365,7 @@ export type ResolversTypes = ResolversObject<{
IngestionRssEdge: ResolverTypeWrapper & { node: ResolversTypes['IngestionRss'] }>;
IngestionRssOrdering: IngestionRssOrdering;
IngestionTaxii: ResolverTypeWrapper;
+ IngestionTaxiiAddAutoUserInput: IngestionTaxiiAddAutoUserInput;
IngestionTaxiiAddInput: IngestionTaxiiAddInput;
IngestionTaxiiCollection: ResolverTypeWrapper;
IngestionTaxiiCollectionAddInput: IngestionTaxiiCollectionAddInput;
@@ -37316,6 +37331,7 @@ export type ResolversParentTypes = ResolversObject<{
IngestionRssConnection: Omit & { edges: Array };
IngestionRssEdge: Omit & { node: ResolversParentTypes['IngestionRss'] };
IngestionTaxii: BasicStoreEntityIngestionTaxii;
+ IngestionTaxiiAddAutoUserInput: IngestionTaxiiAddAutoUserInput;
IngestionTaxiiAddInput: IngestionTaxiiAddInput;
IngestionTaxiiCollection: BasicStoreEntityIngestionTaxiiCollection;
IngestionTaxiiCollectionAddInput: IngestionTaxiiCollectionAddInput;
@@ -43155,6 +43171,7 @@ export type MutationResolvers, ParentType, ContextType, RequireFields>;
ingestionRssFieldPatch?: Resolver, ParentType, ContextType, RequireFields>;
ingestionTaxiiAdd?: Resolver, ParentType, ContextType, RequireFields>;
+ ingestionTaxiiAddAutoUser?: Resolver, ParentType, ContextType, RequireFields>;
ingestionTaxiiCollectionAdd?: Resolver, ParentType, ContextType, RequireFields>;
ingestionTaxiiCollectionDelete?: Resolver, ParentType, ContextType, RequireFields>;
ingestionTaxiiCollectionFieldPatch?: Resolver, ParentType, ContextType, RequireFields>;
diff --git a/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-domain.ts b/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-domain.ts
index c1892f891ff2..fc309f0071e2 100644
--- a/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-domain.ts
+++ b/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-domain.ts
@@ -6,9 +6,10 @@ import { publishUserAction } from '../../listener/UserActionListener';
import { notify } from '../../database/redis';
import { ABSTRACT_INTERNAL_OBJECT } from '../../schema/general';
import type { AuthContext, AuthUser } from '../../types/user';
-import { type EditInput, type IngestionTaxiiAddInput } from '../../generated/graphql';
+import { type EditInput, type IngestionTaxiiAddAutoUserInput, type IngestionTaxiiAddInput } from '../../generated/graphql';
import { addAuthenticationCredentials, removeAuthenticationCredentials, verifyIngestionAuthenticationContent } from './ingestion-common';
import { registerConnectorForIngestion, unregisterConnectorForIngestion } from '../../domain/connector';
+import { createOnTheFlyUser } from '../user/user-domain';
export const findById = async (context: AuthContext, user: AuthUser, ingestionId: string, removeCredentials = false) => {
const taxiiIngestion = await storeLoadById(context, user, ingestionId, ENTITY_TYPE_INGESTION_TAXII);
@@ -27,10 +28,20 @@ export const findAllTaxiiIngestion = async (context: AuthContext, user: AuthUser
};
export const addIngestion = async (context: AuthContext, user: AuthUser, input: IngestionTaxiiAddInput) => {
+ if (input.automatic_user) {
+ const onTheFlyCreatedUser = await createOnTheFlyUser(
+ context,
+ user,
+ { userName: input.user_id, serviceAccount: true, confidenceLevel: input.confidence_level },
+ );
+ input = { ...input, user_id: onTheFlyCreatedUser.id };
+ }
if (input.authentication_value) {
verifyIngestionAuthenticationContent(input.authentication_type, input.authentication_value);
}
- const { element, isCreation } = await createEntity(context, user, input, ENTITY_TYPE_INGESTION_TAXII, { complete: true });
+
+ const { automatic_user: _automatic_user, confidence_level: _confidence_level, ...taxiiFeedToCreate } = input;
+ const { element, isCreation } = await createEntity(context, user, taxiiFeedToCreate, ENTITY_TYPE_INGESTION_TAXII, { complete: true });
if (isCreation) {
await registerConnectorForIngestion(context, {
id: element.id,
@@ -164,3 +175,10 @@ export const ingestionTaxiiResetState = async (context: AuthContext, user: AuthU
});
return notify(BUS_TOPICS[ABSTRACT_INTERNAL_OBJECT].EDIT_TOPIC, ingestionUpdated, user);
};
+
+export const ingestionTaxiiAddAutoUser = async (context: AuthContext, user: AuthUser, ingestionId: string, input: IngestionTaxiiAddAutoUserInput) => {
+ const onTheFlyCreatedUser = await createOnTheFlyUser(context, user,
+ { userName: input.user_name, confidenceLevel: input.confidence_level, serviceAccount: true });
+
+ return ingestionEditField(context, user, ingestionId, [{ key: 'user_id', value: [onTheFlyCreatedUser.id] }]);
+};
diff --git a/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-resolver.ts b/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-resolver.ts
index 33c374b8fdb5..1fb7c46ed913 100644
--- a/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-resolver.ts
+++ b/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii-resolver.ts
@@ -1,4 +1,12 @@
-import { addIngestion, findTaxiiIngestionPaginated, findById, ingestionDelete, ingestionEditField, ingestionTaxiiResetState } from './ingestion-taxii-domain';
+import {
+ addIngestion,
+ findTaxiiIngestionPaginated,
+ findById,
+ ingestionDelete,
+ ingestionEditField,
+ ingestionTaxiiResetState,
+ ingestionTaxiiAddAutoUser,
+} from './ingestion-taxii-domain';
import type { Resolvers } from '../../generated/graphql';
const ingestionTaxiiResolvers: Resolvers = {
@@ -22,6 +30,9 @@ const ingestionTaxiiResolvers: Resolvers = {
ingestionTaxiiFieldPatch: (_, { id, input }, context) => {
return ingestionEditField(context, context.user, id, input);
},
+ ingestionTaxiiAddAutoUser: (_, { id, input }, context) => {
+ return ingestionTaxiiAddAutoUser(context, context.user, id, input);
+ },
},
};
diff --git a/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii.graphql b/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii.graphql
index 5a635f83ebdc..32bb97e89789 100644
--- a/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii.graphql
+++ b/opencti-platform/opencti-graphql/src/modules/ingestion/ingestion-taxii.graphql
@@ -78,7 +78,14 @@ input IngestionTaxiiAddInput {
added_after_start: DateTime
ingestion_running: Boolean
confidence_to_score: Boolean
- user_id: String
+ user_id: String!
+ automatic_user: Boolean
+ confidence_level: Int
+}
+
+input IngestionTaxiiAddAutoUserInput {
+ user_name: String!
+ confidence_level: Int!
}
type Mutation {
@@ -86,4 +93,5 @@ type Mutation {
ingestionTaxiiDelete(id: ID!): ID @auth(for: [INGESTION_SETINGESTIONS])
ingestionTaxiiResetState(id: ID!): IngestionTaxii @auth(for: [INGESTION_SETINGESTIONS])
ingestionTaxiiFieldPatch(id: ID!, input: [EditInput!]!): IngestionTaxii @auth(for: [INGESTION_SETINGESTIONS])
+ ingestionTaxiiAddAutoUser(id: ID!, input: IngestionTaxiiAddAutoUserInput!): IngestionTaxii @auth(for: [INGESTION_SETINGESTIONS])
}
diff --git a/opencti-platform/opencti-graphql/tests/03-integration/02-resolvers/ingestion-taxii-test.ts b/opencti-platform/opencti-graphql/tests/03-integration/02-resolvers/ingestion-taxii-test.ts
index 8045e40c4c89..9f92fbe03d63 100644
--- a/opencti-platform/opencti-graphql/tests/03-integration/02-resolvers/ingestion-taxii-test.ts
+++ b/opencti-platform/opencti-graphql/tests/03-integration/02-resolvers/ingestion-taxii-test.ts
@@ -3,13 +3,36 @@ import gql from 'graphql-tag';
import type { GraphQLFormattedError } from 'graphql/error';
import { queryAsAdminWithSuccess } from '../../utils/testQueryHelper';
import { IngestionAuthType, TaxiiVersion } from '../../../src/generated/graphql';
-import { ADMIN_USER, queryAsAdmin, testContext } from '../../utils/testQuery';
+import { ADMIN_USER, adminQuery, queryAsAdmin, testContext } from '../../utils/testQuery';
import { now } from '../../../src/utils/format';
import { findById as findIngestionById, patchTaxiiIngestion } from '../../../src/modules/ingestion/ingestion-taxii-domain';
+import { findById as findUserById } from '../../../src/domain/user';
+
+const DELETE_USER_QUERY = gql`
+ mutation userDelete($id: ID!) {
+ userEdit(id: $id) {
+ delete
+ }
+ }
+`;
+
+const READ_USER_QUERY = gql`
+ query user($id: String!) {
+ user(id: $id) {
+ id
+ name
+ description
+ user_confidence_level {
+ max_confidence
+ }
+ }
+ }
+`;
describe('TAXII ingestion resolver standard behavior', () => {
- let createdTaxiiIngesterId: string;
- it('should create a TAXII ingester', async () => {
+ let createdTaxiiIngesterId: string = '';
+
+ it('should create a TAXII ingester with existing user', async () => {
const INGESTER_TO_CREATE = {
input: {
authentication_type: IngestionAuthType.Basic,
@@ -17,8 +40,9 @@ describe('TAXII ingestion resolver standard behavior', () => {
name: 'Taxii ingester for integration test',
version: TaxiiVersion.V21,
collection: 'TaxiCollection',
- uri: 'http://taxiserver.invalid'
- }
+ uri: 'http://taxiserver.invalid',
+ user_id: ADMIN_USER.id,
+ },
};
const ingesterQueryResult = await queryAsAdminWithSuccess({
query: gql`
@@ -30,12 +54,55 @@ describe('TAXII ingestion resolver standard behavior', () => {
}
},
`,
- variables: INGESTER_TO_CREATE
+ variables: INGESTER_TO_CREATE,
});
expect(ingesterQueryResult.data?.ingestionTaxiiAdd.id).toBeDefined();
createdTaxiiIngesterId = ingesterQueryResult.data?.ingestionTaxiiAdd.id;
});
+ it('should create a TAXII feed with automatic user', async () => {
+ const INGESTER_TO_CREATE = {
+ input: {
+ authentication_type: IngestionAuthType.Basic,
+ authentication_value: 'username:P@ssw0rd!',
+ name: 'Taxii ingester for integration test',
+ version: TaxiiVersion.V21,
+ collection: 'TaxiCollection',
+ uri: 'http://taxiserver.invalid',
+ automatic_user: true,
+ user_id: '[F] Taxii ingester for integration test',
+ },
+ };
+ const ingesterQueryResult = await queryAsAdminWithSuccess({
+ query: gql`
+ mutation createTaxiiIngester($input: IngestionTaxiiAddInput!) {
+ ingestionTaxiiAdd(input: $input) {
+ id
+ entity_type
+ ingestion_running
+ user_id
+ }
+ },
+ `,
+ variables: INGESTER_TO_CREATE,
+ });
+ expect(ingesterQueryResult.data?.ingestionTaxiiAdd.id).toBeDefined();
+ const createdTaxiiIngester = ingesterQueryResult.data?.ingestionTaxiiAdd;
+
+ const userIdCreated = createdTaxiiIngester.user_id;
+ const createdUser = await findUserById(testContext, ADMIN_USER, userIdCreated);
+ expect(createdUser.name).toBe('[F] Taxii ingester for integration test');
+ // Delete just created user
+ await adminQuery({
+ query: DELETE_USER_QUERY,
+ variables: { id: createdUser.id },
+ });
+ // Verify no longer found
+ const queryResult = await adminQuery({ query: READ_USER_QUERY, variables: { id: createdUser.id } });
+ expect(queryResult).not.toBeNull();
+ expect(queryResult.data.user).toBeNull();
+ });
+
it('should edit a TAXII ingester', async () => {
const ingesterQueryResult = await queryAsAdminWithSuccess({
query: gql`
@@ -47,13 +114,48 @@ describe('TAXII ingestion resolver standard behavior', () => {
}
}
`,
- variables: { id: createdTaxiiIngesterId, input: [{ key: 'authentication_value', value: ['username:P@ssw0rd!'] }] }
+ variables: { id: createdTaxiiIngesterId, input: [{ key: 'authentication_value', value: ['username:P@ssw0rd!'] }] },
});
expect(ingesterQueryResult.data?.ingestionTaxiiFieldPatch.id).toBeDefined();
expect(ingesterQueryResult.data?.ingestionTaxiiFieldPatch.authentication_type).toEqual(IngestionAuthType.Basic);
expect(ingesterQueryResult.data?.ingestionTaxiiFieldPatch.authentication_value).toEqual('username:undefined');
});
+
+ it('should add auto user and update Taxii feed ingester with it', async () => {
+ const TAXII_FEED_AUTO_USER_UPDATE = {
+ id: createdTaxiiIngesterId,
+ input: {
+ user_name: 'AutoUser',
+ confidence_level: 86,
+ },
+ };
+ const updateTaxiiFeedWithAutoUserResult = await queryAsAdminWithSuccess({
+ query: gql`
+ mutation updateTaxiiFeedWithAutoUser($id: ID!, $input: IngestionTaxiiAddAutoUserInput!) {
+ ingestionTaxiiAddAutoUser(id: $id, input: $input){
+ id
+ user {
+ id
+ name
+ }
+ }
+ }
+ `,
+ variables: TAXII_FEED_AUTO_USER_UPDATE,
+ });
+ expect(updateTaxiiFeedWithAutoUserResult?.data?.ingestionTaxiiAddAutoUser?.user?.name).toBe('AutoUser');
+ // Delete just created user
+ await adminQuery({
+ query: DELETE_USER_QUERY,
+ variables: { id: updateTaxiiFeedWithAutoUserResult?.data?.ingestionTaxiiAddAutoUser?.user?.id },
+ });
+ // Verify no longer found
+ const queryResult = await adminQuery({ query: READ_USER_QUERY, variables: { id: updateTaxiiFeedWithAutoUserResult?.data?.ingestionTaxiiAddAutoUser?.user?.id } });
+ expect(queryResult).not.toBeNull();
+ expect(queryResult.data.user).toBeNull();
+ });
+
it('should reset cursor when a user change the start date', async () => {
// shortcut to set a cursor that is defined
const state = { current_state_cursor: 'aaaaaaaaaaaaaaaaaaa', last_execution_date: now() };
@@ -70,7 +172,7 @@ describe('TAXII ingestion resolver standard behavior', () => {
}
}
`,
- variables: { id: createdTaxiiIngesterId, input: [{ key: 'added_after_start', value: [now()] }] }
+ variables: { id: createdTaxiiIngesterId, input: [{ key: 'added_after_start', value: [now()] }] },
});
expect(ingesterChangeDateResult.data?.ingestionTaxiiFieldPatch.id).toBeDefined();
@@ -90,11 +192,11 @@ describe('TAXII ingestion resolver standard behavior', () => {
}
}
`,
- variables: { id: createdTaxiiIngesterId, input: { key: 'authentication_value', value: ['user:name:P@ssw0rd!'] } }
+ variables: { id: createdTaxiiIngesterId, input: { key: 'authentication_value', value: ['user:name:P@ssw0rd!'] } },
});
expect(ingesterQueryResult.errors).toBeDefined();
if (ingesterQueryResult.errors) { // above expect is not taken by eslint
- const error:GraphQLFormattedError = ingesterQueryResult.errors[0];
+ const error: GraphQLFormattedError = ingesterQueryResult.errors[0];
expect(error.message).toContain('Username and password cannot have : character.');
}
});
@@ -117,7 +219,7 @@ describe('TAXII ingestion resolver standard behavior', () => {
}
}
`,
- variables: { id: createdTaxiiIngesterId }
+ variables: { id: createdTaxiiIngesterId },
});
expect(ingesterQueryResult.data?.ingestionTaxiiResetState.id).toBeDefined();
expect(ingesterQueryResult.data?.ingestionTaxiiResetState.current_state_cursor).toBeNull();
@@ -130,7 +232,7 @@ describe('TAXII ingestion resolver standard behavior', () => {
ingestionTaxiiDelete(id: $id)
}
`,
- variables: { id: createdTaxiiIngesterId }
+ variables: { id: createdTaxiiIngesterId },
});
expect(ingesterQueryResult.data?.ingestionTaxiiDelete).toEqual(createdTaxiiIngesterId);
});
diff --git a/opencti-platform/opencti-graphql/tests/03-integration/04-manager/ingestionManager-test.ts b/opencti-platform/opencti-graphql/tests/03-integration/04-manager/ingestionManager-test.ts
index 1b85399f2bd9..380713846e1a 100644
--- a/opencti-platform/opencti-graphql/tests/03-integration/04-manager/ingestionManager-test.ts
+++ b/opencti-platform/opencti-graphql/tests/03-integration/04-manager/ingestionManager-test.ts
@@ -17,13 +17,14 @@ import { connectorIdFromIngestId, queueDetails } from '../../../src/domain/conne
describe('Verify taxii ingestion', () => {
it('should Taxii server response with no pagination (no next, no more, no x-taxii-date-added-last)', async () => {
// 1. Create ingestion in opencti
- const input : IngestionTaxiiAddInput = {
+ const input: IngestionTaxiiAddInput = {
authentication_type: IngestionAuthType.None,
collection: 'testcollection',
ingestion_running: true,
name: 'taxii ingestion with no pagination',
uri: 'http://test.invalid',
version: TaxiiVersion.V21,
+ user_id: ADMIN_USER.id,
};
const ingestionNotPagination = await addTaxiiIngestion(testContext, ADMIN_USER, input);
expect(ingestionNotPagination.id).toBeDefined();
@@ -45,9 +46,9 @@ describe('Verify taxii ingestion', () => {
revoked: false,
spec_version: '2.1',
type: 'report' } as unknown as StixReport],
- more: undefined
+ more: undefined,
},
- addedLastHeader: undefined
+ addedLastHeader: undefined,
};
await processTaxiiResponse(testContext, ingestionNotPagination, taxiResponse);
@@ -61,14 +62,15 @@ describe('Verify taxii ingestion', () => {
it('should taxii server response with data and next page and start date', async () => {
// 1. Create ingestion in opencti
- const input2 : IngestionTaxiiAddInput = {
+ const input2: IngestionTaxiiAddInput = {
authentication_type: IngestionAuthType.None,
collection: 'testcollection',
ingestion_running: true,
name: 'taxii ingestion with pagination and start date',
uri: 'http://test.invalid',
version: TaxiiVersion.V21,
- added_after_start: '2024-01-01T20:35:44.000Z'
+ added_after_start: '2024-01-01T20:35:44.000Z',
+ user_id: ADMIN_USER.id,
};
const ingestionPaginatedWithStartDate = await addTaxiiIngestion(testContext, ADMIN_USER, input2);
expect(ingestionPaginatedWithStartDate.id).toBeDefined();
@@ -91,9 +93,9 @@ describe('Verify taxii ingestion', () => {
revoked: false,
spec_version: '2.1',
type: 'report' } as unknown as StixReport],
- more: true
+ more: true,
},
- addedLastHeader: '2024-02-01T20:35:44.000Z'
+ addedLastHeader: '2024-02-01T20:35:44.000Z',
};
await processTaxiiResponse(testContext, ingestionPaginatedWithStartDate, taxiResponse1);
@@ -118,9 +120,9 @@ describe('Verify taxii ingestion', () => {
revoked: false,
spec_version: '2.1',
type: 'report' } as unknown as StixReport],
- more: false
+ more: false,
},
- addedLastHeader: '2024-03-01T20:35:44.000Z'
+ addedLastHeader: '2024-03-01T20:35:44.000Z',
};
await processTaxiiResponse(testContext, taxiiEntityAfterfirstRequest, taxiResponse);
@@ -134,13 +136,14 @@ describe('Verify taxii ingestion', () => {
it('should taxii server response with no start date, and next page', async () => {
// 1. Create ingestion in opencti
- const input3 : IngestionTaxiiAddInput = {
+ const input3: IngestionTaxiiAddInput = {
authentication_type: IngestionAuthType.None,
collection: 'testcollection',
ingestion_running: true,
name: 'taxii ingestion with pagination no start date',
uri: 'http://test.invalid',
version: TaxiiVersion.V21,
+ user_id: ADMIN_USER.id,
};
const ingestionPaginatedWithNoStartDate = await addTaxiiIngestion(testContext, ADMIN_USER, input3);
expect(ingestionPaginatedWithNoStartDate.id).toBeDefined();
@@ -163,9 +166,9 @@ describe('Verify taxii ingestion', () => {
revoked: false,
spec_version: '2.1',
type: 'report' } as unknown as StixReport],
- more: true
+ more: true,
},
- addedLastHeader: '2024-02-01T20:35:44.000Z'
+ addedLastHeader: '2024-02-01T20:35:44.000Z',
};
await processTaxiiResponse(testContext, ingestionPaginatedWithNoStartDate, taxiResponse);
@@ -190,9 +193,9 @@ describe('Verify taxii ingestion', () => {
revoked: false,
spec_version: '2.1',
type: 'report' } as unknown as StixReport],
- more: false
+ more: false,
},
- addedLastHeader: '2024-03-01T20:44:44.000Z'
+ addedLastHeader: '2024-03-01T20:44:44.000Z',
};
await processTaxiiResponse(testContext, taxiiEntityAfterFirstCall, taxiResponse2);
@@ -206,14 +209,15 @@ describe('Verify taxii ingestion', () => {
it('should store nothing when no data', async () => {
// 1. Create ingestion in opencti
- const input2 : IngestionTaxiiAddInput = {
+ const input2: IngestionTaxiiAddInput = {
authentication_type: IngestionAuthType.None,
collection: 'testcollection',
ingestion_running: true,
name: 'taxii ingestion with pagination and start date',
uri: 'http://test.invalid',
version: TaxiiVersion.V21,
- added_after_start: '2023-01-01T20:35:44.000Z'
+ added_after_start: '2023-01-01T20:35:44.000Z',
+ user_id: ADMIN_USER.id,
};
const ingestionPaginatedWithStartDate = await addTaxiiIngestion(testContext, ADMIN_USER, input2);
expect(ingestionPaginatedWithStartDate.id).toBeDefined();
@@ -223,9 +227,9 @@ describe('Verify taxii ingestion', () => {
data: {
next: undefined,
objects: [],
- more: false
+ more: false,
},
- addedLastHeader: '2021-11-11T11:11:11.111Z'
+ addedLastHeader: '2021-11-11T11:11:11.111Z',
};
await processTaxiiResponse(testContext, ingestionPaginatedWithStartDate, taxiResponse);
@@ -241,13 +245,14 @@ describe('Verify taxii ingestion', () => {
describe('Verify taxii ingestion - patch part', () => {
it('should Taxii server response next as number be transform', async () => {
// 1. Create ingestion in opencti
- const input : IngestionTaxiiAddInput = {
+ const input: IngestionTaxiiAddInput = {
authentication_type: IngestionAuthType.None,
collection: 'testcollection',
ingestion_running: true,
name: 'taxii ingestion for patch test',
uri: 'http://test.invalid',
version: TaxiiVersion.V21,
+ user_id: ADMIN_USER.id,
};
const ingestion = await addTaxiiIngestion(testContext, ADMIN_USER, input);
expect(ingestion.id).toBeDefined();
@@ -271,22 +276,22 @@ describe('Verify csv ingestion', () => {
it('should prepare ingestion data', async () => {
const mapper = csvMapperMockCities as CsvMapperParsed;
- const csvMapperInput : CsvMapperAddInput = {
+ const csvMapperInput: CsvMapperAddInput = {
has_header: mapper.has_header,
name: 'testCsvIngestionMapper',
representations: JSON.stringify(mapper.representations),
separator: mapper.separator,
- skipLineChar: mapper.skipLineChar
+ skipLineChar: mapper.skipLineChar,
};
const mapperCreated = await createCsvMapper(testContext, ADMIN_USER, csvMapperInput);
- const ingestionCsvInput : IngestionCsvAddInput = {
+ const ingestionCsvInput: IngestionCsvAddInput = {
authentication_type: IngestionAuthType.None,
ingestion_running: true,
name: 'csv ingestion',
uri: 'http://test.invalid',
csv_mapper_id: mapperCreated.id,
- user_id: ADMIN_USER.id
+ user_id: ADMIN_USER.id,
};
ingestionCsv = await addIngestionCsv(testContext, ADMIN_USER, ingestionCsvInput);
expect(ingestionCsv.id).toBeDefined();
@@ -300,7 +305,6 @@ describe('Verify csv ingestion', () => {
return false;
}
}, 10000, 6); // Wait for the queue result to exist - max 1 minute
-
csvMapperParsed = parseCsvMapper(mapperCreated);
csvLines = await readCsvFromFileStream('./tests/03-integration/04-manager/ingestionManager', 'csv-file-cities.csv');
From fbe717424ba3aec2c830f8ba4a36348de089bee0 Mon Sep 17 00:00:00 2001
From: Julien Richard
Date: Fri, 2 Jan 2026 15:01:10 +0100
Subject: [PATCH 019/126] [docs] Document prometheus exposed metrics (#13725)
---
docs/docs/deployment/configuration.md | 2 +
docs/docs/deployment/telemetry.md | 66 +++++++++++++++++++++++++++
docs/mkdocs.yml | 1 +
3 files changed, 69 insertions(+)
create mode 100644 docs/docs/deployment/telemetry.md
diff --git a/docs/docs/deployment/configuration.md b/docs/docs/deployment/configuration.md
index 7478a8990885..103427c34185 100644
--- a/docs/docs/deployment/configuration.md
+++ b/docs/docs/deployment/configuration.md
@@ -100,6 +100,8 @@ Here are the configuration keys, for both containers (environment variables) and
| app:telemetry:metrics:exporter_otlp | APP__TELEMETRY__METRICS__EXPORTER_OTLP | | Port to expose the OTLP endpoint |
| app:telemetry:metrics:exporter_prometheus | APP__TELEMETRY__METRICS__EXPORTER_PROMETHEUS | 14269 | Port to expose the Prometheus endpoint |
+For a detailed list of exposed metrics, please refer to the [Telemetry](../deployment/telemetry.md) page.
+
#### Maps & references
diff --git a/docs/docs/deployment/telemetry.md b/docs/docs/deployment/telemetry.md
new file mode 100644
index 000000000000..bd44f260b499
--- /dev/null
+++ b/docs/docs/deployment/telemetry.md
@@ -0,0 +1,66 @@
+# Telemetry
+
+OpenCTI exposes metrics using the OpenTelemetry standard, which can be exported to various systems such as Prometheus or OTLP collectors. These metrics provide insights into the platform's performance, usage, and health.
+
+## Configuration
+
+To enable metrics, you need to configure the telemetry section in your platform configuration. See [Configuration](configuration.md#telemetry) for details on how to enable and configure exporters.
+
+## Available Metrics
+
+The following metrics are exposed by the OpenCTI API.
+
+| Metric Name | Type | Description | Unit |
+| :--- | :--- | :--- | :--- |
+| `opencti_sent_email` | Counter | Counts the total number of emails sent by the platform. | Count |
+| `opencti_api_requests` | Counter | Counts the total number of API requests received. | Count |
+| `opencti_api_errors` | Counter | Counts the total number of API errors encountered. | Count |
+| `opencti_api_latency` | Histogram | Measures the latency of API query execution. | Milliseconds |
+| `opencti_api_direct_bulk` | Gauge | Measures the size of bulks for direct ingestion (fast path). | Count |
+| `opencti_api_side_bulk` | Gauge | Measures the size of bulks for absorption impacts (worker path). | Count |
+
+## Metric Attributes
+
+Metrics exported by OpenCTI include various attributes (labels) to provide granular context.
+
+### API Metrics Attributes
+Applies to: `opencti_api_requests`, `opencti_api_errors`, `opencti_api_latency`
+
+| Attribute | Description | Example |
+|:---|:---|:---|
+| `operation` | The GraphQL operation type. | `query`, `mutation`, `subscription` |
+| `name` | The name of the GraphQL operation. | `StixCoreObjectFind`, `Unspecified` |
+| `status` | The outcome of the request. | `SUCCESS`, `ERROR` |
+| `type` | The error type (only present if status is ERROR). | `AUTH_REQUIRED`, `FORBIDDEN_ACCESS` |
+| `user_agent` | The client user agent initiating the request. | `Mozilla/5.0...`, `OpenCTI-Client` |
+
+### Email Metrics Attributes
+Applies to: `opencti_sent_email`
+
+| Attribute | Description | Example |
+|:---|:---|:---|
+| `category` | The functional category of the email. | `hub-registration`, `dissemination`, `password-reset`, `notification` |
+| `identifier` | The ID of the related entity (e.g., user, trigger, list). | `uuid-v4-string` |
+
+### Bulk Metrics Attributes
+Applies to: `opencti_api_direct_bulk`, `opencti_api_side_bulk`
+
+| Attribute | Description | Example |
+|:---|:---|:---|
+| `type` | The context or source of the indexing operation. | `import`, `connector` |
+
+## Node.js Runtime Metrics
+
+In addition to the application-specific metrics above, OpenCTI also exposes standard Node.js runtime metrics provided by `opentelemetry-node-metrics`. These include metrics for:
+
+- **Process**: CPU usage, memory usage, uptime, etc.
+- **Event Loop**: Lag, active handles, etc.
+- **GC**: Garbage collection duration and counts.
+- **Memory**: Heap usage, heap limits, etc.
+
+Common examples include:
+- `process_cpu_user_seconds_total`
+- `process_cpu_system_seconds_total`
+- `process_resident_memory_bytes`
+- `nodejs_eventloop_lag_seconds`
+- `nodejs_gc_duration_seconds`
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index 8582b76b23ff..f1ceadc11788 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -116,6 +116,7 @@ nav:
- Installation: deployment/installation.md
- Configuration: deployment/configuration.md
- Authentication: deployment/authentication.md
+ - Telemetry: deployment/telemetry.md
- Upgrade: deployment/upgrade.md
- Ecosystem:
- Connectors: deployment/connectors.md
From a519ddcf28ee5749aa267cd7d20a70cdb013b9cc Mon Sep 17 00:00:00 2001
From: Archidoit <75783086+Archidoit@users.noreply.github.com>
Date: Sun, 4 Jan 2026 21:23:58 +0100
Subject: [PATCH 020/126] [backend] Check available playbooks for an entity
according to filters (#13856)
Co-authored-by: Samuel Hassine
---
.../StixCoreObjectEnrollPlaybookLines.jsx | 2 ++
.../src/manager/playbookManager/playbookManager.ts | 10 ++++++----
.../src/modules/playbook/playbook-domain.ts | 10 ++--------
3 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/opencti-platform/opencti-front/src/private/components/common/stix_core_objects/StixCoreObjectEnrollPlaybookLines.jsx b/opencti-platform/opencti-front/src/private/components/common/stix_core_objects/StixCoreObjectEnrollPlaybookLines.jsx
index fa918e3503d1..4bbd8fa9216e 100644
--- a/opencti-platform/opencti-front/src/private/components/common/stix_core_objects/StixCoreObjectEnrollPlaybookLines.jsx
+++ b/opencti-platform/opencti-front/src/private/components/common/stix_core_objects/StixCoreObjectEnrollPlaybookLines.jsx
@@ -34,6 +34,8 @@ const styles = (theme) => ({
noResult: {
color: theme.palette.text.primary,
fontSize: 15,
+ textAlign: 'center',
+ marginTop: 20,
},
itemIcon: {
color: theme.palette.primary.main,
diff --git a/opencti-platform/opencti-graphql/src/manager/playbookManager/playbookManager.ts b/opencti-platform/opencti-graphql/src/manager/playbookManager/playbookManager.ts
index 9c120a902971..e6ec57939c5d 100644
--- a/opencti-platform/opencti-graphql/src/manager/playbookManager/playbookManager.ts
+++ b/opencti-platform/opencti-graphql/src/manager/playbookManager/playbookManager.ts
@@ -26,7 +26,7 @@ import { AUTOMATION_MANAGER_USER, executionContext, RETENTION_MANAGER_USER, SYST
import type { SseEvent, StreamDataEvent } from '../../types/event';
import type { StixBundle, StixObject } from '../../types/stix-2-1-common';
import { streamEventId, utcDate } from '../../utils/format';
-import { findById } from '../../modules/playbook/playbook-domain';
+import { findById, findPlaybooksForEntity } from '../../modules/playbook/playbook-domain';
import { type CronConfiguration, PLAYBOOK_INTERNAL_DATA_CRON, type StreamConfiguration } from '../../modules/playbook/playbook-components';
import { PLAYBOOK_COMPONENTS } from '../../modules/playbook/playbook-components';
import type { BasicStoreEntityPlaybook, ComponentDefinition } from '../../modules/playbook/playbook-types';
@@ -132,15 +132,17 @@ const playbookStreamHandler = async (streamEvents: Array {
- const playbooks = await getEntitiesListFromCache(context, SYSTEM_USER, ENTITY_TYPE_PLAYBOOK);
+ // fetch playbooks allowed for this entity
+ const playbooks = await findPlaybooksForEntity(context, RETENTION_MANAGER_USER, entityId);
let playbook = null;
+ // keep the playbook corresponding to the id
const filteredPlaybooks = playbooks.filter((n) => n.id === id);
if (filteredPlaybooks.length > 0) {
playbook = filteredPlaybooks.at(0);
} else {
- throw FunctionalError('Playbook does not exist', { id });
+ throw FunctionalError('Playbook does not exist for this entity', { id });
}
- // Execute only of definition is available
+ // Execute only if definition is available
if (playbook && playbook.playbook_definition) {
const def = JSON.parse(playbook.playbook_definition) as ComponentDefinition;
const instance = def.nodes.find((n) => n.id === playbook.playbook_start);
diff --git a/opencti-platform/opencti-graphql/src/modules/playbook/playbook-domain.ts b/opencti-platform/opencti-graphql/src/modules/playbook/playbook-domain.ts
index 5f915595d44a..e0c5bec19505 100644
--- a/opencti-platform/opencti-graphql/src/modules/playbook/playbook-domain.ts
+++ b/opencti-platform/opencti-graphql/src/modules/playbook/playbook-domain.ts
@@ -22,7 +22,7 @@ import { notify } from '../../database/redis';
import type { DomainFindById } from '../../domain/domainTypes';
import { ABSTRACT_INTERNAL_OBJECT } from '../../schema/general';
import type { AuthContext, AuthUser } from '../../types/user';
-import { type EditInput, FilterMode, type PlaybookAddInput, type PlaybookAddLinkInput, type PlaybookAddNodeInput, type PositionInput } from '../../generated/graphql';
+import { type EditInput, type PlaybookAddInput, type PlaybookAddLinkInput, type PlaybookAddNodeInput, type PositionInput } from '../../generated/graphql';
import type { BasicStoreEntityPlaybook, ComponentDefinition } from './playbook-types';
import { ENTITY_TYPE_PLAYBOOK } from './playbook-types';
import { PLAYBOOK_COMPONENTS, type SharingConfiguration, type StreamConfiguration } from './playbook-components';
@@ -32,7 +32,6 @@ import { isStixMatchFilterGroup } from '../../utils/filtering/filtering-stix/sti
import { registerConnectorQueues, unregisterConnector } from '../../database/rabbitmq';
import { getEntitiesListFromCache } from '../../database/cache';
import { SYSTEM_USER } from '../../utils/access';
-import { findFiltersFromKey } from '../../utils/filtering/filtering-utils';
import { checkEnterpriseEdition, isEnterpriseEdition } from '../../enterprise-edition/ee';
import pjson from '../../../package.json';
import { extractContentFrom } from '../../utils/fileToContent';
@@ -72,12 +71,7 @@ export const findPlaybooksForEntity = async (context: AuthContext, user: AuthUse
if (instance && (instance.component_id === 'PLAYBOOK_INTERNAL_DATA_STREAM' || instance.component_id === 'PLAYBOOK_INTERNAL_MANUAL_TRIGGER')) {
const { filters } = JSON.parse(instance.configuration ?? '{}') as StreamConfiguration;
const jsonFilters = filters ? JSON.parse(filters) : null;
- const newFilters = {
- mode: FilterMode.And,
- filters: findFiltersFromKey(jsonFilters?.filters ?? [], 'entity_type'),
- filterGroups: [],
- };
- const isMatch = await isStixMatchFilterGroup(context, SYSTEM_USER, stixEntity, newFilters);
+ const isMatch = await isStixMatchFilterGroup(context, SYSTEM_USER, stixEntity, jsonFilters);
if (isMatch) {
filteredPlaybooks.push(playbook);
}
From 6e958f69385d836cf77a0680efa41ca9e387897c Mon Sep 17 00:00:00 2001
From: Julien Richard
Date: Sun, 4 Jan 2026 21:25:32 +0100
Subject: [PATCH 021/126] [backend] Improve license management supporting
official OIDs and grace period (#13840)
---
.../src/modules/settings/licensing.js | 26 ++++++++++++-------
1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/opencti-platform/opencti-graphql/src/modules/settings/licensing.js b/opencti-platform/opencti-graphql/src/modules/settings/licensing.js
index 566d1061e48e..cabf64c753cb 100644
--- a/opencti-platform/opencti-graphql/src/modules/settings/licensing.js
+++ b/opencti-platform/opencti-graphql/src/modules/settings/licensing.js
@@ -26,12 +26,20 @@ export const IS_LTS_PLATFORM = PLATFORM_VERSION.includes('lts');
// https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers
// 62944 - Filigran
-export const LICENSE_OPTION_TYPE = '6.2.9.4.4.10';
-export const LICENSE_OPTION_PRODUCT = '6.2.9.4.4.20';
-export const LICENSE_OPTION_CREATOR = '6.2.9.4.4.30';
+export const LICENSE_OID_TYPE = '1.3.6.1.4.1.62944.10';
+export const LICENSE_OID_PRODUCT = '1.3.6.1.4.1.62944.20';
+export const LICENSE_OID_CREATOR = '1.3.6.1.4.1.62944.30';
+// Legacy OIDs
+export const LICENSE_LEGACY_TYPE = '6.2.9.4.4.10';
+export const LICENSE_LEGACY_PRODUCT = '6.2.9.4.4.20';
+export const LICENSE_LEGACY_CREATOR = '6.2.9.4.4.30';
-const getExtensionValue = (clientCrt, extension) => {
- return clientCrt.extensions.find((ext) => ext.id === extension)?.value;
+const getExtensionValue = (clientCrt, standardOid, legacyOid) => {
+ const extStandard = clientCrt.extensions.find((ext) => ext.id === standardOid);
+ if (extStandard) {
+ return extStandard.value;
+ }
+ return clientCrt.extensions.find((ext) => ext.id === legacyOid)?.value;
};
export const getEnterpriseEditionActivePem = (rawPem) => {
@@ -47,10 +55,10 @@ export const getEnterpriseEditionInfoFromPem = (platformInstanceId, rawPem) => {
try {
const clientCrt = forge.pki.certificateFromPem(pem);
const license_valid_cert = OPENCTI_CA.verify(clientCrt);
- const license_type = getExtensionValue(clientCrt, LICENSE_OPTION_TYPE);
+ const license_type = getExtensionValue(clientCrt, LICENSE_OID_TYPE, LICENSE_LEGACY_TYPE);
const valid_type = IS_LTS_PLATFORM ? license_type === LICENSE_OPTION_LTS : true;
- const license_creator = getExtensionValue(clientCrt, LICENSE_OPTION_CREATOR);
- const valid_product = getExtensionValue(clientCrt, LICENSE_OPTION_PRODUCT) === 'opencti';
+ const license_creator = getExtensionValue(clientCrt, LICENSE_OID_CREATOR, LICENSE_LEGACY_CREATOR);
+ const valid_product = getExtensionValue(clientCrt, LICENSE_OID_PRODUCT, LICENSE_LEGACY_PRODUCT) === 'opencti';
const license_customer = clientCrt.subject.getField('O').value;
const license_platform = clientCrt.subject.getField('OU').value;
const license_platform_match = valid_product && valid_type && (license_platform === GLOBAL_LICENSE_OPTION || platformInstanceId === license_platform);
@@ -66,7 +74,7 @@ export const getEnterpriseEditionInfoFromPem = (platformInstanceId, rawPem) => {
// If trial license, deactivation for expiration is direct
if (license_type !== LICENSE_OPTION_TRIAL) {
// If standard or lts license, a 3 months safe period is granted
- const license_extra_expiration_date = utcDate(clientCrt.validity.notBefore).add(3, 'months');
+ const license_extra_expiration_date = utcDate(clientCrt.validity.notAfter).add(3, 'months');
license_extra_expiration_days = license_extra_expiration_date.diff(utcDate(), 'days');
license_extra_expiration = new Date() < license_extra_expiration_date.toDate();
license_validated = license_extra_expiration;
From be4ab13c30d154adc3cfc49ba128b2039b93e348 Mon Sep 17 00:00:00 2001
From: Filigran Automation
Date: Sun, 4 Jan 2026 20:32:10 +0000
Subject: [PATCH 022/126] [backend/worker] Release 6.9.5
---
client-python/pycti/__init__.py | 2 +-
opencti-platform/opencti-front/package.json | 2 +-
opencti-platform/opencti-graphql/package.json | 2 +-
opencti-platform/opencti-graphql/src/python/requirements.txt | 2 +-
opencti-worker/src/requirements.txt | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/client-python/pycti/__init__.py b/client-python/pycti/__init__.py
index 911bde893f33..48efbce349e7 100644
--- a/client-python/pycti/__init__.py
+++ b/client-python/pycti/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-__version__ = "6.9.4"
+__version__ = "6.9.5"
from .api.opencti_api_client import OpenCTIApiClient
from .api.opencti_api_connector import OpenCTIApiConnector
diff --git a/opencti-platform/opencti-front/package.json b/opencti-platform/opencti-front/package.json
index 7b175f71c8bf..0356d1985da9 100644
--- a/opencti-platform/opencti-front/package.json
+++ b/opencti-platform/opencti-front/package.json
@@ -1,6 +1,6 @@
{
"name": "opencti-front",
- "version": "6.9.4",
+ "version": "6.9.5",
"private": true,
"workspaces": [
"packages/*"
diff --git a/opencti-platform/opencti-graphql/package.json b/opencti-platform/opencti-graphql/package.json
index ecba8b2b95d0..a2cf0c3e7ae4 100644
--- a/opencti-platform/opencti-graphql/package.json
+++ b/opencti-platform/opencti-graphql/package.json
@@ -1,6 +1,6 @@
{
"name": "opencti-graphql",
- "version": "6.9.4",
+ "version": "6.9.5",
"private": true,
"scripts": {
"check-ts": "tsc --noEmit",
diff --git a/opencti-platform/opencti-graphql/src/python/requirements.txt b/opencti-platform/opencti-graphql/src/python/requirements.txt
index f39a15695b6f..f11e54d1106b 100644
--- a/opencti-platform/opencti-graphql/src/python/requirements.txt
+++ b/opencti-platform/opencti-graphql/src/python/requirements.txt
@@ -1,4 +1,4 @@
-pycti==6.9.4
+pycti==6.9.5
parsuricata==0.4.1
yara-python==4.5.2
sigmatools==0.23.1
diff --git a/opencti-worker/src/requirements.txt b/opencti-worker/src/requirements.txt
index 2e66bcb7e013..17b88b1ba9b5 100644
--- a/opencti-worker/src/requirements.txt
+++ b/opencti-worker/src/requirements.txt
@@ -1,4 +1,4 @@
-pycti==6.9.4
+pycti==6.9.5
opentelemetry-api~=1.35.0
opentelemetry-sdk~=1.35.0
opentelemetry-exporter-prometheus==0.56b0
From 65db32317844eefe7f8840dd768fbc942f9b7ddd Mon Sep 17 00:00:00 2001
From: Archidoit <75783086+Archidoit@users.noreply.github.com>
Date: Mon, 5 Jan 2026 09:58:18 +0100
Subject: [PATCH 023/126] [frontend] Add has-label in relationship type filter
values for knowledge widgets (#13837)
---
.../src/private/components/widgets/WidgetFilters.tsx | 2 +-
.../src/utils/filters/useSearchEntities.tsx | 12 ++++++++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/opencti-platform/opencti-front/src/private/components/widgets/WidgetFilters.tsx b/opencti-platform/opencti-front/src/private/components/widgets/WidgetFilters.tsx
index c2dcc1bb8cf4..6a9a83268f4e 100644
--- a/opencti-platform/opencti-front/src/private/components/widgets/WidgetFilters.tsx
+++ b/opencti-platform/opencti-front/src/private/components/widgets/WidgetFilters.tsx
@@ -34,7 +34,7 @@ const WidgetFilters: FunctionComponent = ({ perspective, typ
let availableEntityTypes;
let searchContext;
if (perspective === 'relationships') {
- searchContext = { entityTypes: ['stix-core-relationship', 'stix-sighting-relationship', 'contains'] };
+ searchContext = { entityTypes: ['stix-core-relationship', 'stix-sighting-relationship', 'contains', 'object-label'] };
} else if (perspective === 'audits') {
availableEntityTypes = ['History', 'Activity'];
searchContext = { entityTypes: ['History'] };
diff --git a/opencti-platform/opencti-front/src/utils/filters/useSearchEntities.tsx b/opencti-platform/opencti-front/src/utils/filters/useSearchEntities.tsx
index 7d71ce2b2cc0..bf5078d67122 100644
--- a/opencti-platform/opencti-front/src/utils/filters/useSearchEntities.tsx
+++ b/opencti-platform/opencti-front/src/utils/filters/useSearchEntities.tsx
@@ -325,6 +325,11 @@ const useSearchEntities = ({
value: 'object',
type: 'stix-internal-relationship',
};
+ const labelRelationshipType = {
+ label: t_i18n('relationship_object-label'),
+ value: 'objectLabel',
+ type: 'stix-meta-relationship',
+ };
const unionSetEntities = (key: string, newEntities: EntityValue[]) => setEntities((c) => ({
...c,
@@ -918,6 +923,7 @@ const useSearchEntities = ({
...scrTypes,
abstractTypeFilterValue('stix-sighting-relationship'),
objectRelationshipType,
+ labelRelationshipType,
];
} else { // display relationship types according to searchContext.entityTypes
const { entityTypes } = searchContext;
@@ -936,6 +942,12 @@ const useSearchEntities = ({
objectRelationshipType,
];
}
+ if (entityTypes.includes('object-label')) {
+ relationshipsTypes = [
+ ...relationshipsTypes,
+ labelRelationshipType,
+ ];
+ }
}
unionSetEntities(filterKey, relationshipsTypes.sort((a, b) => a.label.localeCompare(b.label)));
break;
From 54e5d5a06ca747765afad6918a48eca8d3b15daf Mon Sep 17 00:00:00 2001
From: Archidoit <75783086+Archidoit@users.noreply.github.com>
Date: Mon, 5 Jan 2026 10:30:05 +0100
Subject: [PATCH 024/126] [frontend] ai powered label and tooltip in CE
(#13810)
---
.../opencti-front/lang/front/de.json | 8 +-
.../opencti-front/lang/front/en.json | 8 +-
.../opencti-front/lang/front/es.json | 8 +-
.../opencti-front/lang/front/fr.json | 8 +-
.../opencti-front/lang/front/it.json | 8 +-
.../opencti-front/lang/front/ja.json | 8 +-
.../opencti-front/lang/front/ko.json | 8 +-
.../opencti-front/lang/front/ru.json | 8 +-
.../opencti-front/lang/front/zh.json | 8 +-
.../common/entreprise_edition/EEChip.tsx | 74 +++++++++----------
.../private/components/settings/Settings.tsx | 33 +++++++--
11 files changed, 106 insertions(+), 73 deletions(-)
diff --git a/opencti-platform/opencti-front/lang/front/de.json b/opencti-platform/opencti-front/lang/front/de.json
index bc4403d0e1db..923285063042 100644
--- a/opencti-platform/opencti-front/lang/front/de.json
+++ b/opencti-platform/opencti-front/lang/front/de.json
@@ -195,6 +195,7 @@
"Agentic AI (Ariane Assistant)": "Agentische KI (Ariane-Assistent)",
"Agentic AI capabilities": "Agentische KI-Fähigkeiten",
"AI Insights": "AI-Einblicke",
+ "AI is not enabled": "AI ist nicht aktiviert",
"AI Powered": "KI-gesteuert",
"AI Summary": "AI Zusammenfassung",
"alert_GROUP_WITH_NULL_CONFIDENCE_LEVEL": "Beginnend mit OpenCTI 6.0 wird ein maximales Vertrauensniveau für Gruppen und Benutzer hinzugefügt. Damit haben Plattformadministratoren eine bessere Kontrolle über die Auswirkungen importierter Daten und können unerwünschte Datenaktualisierungen verhindern. Bitte lesen Sie {link_blogpost} für weitere Informationen.\n \nAuf dieser Plattform sind \"Max Confidence Level\" einiger Gruppen derzeit undefiniert. Deren Mitglieder können in der Version 6.X der Plattform keine Daten erstellen. Um dies zu verhindern, stellen Sie sicher, dass für alle Gruppen eine maximale Vertrauensstufe festgelegt ist. Mehr dazu in {link_blogpost}. Achten Sie besonders auf Benutzer, die mit Connectors, Feeds und Streams verbunden sind; Sie können die individuelle Vertrauensstufe so einstellen, dass sie die Gruppen-Vertrauensstufe überschreibt, wenn dies erforderlich ist. Treten Sie {link_slack} bei, wenn Sie Ratschläge benötigen.",
@@ -1918,12 +1919,12 @@
"Heatmap": "Heatmap",
"Height": "Größe",
"here": "hier",
+ "Hidden": "Versteckt",
"Hidden entity types": "Ausgeblendete Entitätstypen",
"Hidden in ": "Versteckt in",
"Hidden in groups": "Versteckt in Gruppen",
"Hidden in interface": "Versteckt in der Schnittstelle",
"Hidden in organizations": "Versteckt in Organisationen",
- "Hidden": "Versteckt",
"Hide": "Ausblenden",
"Hide column": "Spalte ausblenden",
"Hide entities in container": "Entitäten im Container ausblenden",
@@ -3802,8 +3803,8 @@
"text/markdown": "MD",
"text/plain": "TXT",
"Textarea": "Textarea",
- "Thank you!": "Vielen Dank!",
"Thank you for reaching out, we'll get back to you shortly.": "Vielen Dank für Ihre Anfrage, wir werden Sie in Kürze kontaktieren.",
+ "Thank you!": "Vielen Dank!",
"The alias has been added": "Der Alias wurde hinzugefügt",
"The alias has been removed": "Der Alias wurde entfernt",
"The amount of results can differ based on the data/relationships, as each occurrence of an inferred relation is counted for this widget.": "Die Anzahl der Ergebnisse kann je nach Daten/Beziehungen unterschiedlich sein, da jedes Auftreten einer abgeleiteten Beziehung für dieses Widget gezählt wird.",
@@ -4515,6 +4516,7 @@
"You need to enable EE License to use this feature": "Sie müssen die EE-Lizenz aktivieren, um diese Funktion nutzen zu können",
"You need to validate your two-factor authentication. Please type the code generated in your application": "Sie müssen Ihre Zwei-Faktor-Authentifizierung validieren. Bitte geben Sie den in Ihrer Anwendung generierten Code ein.",
"You see only marking definitions that can be shared (defined by the admin)": "Sie sehen nur Markierungsdefinitionen, die freigegeben werden können (vom Administrator definiert)",
+ "You should activate EE to use this feature": "Sie sollten EE aktivieren, um diese Funktion zu nutzen",
"You should provide a variable name": "Sie sollten einen Variablennamen angeben",
"You will be able to revert this change if needed. ": "Sie können diese Änderung bei Bedarf rückgängig machen.",
"You will be automatically logged out at end of the timer.": "Sie werden nach Ablauf der Zeit automatisch abgemeldet.",
@@ -4541,4 +4543,4 @@
"Zoom": "Vergrößern",
"Zoom in": "Vergrößern",
"Zoom out": "Verkleinern"
-}
+}
\ No newline at end of file
diff --git a/opencti-platform/opencti-front/lang/front/en.json b/opencti-platform/opencti-front/lang/front/en.json
index e44082d12643..501ef2781757 100644
--- a/opencti-platform/opencti-front/lang/front/en.json
+++ b/opencti-platform/opencti-front/lang/front/en.json
@@ -195,6 +195,7 @@
"Agentic AI (Ariane Assistant)": "Agentic AI (Ariane Assistant)",
"Agentic AI capabilities": "Agentic AI capabilities",
"AI Insights": "AI Insights",
+ "AI is not enabled": "AI is not enabled",
"AI Powered": "AI Powered",
"AI Summary": "AI Summary",
"alert_GROUP_WITH_NULL_CONFIDENCE_LEVEL": "Starting with OpenCTI 6.0, a Max Confidence Level will be added to groups and users. It will provide platform administrators with more control on the impact of imported data and prevent any unwanted update on data. Please read {link_blogpost} for more information.\n \nOn this platform, \"Max Confidence Level\" of some groups are currently undefined. Their members will not be able to create any data in version 6.X of the platform. In order to prevent that, make sure that all groups have a Max Confidence Level set. More info in {link_blogpost}. Be particularly mindful of users associated to Connectors, Feeds and Streams; you can set individual confidence level to override group confidence level if needed. Join {link_slack} if you need advices.",
@@ -1918,12 +1919,12 @@
"Heatmap": "Heatmap",
"Height": "Height",
"here": "here",
+ "Hidden": "Hidden",
"Hidden entity types": "Hidden entity types",
"Hidden in ": "Hidden in ",
"Hidden in groups": "Hidden in groups",
"Hidden in interface": "Hidden in interface",
"Hidden in organizations": "Hidden in organizations",
- "Hidden": "Hidden",
"Hide": "Hide",
"Hide column": "Hide column",
"Hide entities in container": "Hide entities in container",
@@ -3802,8 +3803,8 @@
"text/markdown": "MD",
"text/plain": "TXT",
"Textarea": "Textarea",
- "Thank you!": "Thank you!",
"Thank you for reaching out, we'll get back to you shortly.": "Thank you for reaching out, we'll get back to you shortly.",
+ "Thank you!": "Thank you!",
"The alias has been added": "The alias has been added",
"The alias has been removed": "The alias has been removed",
"The amount of results can differ based on the data/relationships, as each occurrence of an inferred relation is counted for this widget.": "The amount of results can differ based on the data/relationships, as each occurrence of an inferred relation is counted for this widget.",
@@ -4515,6 +4516,7 @@
"You need to enable EE License to use this feature": "You need to enable EE License to use this feature",
"You need to validate your two-factor authentication. Please type the code generated in your application": "You need to validate your two-factor authentication. Please type the code generated in your application.",
"You see only marking definitions that can be shared (defined by the admin)": "You see only marking definitions that can be shared (defined by the admin)",
+ "You should activate EE to use this feature": "You should activate EE to use this feature",
"You should provide a variable name": "You should provide a variable name",
"You will be able to revert this change if needed. ": "You will be able to revert this change if needed. ",
"You will be automatically logged out at end of the timer.": "You will be automatically logged out at end of the timer.",
@@ -4541,4 +4543,4 @@
"Zoom": "Zoom",
"Zoom in": "Zoom in",
"Zoom out": "Zoom out"
-}
+}
\ No newline at end of file
diff --git a/opencti-platform/opencti-front/lang/front/es.json b/opencti-platform/opencti-front/lang/front/es.json
index 54b746bdf0ce..ee0f39cd46a3 100644
--- a/opencti-platform/opencti-front/lang/front/es.json
+++ b/opencti-platform/opencti-front/lang/front/es.json
@@ -195,6 +195,7 @@
"Agentic AI (Ariane Assistant)": "IA Agenética (Asistente Ariane)",
"Agentic AI capabilities": "Capacidades de IA agéntica",
"AI Insights": "AI Insights",
+ "AI is not enabled": "La IA no está activada",
"AI Powered": "AI Powered",
"AI Summary": "Resumen AI",
"alert_GROUP_WITH_NULL_CONFIDENCE_LEVEL": "A partir de OpenCTI 6.0, se añadirá un nivel de confianza máximo a los grupos y usuarios. Proporcionará a los administradores de la plataforma un mayor control sobre el impacto de los datos importados y evitará cualquier actualización no deseada de los datos. Lea {link_blogpost} para obtener más información.\n \nEn esta plataforma, \"el nivel máximo de confianza\" de algunos grupos no están definidos actualmente. Sus miembros no podrán crear ningún dato en la versión 6.X de la plataforma. Para evitarlo, asegúrate de que todos los grupos tienen un nivel de confianza máximo definido. Más información en {link_blogpost}. Ten especial cuidado con los usuarios asociados a Conectores, Feeds y Streams; puedes establecer el nivel de confianza individual para anular el nivel de confianza de grupo si es necesario. Únete a {link_slack} si necesitas consejos.",
@@ -1918,12 +1919,12 @@
"Heatmap": "Mapa de calor",
"Height": "Altura",
"here": "aquí",
+ "Hidden": "¿Escondido",
"Hidden entity types": "Tipos de entidad ocultos",
"Hidden in ": "Oculto en ",
"Hidden in groups": "Oculto en grupos",
"Hidden in interface": "Oculto en la interfaz",
"Hidden in organizations": "Oculto en las organizaciones",
- "Hidden": "¿Escondido",
"Hide": "Ocultar",
"Hide column": "Ocultar columna",
"Hide entities in container": "Ocultar entidades en el contenedor",
@@ -3802,8 +3803,8 @@
"text/markdown": "MD",
"text/plain": "TXT",
"Textarea": "Área de texto",
- "Thank you!": "¡Gracias!",
"Thank you for reaching out, we'll get back to you shortly.": "¡Gracias por contactarnos, te responderemos lo antes posible!",
+ "Thank you!": "¡Gracias!",
"The alias has been added": "El alias has sido añadido",
"The alias has been removed": "El alias ha sido eliminado",
"The amount of results can differ based on the data/relationships, as each occurrence of an inferred relation is counted for this widget.": "La cantidad de resultados puede variar en función de los datos/relaciones, ya que cada aparición de una relación inferida se cuenta para este widget.",
@@ -4515,6 +4516,7 @@
"You need to enable EE License to use this feature": "Debe activar la licencia EE para utilizar esta función",
"You need to validate your two-factor authentication. Please type the code generated in your application": "Debe validar su autenticación de dos factores. Por favor, escriba el código generado en su aplicación.",
"You see only marking definitions that can be shared (defined by the admin)": "Sólo se ven las definiciones de marcado que se pueden compartir (definidas por el administrador)",
+ "You should activate EE to use this feature": "Debe activar EE para utilizar esta función",
"You should provide a variable name": "Debes proporcionar un nombre de variable",
"You will be able to revert this change if needed. ": "Podrás revertir este cambio si es necesario.",
"You will be automatically logged out at end of the timer.": "Se cerrará la sesión automáticamente al final del temporizador.",
@@ -4541,4 +4543,4 @@
"Zoom": "Zoom",
"Zoom in": "Ampliar",
"Zoom out": "Alejar"
-}
+}
\ No newline at end of file
diff --git a/opencti-platform/opencti-front/lang/front/fr.json b/opencti-platform/opencti-front/lang/front/fr.json
index 6cfd0ec4e59e..4fbb93364246 100644
--- a/opencti-platform/opencti-front/lang/front/fr.json
+++ b/opencti-platform/opencti-front/lang/front/fr.json
@@ -195,6 +195,7 @@
"Agentic AI (Ariane Assistant)": "IA agentique (assistant Ariane)",
"Agentic AI capabilities": "Capacités de l'IA agentique",
"AI Insights": "Aperçu par AI",
+ "AI is not enabled": "L'IA n'est pas activée",
"AI Powered": "AI Powered",
"AI Summary": "Résumé AI",
"alert_GROUP_WITH_NULL_CONFIDENCE_LEVEL": "À partir d'OpenCTI 6.0, un niveau de confiance maximal sera ajouté aux groupes et aux utilisateurs. Cela permettra aux administrateurs de la plateforme de mieux contrôler l'impact des données importées et d'éviter toute mise à jour indésirable des données. Veuillez lire {link_blogpost} pour plus d'informations.\n \nSur cette plateforme, le niveau de confiance maximum de certains groupes est actuellement indéfini. Leurs membres ne pourront pas créer de données dans la version 6.X de la plateforme. Pour éviter cela, assurez-vous que tous les groupes ont un niveau de confiance maximum défini. Plus d'informations dans {link_blogpost}. Soyez particulièrement attentif aux utilisateurs associés aux connecteurs, aux streams et aux feeds ; vous pouvez définir un niveau de confiance individuel pour remplacer le niveau de confiance du groupe si nécessaire. Rejoignez {link_slack} si vous avez besoin de conseils.",
@@ -1918,12 +1919,12 @@
"Heatmap": "Carte de chaleur",
"Height": "Hauteur",
"here": "ici",
+ "Hidden": "Caché",
"Hidden entity types": "Types d'entité cachés",
"Hidden in ": "Caché dans ",
"Hidden in groups": "Caché dans les groupes",
"Hidden in interface": "Caché dans l'interface",
"Hidden in organizations": "Caché dans les organisations",
- "Hidden": "Caché",
"Hide": "Cacher",
"Hide column": "Masquer la colonne",
"Hide entities in container": "Cacher les entités dans le conteneur",
@@ -3802,8 +3803,8 @@
"text/markdown": "MD",
"text/plain": "TXT",
"Textarea": "Zone de texte",
- "Thank you!": "Merci!",
"Thank you for reaching out, we'll get back to you shortly.": "Merci d'avoir contacté notre équipe, nous vous répondrons dans les plus brefs délais.",
+ "Thank you!": "Merci!",
"The alias has been added": "L'alias a bien été ajouté",
"The alias has been removed": "L'alias a été supprimé",
"The amount of results can differ based on the data/relationships, as each occurrence of an inferred relation is counted for this widget.": "Le nombre de résultats peut varier en fonction des données/relations, car chaque occurrence d'une relation déduite est comptée pour ce widget.",
@@ -4515,6 +4516,7 @@
"You need to enable EE License to use this feature": "Vous devez activer la licence EE pour utiliser cette fonction",
"You need to validate your two-factor authentication. Please type the code generated in your application": "Vous devez valider votre authentification à deux facteurs. Veuillez saisir le code généré dans votre application.",
"You see only marking definitions that can be shared (defined by the admin)": "Vous ne voyez que les définitions de marquage qui peuvent être partagées (définies par l'administrateur)",
+ "You should activate EE to use this feature": "Vous devez activer l'EE pour utiliser cette fonction",
"You should provide a variable name": "Vous devez fournir un nom de variable",
"You will be able to revert this change if needed. ": "Vous pourrez revenir sur cette modification si nécessaire.",
"You will be automatically logged out at end of the timer.": "Vous serez automatiquement déconnecté à la fin du décompte.",
@@ -4541,4 +4543,4 @@
"Zoom": "Zoom",
"Zoom in": "Zoomer",
"Zoom out": "Zoom arrière"
-}
+}
\ No newline at end of file
diff --git a/opencti-platform/opencti-front/lang/front/it.json b/opencti-platform/opencti-front/lang/front/it.json
index 3c9eaf3d8811..a07f2bb00329 100644
--- a/opencti-platform/opencti-front/lang/front/it.json
+++ b/opencti-platform/opencti-front/lang/front/it.json
@@ -195,6 +195,7 @@
"Agentic AI (Ariane Assistant)": "IA agenziale (Assistente Arianna)",
"Agentic AI capabilities": "Funzionalità di IA agenziale",
"AI Insights": "AI Insights",
+ "AI is not enabled": "L'intelligenza artificiale non è abilitata",
"AI Powered": "AI Powered",
"AI Summary": "AI Summary",
"alert_GROUP_WITH_NULL_CONFIDENCE_LEVEL": "A partire da OpenCTI 6.0, verrà aggiunto un livello di fiducia massimo ai gruppi e agli utenti. Questo permetterà agli amministratori della piattaforma di avere un maggiore controllo sull'impatto dei dati importati e di prevenire aggiornamenti indesiderati sui dati. Per maggiori informazioni, consultare {link_blogpost}.\n\nSu questa piattaforma, il \"Livello di Fiducia Massimo\" di alcuni gruppi non è attualmente definito. I loro membri non potranno creare dati nella versione 6.X della piattaforma. Per evitare questo problema, assicurati che tutti i gruppi abbiano un livello di fiducia massimo impostato. Più informazioni su {link_blogpost}. Presta particolare attenzione agli utenti associati a Connettori, Feed e Stream; se necessario, puoi impostare un livello di fiducia individuale per sovrascrivere quello del gruppo. Unisciti a {link_slack} se hai bisogno di consigli.",
@@ -1918,12 +1919,12 @@
"Heatmap": "Mappa di calore",
"Height": "Altezza",
"here": "qui",
+ "Hidden": "Nascosto",
"Hidden entity types": "Tipi di entità nascosti",
"Hidden in ": "Nascosto in ",
"Hidden in groups": "Nascosto nei gruppi",
"Hidden in interface": "Nascosto nell'interfaccia",
"Hidden in organizations": "Nascosto nelle organizzazioni",
- "Hidden": "Nascosto",
"Hide": "Nascondi",
"Hide column": "Nascondi colonna",
"Hide entities in container": "Nascondi entità nel contenitore",
@@ -3802,8 +3803,8 @@
"text/markdown": "MD",
"text/plain": "TXT",
"Textarea": "Area di testo",
- "Thank you!": "Grazie!",
"Thank you for reaching out, we'll get back to you shortly.": "Grazie per averci contattato, ti risponderemo a breve.",
+ "Thank you!": "Grazie!",
"The alias has been added": "L'alias è stato aggiunto",
"The alias has been removed": "L'alias è stato rimosso",
"The amount of results can differ based on the data/relationships, as each occurrence of an inferred relation is counted for this widget.": "La quantità di risultati può variare in base ai dati/alle relazioni, poiché ogni occorrenza di una relazione dedotta viene contata per questo widget.",
@@ -4515,6 +4516,7 @@
"You need to enable EE License to use this feature": "È necessario abilitare la licenza EE per utilizzare questa funzione",
"You need to validate your two-factor authentication. Please type the code generated in your application": "Devi convalidare la tua autenticazione a due fattori. Inserisci il codice generato nella tua applicazione.",
"You see only marking definitions that can be shared (defined by the admin)": "Vedi solo le definizioni di marcatura che possono essere condivise (definite dall'amministratore)",
+ "You should activate EE to use this feature": "È necessario attivare EE per utilizzare questa funzione",
"You should provide a variable name": "Dovresti fornire un nome per la variabile",
"You will be able to revert this change if needed. ": "Sarà possibile ripristinare questa modifica se necessario.",
"You will be automatically logged out at end of the timer.": "Verrai disconnesso automaticamente alla fine del timer.",
@@ -4541,4 +4543,4 @@
"Zoom": "Zoom",
"Zoom in": "Ingrandisci",
"Zoom out": "Riduci"
-}
+}
\ No newline at end of file
diff --git a/opencti-platform/opencti-front/lang/front/ja.json b/opencti-platform/opencti-front/lang/front/ja.json
index d7499f0484e9..856cc95f8e36 100644
--- a/opencti-platform/opencti-front/lang/front/ja.json
+++ b/opencti-platform/opencti-front/lang/front/ja.json
@@ -195,6 +195,7 @@
"Agentic AI (Ariane Assistant)": "エージェント型AI(アリアン・アシスタント)",
"Agentic AI capabilities": "エージェントAIの能力",
"AI Insights": "AIインサイト",
+ "AI is not enabled": "AIは有効ではない",
"AI Powered": "AI搭載",
"AI Summary": "AIサマリー",
"alert_GROUP_WITH_NULL_CONFIDENCE_LEVEL": "OpenCTI 6.0 から、グループとユーザーに最大信頼度が追加されます。これにより、プラットフォーム管理者はインポートされたデータの影響をよりコントロールできるようになり、データの不要な更新を防ぐことができます。詳しくは{link_blogpost}をお読みください。\n \nこのプラットフォームでは、いくつかのグループの最大信頼度が現在未定義です。そのグループのメンバーはバージョン6.Xではデータを作成することができません。これを防ぐには、すべてのグループに最大信頼度が設定されていることを確認してください。詳細は{link_blogpost}を参照してください。コネクター、フィード、ストリームに関連するユーザーには特に注意してください。必要であれば、グループの信頼度よりも個人の信頼度を優先して設定できます。アドバイスが必要な場合は{link_slack}に参加してください。",
@@ -1918,12 +1919,12 @@
"Heatmap": "ヒートマップ",
"Height": "身長",
"here": "ここ",
+ "Hidden": "隠された",
"Hidden entity types": "非表示のエンティティ種別",
"Hidden in ": "に隠されています",
"Hidden in groups": "グループに隠れている",
"Hidden in interface": "インターフェイスに隠されている",
"Hidden in organizations": "組織に隠れて",
- "Hidden": "隠された",
"Hide": "隠す",
"Hide column": "列を隠す",
"Hide entities in container": "コンテナ内のエンティティを隠す",
@@ -3802,8 +3803,8 @@
"text/markdown": "MD",
"text/plain": "TXT",
"Textarea": "テキストエリア",
- "Thank you!": "ありがとうございます!",
"Thank you for reaching out, we'll get back to you shortly.": "ご連絡ありがとうございます。ご連絡を承りました。",
+ "Thank you!": "ありがとうございます!",
"The alias has been added": "別名を追加しました",
"The alias has been removed": "エイリアスは削除されました",
"The amount of results can differ based on the data/relationships, as each occurrence of an inferred relation is counted for this widget.": "推論された関係の各出現がこのウィジェットのためにカウントされるので,結果の量は,データ/関係によって異なる可能性がある.",
@@ -4515,6 +4516,7 @@
"You need to enable EE License to use this feature": "この機能を使用するには、EEライセンスを有効にする必要があります。",
"You need to validate your two-factor authentication. Please type the code generated in your application": "二要素認証を検証する必要があります。アプリケーションで生成されたコードを入力してください。",
"You see only marking definitions that can be shared (defined by the admin)": "共有可能な(管理者によって定義された)マーキング定義のみが表示されます。",
+ "You should activate EE to use this feature": "この機能を使用するにはEEを有効にする必要がある",
"You should provide a variable name": "変数名を指定してください",
"You will be able to revert this change if needed. ": "必要に応じて、この変更を元に戻すことができます。",
"You will be automatically logged out at end of the timer.": "タイマーが終了すると自動的にログアウトされます",
@@ -4541,4 +4543,4 @@
"Zoom": "ズーム",
"Zoom in": "ズームイン",
"Zoom out": "ズームアウト"
-}
+}
\ No newline at end of file
diff --git a/opencti-platform/opencti-front/lang/front/ko.json b/opencti-platform/opencti-front/lang/front/ko.json
index d2cd009e4a03..49b29c8a7a47 100644
--- a/opencti-platform/opencti-front/lang/front/ko.json
+++ b/opencti-platform/opencti-front/lang/front/ko.json
@@ -195,6 +195,7 @@
"Agentic AI (Ariane Assistant)": "에이전트 AI(아리안 어시스턴트)",
"Agentic AI capabilities": "에이전트 AI 기능",
"AI Insights": "AI 인사이트",
+ "AI is not enabled": "AI가 활성화되지 않았습니다",
"AI Powered": "AI 지원",
"AI Summary": "AI 요약",
"alert_GROUP_WITH_NULL_CONFIDENCE_LEVEL": "OpenCTI 6.0부터 그룹과 사용자에게 최대 신뢰 수준이 추가됩니다. 이는 플랫폼 관리자에게 가져온 데이터의 영향을 더 많이 제어할 수 있도록 하며 데이터의 원치 않는 업데이트를 방지합니다. 자세한 내용은 {link_blogpost}을(를) 참조하십시오.\n \n이 플랫폼에서는 일부 그룹의 '최대 신뢰 수준'이 현재 정의되지 않았습니다. 그들의 멤버는 플랫폼의 버전 6.X에서 데이터를 생성할 수 없습니다. 이를 방지하려면 모든 그룹에 최대 신뢰 수준이 설정되어 있는지 확인하십시오. 자세한 내용은 {link_blogpost}을 참조하십시오. 커넥터, 피드 및 스트림과 연결된 사용자에 특히 주의해야 합니다. 필요 시 개별 신뢰 수준을 설정하여 그룹 신뢰 수준을 재정의할 수 있습니다. 도움이 필요하면 {link_slack}에 참여하십시오.",
@@ -1918,12 +1919,12 @@
"Heatmap": "히트맵",
"Height": "키",
"here": "여기",
+ "Hidden": "숨겨져 있나요",
"Hidden entity types": "숨겨진 엔터티 유형",
"Hidden in ": "숨겨진 ",
"Hidden in groups": "그룹에서 숨겨짐",
"Hidden in interface": "인터페이스에서 숨겨짐",
"Hidden in organizations": "조직에서 숨겨짐",
- "Hidden": "숨겨져 있나요",
"Hide": "숨기기",
"Hide column": "열 숨기기",
"Hide entities in container": "컨테이너에서 엔티티 숨기기",
@@ -3802,8 +3803,8 @@
"text/markdown": "MD",
"text/plain": "TXT",
"Textarea": "텍스트 영역",
- "Thank you!": "감사합니다!",
"Thank you for reaching out, we'll get back to you shortly.": "감사합니다. 곧 연락드리겠습니다.",
+ "Thank you!": "감사합니다!",
"The alias has been added": "별명이 추가되었습니다",
"The alias has been removed": "별명이 제거되었습니다",
"The amount of results can differ based on the data/relationships, as each occurrence of an inferred relation is counted for this widget.": "이 위젯에서는 추론된 관계가 발생할 때마다 계산되므로 결과의 양은 데이터/관계에 따라 달라질 수 있습니다.",
@@ -4515,6 +4516,7 @@
"You need to enable EE License to use this feature": "이 기능을 사용하려면 EE 라이선스를 활성화해야 합니다",
"You need to validate your two-factor authentication. Please type the code generated in your application": "이중 인증을 검증해야 합니다. 애플리케이션에서 생성된 코드를 입력하십시오",
"You see only marking definitions that can be shared (defined by the admin)": "공유할 수 있는 마킹 정의만 표시됩니다 (관리자가 정의한 것)",
+ "You should activate EE to use this feature": "이 기능을 사용하려면 EE를 활성화해야 합니다",
"You should provide a variable name": "변수 이름을 입력해야 합니다",
"You will be able to revert this change if needed. ": "필요한 경우 이 변경 사항을 되돌릴 수 있습니다.",
"You will be automatically logged out at end of the timer.": "타이머가 끝나면 자동으로 로그아웃됩니다.",
@@ -4541,4 +4543,4 @@
"Zoom": "확대/축소",
"Zoom in": "확대",
"Zoom out": "축소"
-}
+}
\ No newline at end of file
diff --git a/opencti-platform/opencti-front/lang/front/ru.json b/opencti-platform/opencti-front/lang/front/ru.json
index 7b4effa552e3..bfc8145dbf69 100644
--- a/opencti-platform/opencti-front/lang/front/ru.json
+++ b/opencti-platform/opencti-front/lang/front/ru.json
@@ -195,6 +195,7 @@
"Agentic AI (Ariane Assistant)": "Агентный искусственный интеллект (помощник Ариана)",
"Agentic AI capabilities": "Возможности агентного ИИ",
"AI Insights": "Инсайты ИИ",
+ "AI is not enabled": "ИИ не включен",
"AI Powered": "На базе ИИ",
"AI Summary": "Краткое резюме ИИ",
"alert_GROUP_WITH_NULL_CONFIDENCE_LEVEL": "alert_GROUP_WITH_NULL_CONFIDENCE_LEVEL",
@@ -1918,12 +1919,12 @@
"Heatmap": "Тепловая карта",
"Height": "Высота",
"here": "здесь",
+ "Hidden": "Скрытый",
"Hidden entity types": "Скрытые типы сущностей",
"Hidden in ": "Скрыто в",
"Hidden in groups": "Скрытые в группах",
"Hidden in interface": "Скрыто в интерфейсе",
"Hidden in organizations": "Скрытые в организациях",
- "Hidden": "Скрытый",
"Hide": "Скрыть",
"Hide column": "Скрыть колонку",
"Hide entities in container": "Скрыть сущности в контейнере",
@@ -3802,8 +3803,8 @@
"text/markdown": "текст/маркдаун",
"text/plain": "текст/plain",
"Textarea": "Textarea",
- "Thank you!": "Спасибо!",
"Thank you for reaching out, we'll get back to you shortly.": "Спасибо за обращение, мы скоро вам ответим.",
+ "Thank you!": "Спасибо!",
"The alias has been added": "Псевдоним был добавлен",
"The alias has been removed": "Псевдоним был удален",
"The amount of results can differ based on the data/relationships, as each occurrence of an inferred relation is counted for this widget.": "Количество результатов может отличаться в зависимости от данных/отношений, поскольку для этого виджета учитывается каждое появление предполагаемого отношения.",
@@ -4515,6 +4516,7 @@
"You need to enable EE License to use this feature": "Для использования этой функции необходимо включить лицензию EE License.",
"You need to validate your two-factor authentication. Please type the code generated in your application": "Вам необходимо подтвердить двухфакторную аутентификацию. Пожалуйста, введите код, сгенерированный в вашем приложении",
"You see only marking definitions that can be shared (defined by the admin)": "Вы видите только те определения маркировки, которые могут быть доступны (определены администратором).",
+ "You should activate EE to use this feature": "Чтобы использовать эту функцию, необходимо активировать EE",
"You should provide a variable name": "Вы должны указать имя переменной",
"You will be able to revert this change if needed. ": "При необходимости вы сможете отменить это изменение.",
"You will be automatically logged out at end of the timer.": "По окончании таймера вы автоматически выйдете из системы.",
@@ -4541,4 +4543,4 @@
"Zoom": "Zoom",
"Zoom in": "Увеличить",
"Zoom out": "Уменьшить масштаб"
-}
+}
\ No newline at end of file
diff --git a/opencti-platform/opencti-front/lang/front/zh.json b/opencti-platform/opencti-front/lang/front/zh.json
index e20b23409590..e0078c387a95 100644
--- a/opencti-platform/opencti-front/lang/front/zh.json
+++ b/opencti-platform/opencti-front/lang/front/zh.json
@@ -195,6 +195,7 @@
"Agentic AI (Ariane Assistant)": "人工智能代理(阿丽亚娜助理)",
"Agentic AI capabilities": "人工智能代理能力",
"AI Insights": "人工智能洞察",
+ "AI is not enabled": "未启用人工智能",
"AI Powered": "人工智能技术",
"AI Summary": "人工智能摘要",
"alert_GROUP_WITH_NULL_CONFIDENCE_LEVEL": "从 OpenCTI 6.0 开始,将为组和用户添加最大置信度。这将为平台管理员提供更多对导入数据影响的控制,并防止任何不必要的数据更新。请阅读 {link_blogpost} 获取更多信息。\n \n在本平台中,某些组的 \"Max Confidence Level\" 目前未定义。这些组的成员将无法在 6.X 版平台中创建任何数据。为避免出现这种情况,请确保所有组都设置了最大置信度。更多信息请参见 {link_blogpost}。请特别注意与连接器、馈送和数据流相关联的用户;必要时,您可以设置个人置信度来覆盖组置信度。如果需要建议,请加入 {link_slack} 。",
@@ -1918,12 +1919,12 @@
"Heatmap": "热图",
"Height": "高度",
"here": "这里",
+ "Hidden": "隐藏",
"Hidden entity types": "隐藏的实体类型",
"Hidden in ": "隐藏在",
"Hidden in groups": "隐藏在群体中",
"Hidden in interface": "隐藏在界面中",
"Hidden in organizations": "隐藏在组织中",
- "Hidden": "隐藏",
"Hide": "隐藏",
"Hide column": "隐藏栏",
"Hide entities in container": "隐藏容器中的实体",
@@ -3802,8 +3803,8 @@
"text/markdown": "MD",
"text/plain": "TXT",
"Textarea": "文本区域",
- "Thank you!": "感谢您的联系",
"Thank you for reaching out, we'll get back to you shortly.": "感谢您的联系,我们会尽快回复您。",
+ "Thank you!": "感谢您的联系",
"The alias has been added": "别名已添加",
"The alias has been removed": "别名已删除",
"The amount of results can differ based on the data/relationships, as each occurrence of an inferred relation is counted for this widget.": "结果的数量可能因数据/关系而异,因为推断关系的每次出现都会计入该 widget 中。",
@@ -4515,6 +4516,7 @@
"You need to enable EE License to use this feature": "您需要启用 EE 许可才能使用此功能",
"You need to validate your two-factor authentication. Please type the code generated in your application": "您需要验证您的双因素身份验证。请输入在您的应用程序中生成的代码。",
"You see only marking definitions that can be shared (defined by the admin)": "您只能看到可以共享的标记定义(由管理员定义)",
+ "You should activate EE to use this feature": "您应激活 EE 才能使用此功能",
"You should provide a variable name": "您应该提供一个变量名",
"You will be able to revert this change if needed. ": "如果需要,您可以恢复这一更改。",
"You will be automatically logged out at end of the timer.": "计时器结束时您将自动注销",
@@ -4541,4 +4543,4 @@
"Zoom": "放大",
"Zoom in": "放大",
"Zoom out": "缩小"
-}
+}
\ No newline at end of file
diff --git a/opencti-platform/opencti-front/src/private/components/common/entreprise_edition/EEChip.tsx b/opencti-platform/opencti-front/src/private/components/common/entreprise_edition/EEChip.tsx
index 3d4411ff1832..06e31344f70a 100644
--- a/opencti-platform/opencti-front/src/private/components/common/entreprise_edition/EEChip.tsx
+++ b/opencti-platform/opencti-front/src/private/components/common/entreprise_edition/EEChip.tsx
@@ -1,5 +1,4 @@
-import makeStyles from '@mui/styles/makeStyles';
-import React, { MouseEvent, useState } from 'react';
+import React, { CSSProperties, MouseEvent, useState } from 'react';
import FeedbackCreation from '@components/cases/feedbacks/FeedbackCreation';
import EnterpriseEditionAgreement from '@components/common/entreprise_edition/EnterpriseEditionAgreement';
import { useFormatter } from '../../../../components/i18n';
@@ -7,45 +6,11 @@ import type { Theme } from '../../../../components/Theme';
import useEnterpriseEdition from '../../../../utils/hooks/useEnterpriseEdition';
import useGranted, { SETTINGS_SETPARAMETERS } from '../../../../utils/hooks/useGranted';
import useAuth from '../../../../utils/hooks/useAuth';
-
-// Deprecated - https://mui.com/system/styles/basics/
-// Do not use it for new code.
-const useStyles = makeStyles((theme) => ({
- container: {
- fontSize: 'xx-small',
- height: 18,
- display: 'inline-flex',
- justifyContent: 'center',
- alignItems: 'center',
- width: 21,
- margin: 'auto',
- marginLeft: 6,
- borderRadius: theme.borderRadius,
- border: `1px solid ${theme.palette.ee.main}`,
- color: theme.palette.ee.main,
- backgroundColor: theme.palette.ee.background,
- cursor: 'pointer',
- },
- containerFloating: {
- float: 'left',
- fontSize: 'xx-small',
- height: 18,
- display: 'inline-flex',
- justifyContent: 'center',
- alignItems: 'center',
- width: 21,
- margin: '2px 0 0 6px',
- borderRadius: theme.borderRadius,
- border: `1px solid ${theme.palette.ee.main}`,
- color: theme.palette.ee.main,
- backgroundColor: theme.palette.ee.background,
- cursor: 'pointer',
- },
-}));
+import { useTheme } from '@mui/material/styles';
const EEChip = React.forwardRef(({ feature, clickable = true, floating = false }, ref) => {
- const classes = useStyles();
const isEnterpriseEdition = useEnterpriseEdition();
+ const theme = useTheme();
const { t_i18n } = useFormatter();
const [displayDialog, setDisplayDialog] = useState(false);
const isAdmin = useGranted([SETTINGS_SETPARAMETERS]);
@@ -56,12 +21,43 @@ const EEChip = React.forwardRef
onClick(e)}
>
EE
diff --git a/opencti-platform/opencti-front/src/private/components/settings/Settings.tsx b/opencti-platform/opencti-front/src/private/components/settings/Settings.tsx
index 13277a4f856d..e268eb60dbed 100644
--- a/opencti-platform/opencti-front/src/private/components/settings/Settings.tsx
+++ b/opencti-platform/opencti-front/src/private/components/settings/Settings.tsx
@@ -211,6 +211,23 @@ const SettingsComponent = ({ queryRef }: SettingsComponentProps) => {
setTitle(t_i18n('Parameters | Settings'));
+ // generate AI Powered label and tooltip
+ let aiPoweredLabel;
+ let aiPoweredTooltip;
+ if (!isEnterpriseEditionValid) {
+ aiPoweredLabel = t_i18n('Disabled');
+ aiPoweredTooltip = t_i18n('You should activate EE to use this feature');
+ } else if (!settings.platform_ai_enabled) {
+ aiPoweredLabel = t_i18n('Disabled');
+ aiPoweredTooltip = t_i18n('AI is not enabled');
+ } else if (settings.platform_ai_has_token) {
+ aiPoweredLabel = settings.platform_ai_type;
+ aiPoweredTooltip = `${settings.platform_ai_type} - ${settings.platform_ai_model}`;
+ } else {
+ aiPoweredLabel = `${settings.platform_ai_type} - ${t_i18n('Missing token')}`;
+ aiPoweredTooltip = t_i18n('The token is missing in your platform configuration, please ask your Filigran representative to provide you with it or with on-premise deployment instructions. Your can open a support ticket to do so.');
+ };
+
const settingsValidation = () => Yup.object().shape({
platform_title: Yup.string().required(t_i18n('This field is required')),
platform_favicon: Yup.string().nullable(),
@@ -688,16 +705,18 @@ const SettingsComponent = ({ queryRef }: SettingsComponentProps) => {
+ {t_i18n('AI Powered')}
+
+ >
+ )}
/>
From a6e5357db6012b75a7bad205065104bfb2511f40 Mon Sep 17 00:00:00 2001
From: Landry Trebon <33682259+lndrtrbn@users.noreply.github.com>
Date: Mon, 5 Jan 2026 11:47:49 +0100
Subject: [PATCH 025/126] [frontend] Move component KillchainPhasesField to
Typescript (#13845)
---
.../arsenal/tools/ToolEditionOverview.tsx | 1 -
.../common/form/KillChainPhasesField.jsx | 96 ----------------
.../common/form/KillChainPhasesField.tsx | 106 ++++++++++++++++++
.../StixCoreRelationshipEditionOverview.tsx | 3 +-
.../PlaybookActionValueField.tsx | 4 +-
.../InfrastructureEditionOverview.tsx | 1 -
.../opencti-front/src/utils/field.tsx | 7 --
7 files changed, 109 insertions(+), 109 deletions(-)
delete mode 100644 opencti-platform/opencti-front/src/private/components/common/form/KillChainPhasesField.jsx
create mode 100644 opencti-platform/opencti-front/src/private/components/common/form/KillChainPhasesField.tsx
diff --git a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.tsx b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.tsx
index dbcdc80e1aa7..31795aa15112 100644
--- a/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.tsx
+++ b/opencti-platform/opencti-front/src/private/components/arsenal/tools/ToolEditionOverview.tsx
@@ -280,7 +280,6 @@ const ToolEditionOverview: FunctionComponent = ({
}
onChange={editor.changeKillChainPhases}
diff --git a/opencti-platform/opencti-front/src/private/components/common/form/KillChainPhasesField.jsx b/opencti-platform/opencti-front/src/private/components/common/form/KillChainPhasesField.jsx
deleted file mode 100644
index f84ec32c9ac3..000000000000
--- a/opencti-platform/opencti-front/src/private/components/common/form/KillChainPhasesField.jsx
+++ /dev/null
@@ -1,96 +0,0 @@
-import React, { Component } from 'react';
-import { compose, pathOr, pipe, map, sortWith, ascend, path, union } from 'ramda';
-import { Field } from 'formik';
-import withStyles from '@mui/styles/withStyles';
-import { fetchQuery } from '../../../../relay/environment';
-import AutocompleteField from '../../../../components/AutocompleteField';
-import inject18n from '../../../../components/i18n';
-import { killChainPhasesSearchQuery } from '../../settings/KillChainPhases';
-import ItemIcon from '../../../../components/ItemIcon';
-
-const styles = () => ({
- icon: {
- paddingTop: 4,
- display: 'inline-block',
- },
- text: {
- display: 'inline-block',
- flexGrow: 1,
- marginLeft: 10,
- },
-});
-
-class KillChainPhasesField extends Component {
- constructor(props) {
- super(props);
- this.state = {
- killChainPhases: [],
- };
- }
-
- searchKillChainPhases(event) {
- fetchQuery(killChainPhasesSearchQuery, {
- search: event && event.target.value,
- })
- .toPromise()
- .then((data) => {
- const killChainPhases = pipe(
- pathOr([], ['killChainPhases', 'edges']),
- sortWith([ascend(path(['node', 'x_opencti_order']))]),
- map((n) => ({
- label: `[${n.node.kill_chain_name}] ${n.node.phase_name}`,
- value: n.node.id,
- kill_chain_name: n.node.kill_chain_name,
- phase_name: n.node.phase_name,
- })),
- )(data);
- this.setState({
- killChainPhases: union(this.state.killChainPhases, killChainPhases),
- });
- });
- }
-
- render() {
- const {
- t,
- name,
- style,
- classes,
- onChange,
- helpertext,
- disabled,
- required = false,
- } = this.props;
- return (
- (
-
-
-
-
- {option.label}
-
- )}
- />
- );
- }
-}
-
-export default compose(inject18n, withStyles(styles))(KillChainPhasesField);
diff --git a/opencti-platform/opencti-front/src/private/components/common/form/KillChainPhasesField.tsx b/opencti-platform/opencti-front/src/private/components/common/form/KillChainPhasesField.tsx
new file mode 100644
index 000000000000..6ca07a6db1f8
--- /dev/null
+++ b/opencti-platform/opencti-front/src/private/components/common/form/KillChainPhasesField.tsx
@@ -0,0 +1,106 @@
+import { CSSProperties, HTMLAttributes, ReactNode, SyntheticEvent, useState } from 'react';
+import { union } from 'ramda';
+import { Field } from 'formik';
+import { fetchQuery } from '../../../../relay/environment';
+import AutocompleteField from '../../../../components/AutocompleteField';
+import { killChainPhasesSearchQuery } from '../../settings/KillChainPhases';
+import ItemIcon from '../../../../components/ItemIcon';
+import { useFormatter } from '../../../../components/i18n';
+import { FieldOption } from '../../../../utils/field';
+import { KillChainPhasesSearchQuery$data } from '../../settings/__generated__/KillChainPhasesSearchQuery.graphql';
+import { getNodes } from '../../../../utils/connection';
+
+interface KillChainPhaseFieldOption extends FieldOption {
+ kill_chain_name: string;
+ phase_name: string;
+}
+
+interface KillChainPhasesFieldProps {
+ name: string;
+ onChange?: (name: string, value: KillChainPhaseFieldOption[]) => void;
+ style?: CSSProperties;
+ helpertext?: ReactNode;
+ disabled?: boolean;
+ required?: boolean;
+}
+
+const KillChainPhasesField = ({
+ style,
+ name,
+ onChange,
+ helpertext,
+ disabled,
+ required = false,
+}: KillChainPhasesFieldProps) => {
+ const { t_i18n } = useFormatter();
+ const [killChainPhases, setKillChainPhases] = useState([]);
+
+ const searchKillChainPhases = (event?: SyntheticEvent) => {
+ if (event?.target instanceof HTMLInputElement) {
+ const search = event.target.value ?? '';
+ fetchQuery(killChainPhasesSearchQuery, { search })
+ .toPromise()
+ .then((data) => {
+ const dataNodes = getNodes((data as KillChainPhasesSearchQuery$data).killChainPhases);
+ dataNodes.sort((a, b) => (a.x_opencti_order ?? 0) - (b.x_opencti_order ?? 0));
+ const kcp = dataNodes.map((node) => {
+ return {
+ label: `[${node.kill_chain_name}] ${node.phase_name}`,
+ value: node.id,
+ kill_chain_name: node.kill_chain_name,
+ phase_name: node.phase_name,
+ };
+ });
+ setKillChainPhases(union(killChainPhases, kcp));
+ });
+ }
+ };
+
+ return (
+ ,
+ option: KillChainPhaseFieldOption,
+ ) => (
+
+
+
+
+ {option.label}
+
+
+ )}
+ />
+ );
+};
+
+export default KillChainPhasesField;
diff --git a/opencti-platform/opencti-front/src/private/components/common/stix_core_relationships/StixCoreRelationshipEditionOverview.tsx b/opencti-platform/opencti-front/src/private/components/common/stix_core_relationships/StixCoreRelationshipEditionOverview.tsx
index b9888835ed28..25b422740c9f 100644
--- a/opencti-platform/opencti-front/src/private/components/common/stix_core_relationships/StixCoreRelationshipEditionOverview.tsx
+++ b/opencti-platform/opencti-front/src/private/components/common/stix_core_relationships/StixCoreRelationshipEditionOverview.tsx
@@ -420,7 +420,6 @@ const StixCoreRelationshipEditionOverviewComponent: FunctionComponent<
;
}
- // eslint-disable-next-line max-len
+
const stixCoreRelationship = useFragment(
StixCoreRelationshipEditionOverviewFragment,
queryData.stixCoreRelationship,
diff --git a/opencti-platform/opencti-front/src/private/components/data/playbooks/playbookFlow/playbookFlowFields/playbookFlowFieldsActions/PlaybookActionValueField.tsx b/opencti-platform/opencti-front/src/private/components/data/playbooks/playbookFlow/playbookFlowFields/playbookFlowFieldsActions/PlaybookActionValueField.tsx
index 3c6954375b09..d521a8374bfb 100644
--- a/opencti-platform/opencti-front/src/private/components/data/playbooks/playbookFlow/playbookFlowFields/playbookFlowFieldsActions/PlaybookActionValueField.tsx
+++ b/opencti-platform/opencti-front/src/private/components/data/playbooks/playbookFlow/playbookFlowFields/playbookFlowFieldsActions/PlaybookActionValueField.tsx
@@ -15,7 +15,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import { Field, useFormikContext } from 'formik';
import SwitchField from '../../../../../../../components/fields/SwitchField';
-import { FieldOption, KillChainPhaseFieldOption } from '../../../../../../../utils/field';
+import { FieldOption } from '../../../../../../../utils/field';
import { isEmptyField } from '../../../../../../../utils/utils';
import CreatedByField from '../../../../../common/form/CreatedByField';
import KillChainPhasesField from '../../../../../common/form/KillChainPhasesField';
@@ -250,7 +250,7 @@ const PlaybookActionValueField = ({
return (
{
+ onChange={(_, killChainPhases) => {
setFieldValue(
valueName,
killChainPhases.map((kcp) => ({
diff --git a/opencti-platform/opencti-front/src/private/components/observations/infrastructures/InfrastructureEditionOverview.tsx b/opencti-platform/opencti-front/src/private/components/observations/infrastructures/InfrastructureEditionOverview.tsx
index 2e4e790c046f..eae0d4b6106f 100644
--- a/opencti-platform/opencti-front/src/private/components/observations/infrastructures/InfrastructureEditionOverview.tsx
+++ b/opencti-platform/opencti-front/src/private/components/observations/infrastructures/InfrastructureEditionOverview.tsx
@@ -347,7 +347,6 @@ const InfrastructureEditionOverviewComponent: FunctionComponent = Omit, 'component' | 'as' | 'render' | 'children'>;
type NoMetaProps = Omit
;
type FieldProps = FormikFieldConfig & NoMetaProps & {
From c365f61fb957c592ac955c8fb610d7c3aedcf17b Mon Sep 17 00:00:00 2001
From: "A. Jard"
Date: Mon, 5 Jan 2026 12:58:03 +0100
Subject: [PATCH 026/126] [docs] update documentation on yarn command for tests
(#13317)
---
docs/docs/development/platform.md | 151 ++++++++++++++++--------------
1 file changed, 83 insertions(+), 68 deletions(-)
diff --git a/docs/docs/development/platform.md b/docs/docs/development/platform.md
index abb80571b3af..5d42fa5167b5 100644
--- a/docs/docs/development/platform.md
+++ b/docs/docs/development/platform.md
@@ -34,20 +34,6 @@ Fork and clone the git repositories
- [https://github.com/OpenCTI-Platform/opencti/](https://github.com/OpenCTI-Platform/opencti/) - frontend / backend
- [https://github.com/OpenCTI-Platform/connectors](https://github.com/OpenCTI-Platform/connectors) - connectors
-- [https://github.com/OpenCTI-Platform/docker](https://github.com/OpenCTI-Platform/docker) - docker stack
-
-## Dependencies containers
-
-In development dependencies are deployed trough containers.
-A development compose file is available in `~/opencti/opencti-platform/opencti-dev`
-
-```bash
-cd ~/docker
-#Start the stack in background
-docker-compose -f ./docker-compose-dev.yml up -d
-```
-
-You now have all the dependencies of OpenCTI running and waiting for product to run.
## Backend / API
@@ -86,9 +72,28 @@ At minimum adapt the admin part for the password and token.
}
```
-### Install / start
+### Install / start OpenCTI for development
+
+For development setup, you need to run both the backend and frontend.
-Before starting the backend you need to install the nodejs modules
+#### Start infrastructure with docker composer
+
+```bash
+cd ~/opencti/opencti-platform/opencti-dev
+docker compose up -d
+```
+
+You should have:
+- elasticsearch
+- kibana
+- redis
+- redis insight
+- rabbitmq
+- minio
+
+#### Start backend
+
+Before starting the backend you need to install the nodejs modules and be sure to have started docker compose stack.
```bash
cd ~/opencti/opencti-platform/opencti-graphql
@@ -114,23 +119,61 @@ The platform will start logging some interesting information
{"category":"APP","level":"info","message":"[OPENCTI] API ready on port 4000","timestamp":"2023-07-02T16:37:12.382Z","version":"5.8.7"}
```
-If you want to start on another profile you can use the -e parameter.
-For example here to use the profile.json configuration file.
+OpenCTI api should be now up and running on [http://127.0.0.1:4000](http://127.0.0.1:4000). Note that without frontend started only api call are avlaible. Please follow next section for a complete development setup.
+
+#### Start frontend
+
+Before starting the frontend you need to install.
+
+```bash
+cd ~/opencti/opencti-platform/opencti-front
+yarn install
+```
+
+Then you can start the frontend
```bash
-yarn start -e profile
+cd ~/opencti/opencti-platform/opencti-front
+yarn start
```
+
+OpenCTI should be now up and running on [http://127.0.0.1:3000](http://127.0.0.1:3000)
+
+The frontend will start with some interesting information
+
+```log
+[INFO] [default] compiling...
+[INFO] [default] compiled documents: 1592 reader, 1072 normalization, 1596 operation text
+[INFO] Compilation completed.
+[INFO] Done.
+[HPM] Proxy created: /stream -> http://localhost:4000
+[HPM] Proxy created: /storage -> http://localhost:4000
+[HPM] Proxy created: /taxii2 -> http://localhost:4000
+[HPM] Proxy created: /feeds -> http://localhost:4000
+[HPM] Proxy created: /graphql -> http://localhost:4000
+[HPM] Proxy created: /auth/** -> http://localhost:4000
+[HPM] Proxy created: /static/flags/** -> http://localhost:4000
+```
+
### Code check
Before pushing your code you need to validate the syntax and ensure the testing will be validated.
#### For validation
-`yarn lint`
+```bash
+cd ~/opencti/opencti-platform/opencti-front
+yarn lint
+yarn check-ts
+
+cd ~/opencti/opencti-platform/opencti-graphql
+yarn lint
+yarn check-ts
+```
-`yarn check-ts`
+### For testing
-#### For testing
+#### Backend tests
For starting the test you will need to create a test.json configuration file.
You can use the same dependencies by only adapting all prefix for all dependencies.
@@ -144,68 +187,40 @@ The file `vitest.config.test.ts` can be edited to run only a specific file patte
`yarn test:dev`
We also provide utility scripts to ease the development of new tests, especially integration tests that rely on the sample data
-loaded after executing `00-inject/loader-test.ts`.
+loaded after executing `tests/02-dataInjection`.
To solely initialize the test database with this sample dataset run:
`yarn test:dev:init`
-And then, execute the following command to run the pattern specified in the file `vitest.config.test.ts`, or add a file name
-to the command line to run only this test file.
+And then, execute the following command to run only this test file.
-`yarn test:dev:resume`
+`yarn test:dev:resume `
This last command will NOT cleanup & initialize the test database and thus will be quicker to execute.
-## Frontend
-
-### Install / start
-
-Before starting the backend you need to install the nodejs modules
+Some yarn command are made for CI but can be used locally too:
```bash
-cd ~/opencti/opencti-platform/opencti-front
-yarn install
-```
+cd ~/opencti/opencti-platform/opencti-graphql
-Then you can simply start the frontend with the yarn start command
+# Run unit tests, no need for elastic or redis
+yarn test:ci-unit
-```bash
-cd ~/opencti/opencti-platform/opencti-front
-yarn start
-```
+# Run data injection + integration domain & resolvers test, but not sync part
+yarn test:ci-integration
-The frontend will start with some interesting information
+# Run data injection + integration domain & resolvers test, including sync part
+yarn test:ci-integration-sync
-```log
-[INFO] [default] compiling...
-[INFO] [default] compiled documents: 1592 reader, 1072 normalization, 1596 operation text
-[INFO] Compilation completed.
-[INFO] Done.
-[HPM] Proxy created: /stream -> http://localhost:4000
-[HPM] Proxy created: /storage -> http://localhost:4000
-[HPM] Proxy created: /taxii2 -> http://localhost:4000
-[HPM] Proxy created: /feeds -> http://localhost:4000
-[HPM] Proxy created: /graphql -> http://localhost:4000
-[HPM] Proxy created: /auth/** -> http://localhost:4000
-[HPM] Proxy created: /static/flags/** -> http://localhost:4000
+# Run data injection + rule tests
+test:ci-rules-and-others
```
+Those command works also for a single file, for example to run only one unit test:
-The web UI should be accessible on [http://127.0.0.1:3000](http://127.0.0.1:3000)
-
-### Code check
-
-Before pushing your code you need to validate the syntax and ensure the testing will be validated.
-
-#### For validation
-
-`yarn lint`
-
-`yarn check-ts`
-
-#### For testing
-
-`yarn test`
+```bash
+yarn test:ci-unit
+```
## Worker
@@ -264,4 +279,4 @@ The Pull Request on ***opencti*** repository should be (issue or bug)/number + o
The pull request on ***connector*** should refer to the opencti one by starting with "opencti/" and then the same name. Example: `opencti/issue/7062-contributing`
-Note that if there are several matches, the first one is taken. So for example having `issue/7062-contributing` and `issue/7062` that are both marked as "multi-repository" is not a good idea.
+Note that if there are several matches, the first one is taken. So for example having `issue/7062-contributing` and `issue/7062` that are both marked as "multi-repository" is not a good idea.
\ No newline at end of file
From 5621343f80042b9f3882c844411b0e7203b962a0 Mon Sep 17 00:00:00 2001
From: hervyt
Date: Mon, 5 Jan 2026 14:21:28 +0100
Subject: [PATCH 027/126] [frontend/backend] - (TaxiiFeeds) Add import/export
of taxii feeds #13848
---
docs/docs/usage/assets/taxii-feeds-export.png | Bin 0 -> 35960 bytes
.../usage/assets/taxii-feeds-import-icon.png | Bin 0 -> 17409 bytes
docs/docs/usage/import/taxii-feed.md | 17 ++
.../opencti-front/lang/front/de.json | 2 +
.../opencti-front/lang/front/en.json | 2 +
.../opencti-front/lang/front/es.json | 2 +
.../opencti-front/lang/front/fr.json | 2 +
.../opencti-front/lang/front/it.json | 2 +
.../opencti-front/lang/front/ja.json | 2 +
.../opencti-front/lang/front/ko.json | 2 +
.../opencti-front/lang/front/ru.json | 2 +
.../opencti-front/lang/front/zh.json | 2 +
.../private/components/data/IngestionCsv.tsx | 2 +-
...ngestionTaxiis.jsx => IngestionTaxiis.tsx} | 58 ++++-
...reation.jsx => IngestionTaxiiCreation.tsx} | 237 ++++++++++--------
.../ingestionTaxii/IngestionTaxiiImport.tsx | 119 +++++++++
.../ingestionTaxii/IngestionTaxiiPopover.tsx | 36 ++-
.../src/schema/relay.schema.graphql | 13 +
.../opencti-graphql/src/generated/graphql.ts | 35 +++
.../ingestion/ingestion-taxii-domain.ts | 46 +++-
.../ingestion/ingestion-taxii-resolver.ts | 4 +
.../modules/ingestion/ingestion-taxii.graphql | 15 ++
.../02-resolvers/ingestion-taxii-test.ts | 61 ++++-
.../tests/data/taxiiFeed/test-taxii-feed.json | 9 +
24 files changed, 550 insertions(+), 120 deletions(-)
create mode 100644 docs/docs/usage/assets/taxii-feeds-export.png
create mode 100644 docs/docs/usage/assets/taxii-feeds-import-icon.png
rename opencti-platform/opencti-front/src/private/components/data/{IngestionTaxiis.jsx => IngestionTaxiis.tsx} (63%)
rename opencti-platform/opencti-front/src/private/components/data/ingestionTaxii/{IngestionTaxiiCreation.jsx => IngestionTaxiiCreation.tsx} (54%)
create mode 100644 opencti-platform/opencti-front/src/private/components/data/ingestionTaxii/IngestionTaxiiImport.tsx
create mode 100644 opencti-platform/opencti-graphql/tests/data/taxiiFeed/test-taxii-feed.json
diff --git a/docs/docs/usage/assets/taxii-feeds-export.png b/docs/docs/usage/assets/taxii-feeds-export.png
new file mode 100644
index 0000000000000000000000000000000000000000..3b25993b64417eeeca0a0a3b87788a9f3e6a822a
GIT binary patch
literal 35960
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