Skip to content

Commit 2cb4539

Browse files
committed
[backend] Allow escape function in safeEjs for Simple Mailer templates (#13753)
1 parent b21a404 commit 2cb4539

File tree

6 files changed

+173
-46
lines changed

6 files changed

+173
-46
lines changed

.readthedocs.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ build:
99
os: ubuntu-22.04
1010
tools:
1111
python: "3.12"
12+
apt_packages:
13+
- graphviz
1214

1315
# Build documentation in the client-python/docs/ directory with Sphinx
1416
sphinx:

client-python/docs/conf.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,26 @@ def get_version():
5656
"sphinx.ext.autodoc",
5757
"sphinx.ext.viewcode",
5858
"sphinx.ext.napoleon",
59+
"sphinx.ext.graphviz",
60+
"sphinx.ext.inheritance_diagram",
5961
"autoapi.extension",
6062
"sphinx_autodoc_typehints",
6163
]
6264

65+
# Graphviz configuration
66+
graphviz_output_format = "svg"
67+
inheritance_graph_attrs = {
68+
"rankdir": "TB",
69+
"size": '"6.0, 8.0"',
70+
}
71+
inheritance_node_attrs = {
72+
"shape": "box",
73+
"fontsize": 10,
74+
"height": 0.25,
75+
"style": '"setlinewidth(0.5),filled"',
76+
"fillcolor": "white",
77+
}
78+
6379
# Napoleon settings for Google/NumPy style docstrings
6480
napoleon_google_docstring = True
6581
napoleon_numpy_docstring = True
@@ -82,14 +98,17 @@ def get_version():
8298
"undoc-members",
8399
"show-inheritance",
84100
"show-module-summary",
85-
"imported-members",
101+
"special-members",
86102
]
87103
autoapi_python_class_content = (
88104
"both" # Include both class docstring and __init__ docstring
89105
)
90106
autoapi_member_order = "bysource"
91107
autoapi_keep_files = False
92108
autoapi_add_toctree_entry = True
109+
# Ignore top-level __init__.py to prevent "Undocumented" for re-exported classes
110+
# Classes will be documented in their original modules with proper docstrings
111+
autoapi_ignore = ["*/pycti/__init__.py"]
93112

94113
# Mock imports for modules that can't be installed on ReadTheDocs
95114
autodoc_mock_imports = [

client-python/docs/pycti/pycti.rst

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -24,52 +24,52 @@ Classes
2424
=======
2525

2626
- :py:class:`AttackPattern`:
27-
Undocumented.
27+
Main AttackPattern class for OpenCTI
2828

2929
- :py:class:`Campaign`:
30-
Undocumented.
30+
Main Campaign class for OpenCTI
3131

3232
- :py:class:`CaseIncident`:
33-
Undocumented.
33+
Main CaseIncident class for OpenCTI
3434

3535
- :py:class:`CaseRfi`:
36-
Undocumented.
36+
Main CaseRfi class for OpenCTI
3737

3838
- :py:class:`CaseRft`:
39-
Undocumented.
39+
Main CaseRft class for OpenCTI
4040

4141
- :py:class:`Channel`:
42-
Undocumented.
42+
Main Channel class for OpenCTI
4343

4444
- :py:class:`Task`:
45-
Undocumented.
45+
Main Task class for OpenCTI
4646

4747
- :py:class:`ConnectorType`:
4848
An enumeration.
4949

5050
- :py:class:`CourseOfAction`:
51-
Undocumented.
51+
Main CourseOfAction class for OpenCTI
5252

5353
- :py:class:`DataComponent`:
54-
Undocumented.
54+
Main DataComponent class for OpenCTI
5555

5656
- :py:class:`DataSource`:
57-
Undocumented.
57+
Main DataSource class for OpenCTI
5858

5959
- :py:class:`ExternalReference`:
60-
Undocumented.
60+
Main ExternalReference class for OpenCTI
6161

6262
- :py:class:`Feedback`:
63-
Undocumented.
63+
Main Feedback class for OpenCTI
6464

6565
- :py:class:`Grouping`:
66-
Undocumented.
66+
Main Grouping class for OpenCTI
6767

6868
- :py:class:`Identity`:
69-
Undocumented.
69+
Main Identity class for OpenCTI
7070

7171
- :py:class:`Incident`:
72-
Undocumented.
72+
Main Incident class for OpenCTI
7373

7474
- :py:class:`Indicator`:
7575
Main Indicator class for OpenCTI
@@ -78,40 +78,40 @@ Classes
7878
Main Infrastructure class for OpenCTI
7979

8080
- :py:class:`IntrusionSet`:
81-
Undocumented.
81+
Main IntrusionSet class for OpenCTI
8282

8383
- :py:class:`KillChainPhase`:
84-
Undocumented.
84+
Main KillChainPhase class for OpenCTI
8585

8686
- :py:class:`Label`:
87-
Undocumented.
87+
Main Label class for OpenCTI
8888

8989
- :py:class:`Location`:
90-
Undocumented.
90+
Main Location class for OpenCTI
9191

9292
- :py:class:`Malware`:
93-
Undocumented.
93+
Main Malware class for OpenCTI
9494

9595
- :py:class:`MalwareAnalysis`:
96-
Undocumented.
96+
Main MalwareAnalysis class for OpenCTI
9797

9898
- :py:class:`MarkingDefinition`:
99-
Undocumented.
99+
Main MarkingDefinition class for OpenCTI
100100

101101
- :py:class:`Note`:
102-
Undocumented.
102+
Main Note class for OpenCTI
103103

104104
- :py:class:`ObservedData`:
105-
Undocumented.
105+
Main ObservedData class for OpenCTI
106106

107107
- :py:class:`OpenCTIApiClient`:
108108
Main API client for OpenCTI
109109

110110
- :py:class:`OpenCTIApiConnector`:
111-
OpenCTIApiConnector
111+
OpenCTI API Connector client
112112

113113
- :py:class:`OpenCTIApiWork`:
114-
OpenCTIApiJob
114+
OpenCTI API Work client
115115

116116
- :py:class:`OpenCTIConnector`:
117117
Main class for OpenCTI connector
@@ -120,40 +120,40 @@ Classes
120120
Python API for OpenCTI connector
121121

122122
- :py:class:`OpenCTIMetricHandler`:
123-
Undocumented.
123+
Main OpenCTI Metric Handler class
124124

125125
- :py:class:`OpenCTIStix2`:
126126
Python API for Stix2 in OpenCTI
127127

128128
- :py:class:`OpenCTIStix2Splitter`:
129-
Undocumented.
129+
Main OpenCTI Stix2 Splitter class
130130

131131
- :py:class:`OpenCTIStix2Update`:
132132
Python API for Stix2 Update in OpenCTI
133133

134134
- :py:class:`OpenCTIStix2Utils`:
135-
Undocumented.
135+
Main OpenCTI Stix2 Utils class
136136

137137
- :py:class:`Opinion`:
138-
Undocumented.
138+
Main Opinion class for OpenCTI
139139

140140
- :py:class:`Report`:
141-
Undocumented.
141+
Main Report class for OpenCTI
142142

143143
- :py:class:`StixCoreRelationship`:
144-
Undocumented.
144+
Main StixCoreRelationship class for OpenCTI
145145

146146
- :py:class:`StixCyberObservable`:
147-
deprecated [>=6.2 & <6.5]`
147+
Deprecated StixCyberObservable class [>=6.2 & <6.5]
148148

149149
- :py:class:`StixNestedRefRelationship`:
150-
Undocumented.
150+
Main StixNestedRefRelationship class for OpenCTI
151151

152152
- :py:class:`StixCyberObservableTypes`:
153153
An enumeration.
154154

155155
- :py:class:`StixDomainObject`:
156-
Undocumented.
156+
Main StixDomainObject class for OpenCTI
157157

158158
- :py:class:`StixMetaTypes`:
159159
An enumeration.
@@ -162,10 +162,10 @@ Classes
162162
An enumeration.
163163

164164
- :py:class:`StixObjectOrStixRelationship`:
165-
Undocumented.
165+
Main StixObjectOrStixRelationship class for OpenCTI
166166

167167
- :py:class:`StixSightingRelationship`:
168-
Undocumented.
168+
Main StixSightingRelationship class for OpenCTI
169169

170170
- :py:class:`ThreatActor`:
171171
Main ThreatActor class for OpenCTI
@@ -177,10 +177,10 @@ Classes
177177
Main ThreatActorIndividual class for OpenCTI
178178

179179
- :py:class:`Tool`:
180-
Undocumented.
180+
Main Tool class for OpenCTI
181181

182182
- :py:class:`Vulnerability`:
183-
Undocumented.
183+
Main Vulnerability class for OpenCTI
184184

185185
- :py:class:`CustomObjectCaseIncident`:
186186
Case-Incident object.

client-python/pycti/utils/opencti_stix2.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,14 @@
4949
ERROR_TYPE_DRAFT_LOCK = "DRAFT_LOCKED"
5050
ERROR_TYPE_TIMEOUT = "Request timed out"
5151

52-
# Extensions
53-
STIX_EXT_OCTI = "extension-definition--ea279b3e-5c71-4632-ac08-831c66a786ba"
54-
STIX_EXT_OCTI_SCO = "extension-definition--f93e2c80-4231-4f9a-af8b-95c9bd566a82"
55-
STIX_EXT_MITRE = "extension-definition--322b8f77-262a-4cb8-a915-1e441e00329b"
52+
#: STIX Extension ID for OpenCTI custom objects and properties
53+
STIX_EXT_OCTI: str = "extension-definition--ea279b3e-5c71-4632-ac08-831c66a786ba"
54+
55+
#: STIX Extension ID for OpenCTI custom Cyber Observables (SCO)
56+
STIX_EXT_OCTI_SCO: str = "extension-definition--f93e2c80-4231-4f9a-af8b-95c9bd566a82"
57+
58+
#: STIX Extension ID for MITRE ATT&CK framework objects
59+
STIX_EXT_MITRE: str = "extension-definition--322b8f77-262a-4cb8-a915-1e441e00329b"
5660
PROCESSING_COUNT: int = 4
5761
MAX_PROCESSING_COUNT: int = 100
5862

opencti-platform/opencti-graphql/src/utils/safeEjs.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const authorizeGlobals = new Map<string, string | true>([
6969
['encodeURIComponent', true],
7070
['decodeURI', true],
7171
['decodeURIComponent', true],
72+
['escape', true],
7273
]);
7374

7475
const forbiddenGlobals = [
@@ -82,7 +83,10 @@ const forbiddenGlobals = [
8283

8384
const noop = () => {};
8485

85-
const createSafeContext = (async: boolean, { maxExecutedStatementCount = 0, maxExecutionDuration = 0, yieldMethod }: SafeOptions) => {
86+
const createSafeContext = (
87+
async: boolean,
88+
{ maxExecutedStatementCount = 0, maxExecutionDuration = 0, yieldMethod, escape }: SafeOptions & { escape?: (str: string) => string },
89+
) => {
8690
let executedStatementCount = 0;
8791
const checkMaxExecutedStatementCount = maxExecutedStatementCount > 0 ? () => {
8892
executedStatementCount += 1;
@@ -98,7 +102,7 @@ const createSafeContext = (async: boolean, { maxExecutedStatementCount = 0, maxE
98102
}
99103
} : noop;
100104

101-
return {
105+
const context: Record<string, unknown> = {
102106
[safeName('statement')]: async
103107
? async () => {
104108
checkMaxExecutedStatementCount();
@@ -140,6 +144,13 @@ const createSafeContext = (async: boolean, { maxExecutedStatementCount = 0, maxE
140144
},
141145
}),
142146
};
147+
148+
// If a custom escape function is provided, make it available in template context
149+
if (escape) {
150+
context.escape = escape;
151+
}
152+
153+
return context;
143154
};
144155

145156
const extractEJSCode = (template: string, openTag: string, closeTag: string) => {

0 commit comments

Comments
 (0)